【问题标题】:Firebase Cloud Functions and Android Push NotificationFirebase 云函数和 Android 推送通知
【发布时间】:2018-09-29 08:46:28
【问题描述】:

我有这个问题,我正在创建一个连接到 Firebase 的 android 应用程序。然后我将 Raspberry Pi 连接到 Firebase,从 Pi 发送的数据是 GPS 坐标,特别是纬度和经度。当 Firebase 上的数据已更改或主节点上的坐标已更改时,我要创建的主应用程序具有推送通知功能。这是我的 Firebase 数据的屏幕截图:

Firebase Database Screenshot

我的问题是,我创建的云功能发现了我不理解的错误,或者我只是在监督它。我查看了 Firebase 文档、文章中的示例代码,我想似乎没有什么对我有用。这是云功能的代码,也是我在 Firebase 中手动输入数据时遇到的错误。

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.sendLocationNotification = functions.database.ref("/GPS/{gps_id}").onWrite((event)=>{

var latitude = event.data.child('latitude'); 

var longitude = event.data.child('longitude');        

if(!latitude.changed() && !longitude.changed()){

return console.log('The database has been reset');
    } 

const payload = {        
    notification:{            
            title: "Location Monitor",            
            body: "Your motorcycle has moved",            
            icon: "default",            
            sound: "default"
        }
    };


    const options = {        
            priority: "high",
            timeToLive: 60 * 60 * 24
    };

        return admin.messaging().sendToTopic("Location_Notification", payload, options)

});

下一个是 Android 应用程序,即使我的 Firebase FCM 在 gradle:app 中,然后我在 Firebase 控制台中手动发送一条消息,该应用程序在安装的 avd 或手机上没有收到任何消息应用程序。这是我的 MessagingService 处理前台通知的代码:

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

import java.util.Map;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "FirebaseMessgingService";

    @Override

    public void onMessageReceived(RemoteMessage remoteMessage){

        if(remoteMessage.getData().size()>0){
            Map<String, String> payload = remoteMessage.getData();

            showNotification(payload);

        }

    }

    private void showNotification(Map<String, String> payload) {

        Intent intent = new Intent(this, Tracking.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent, PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
                .setAutoCancel(true)
                .setSmallIcon(R.drawable.track)
                .setContentIntent(pendingIntent)
                .setContentTitle(payload.get("Title"))
                .setContentText(payload.get("Body"))
                .setSound(defaultSoundUri);

        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0,notificationBuilder.build());

    }

}

然后这是我的 android 清单:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="">

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Splash">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".Menu" />
        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/track"/>
        <service android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
        <activity
            android:name=".Tracking"
            android:label="@string/title_activity_tracking" />
        <activity
            android:name=".Tracing"
            android:label="@string/title_activity_tracing" />
        <activity android:name=".Tips" />
        <activity android:name=".Instruction" />
        <activity android:name=".About"></activity>
    </application>

</manifest>

这是我的 gradle:app

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId ""
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.google.android.gms:play-services-maps:11.0.4'
    implementation 'com.google.firebase:firebase-database:11.0.4'
    implementation 'com.google.firebase:firebase-messaging:11.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    compile 'com.github.Hitomis:CircleMenu:v1.1.0'
}


apply plugin: 'com.google.gms.google-services'

这是不断出现的错误:

TypeError: Cannot read property 'child' of undefined
    at exports.sendLocationNotification.functions.database.ref.onWrite (/user_code/index.js:13:30)
    at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27)
    at next (native)
    at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
    at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36)
    at /var/tmp/worker/worker.js:700:26
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)

【问题讨论】:

    标签: android firebase firebase-realtime-database push-notification google-cloud-functions


    【解决方案1】:

    根据 onWrite 方法的 Firebase 文档,它已通过:

    一个 functions.Change 包含一个非空 functions.database.DataSnapshot 和一个可选的非空 functions.EventContext)

    但是,在您的函数中,您需要一个事件对象,结果为空。

    按照可用的示例代码here,您可以像这样重写您的函数:

    exports.makeUppercase = functions.database.ref("/GPS/{gps_id}")
        .onWrite((change, context) => {
    
          // You can get the previous value for latitude and longitude
          var previousLatitude = change.before.ref.parent.child('latitude'); 
          var previousLongitude = change.before.ref.parent.child('longitude');
    
          // And the new values
          var newLatitude = change.after.ref.parent.child('latitude'); 
          var newLongitude = change.after.ref.parent.child('longitude');
    
          // And perform your logic from here
          ...
    
          return admin.messaging().sendToTopic("Location_Notification", payload, options);
        });
    

    我没有检查你提到的 Android 问题,但我猜由于 Firebase 函数失败,return 语句没有执行并且根本没有发送任何通知。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 2019-11-29
      相关资源
      最近更新 更多