Firebase云功能和Android推送通知

时间:2018-04-19 00:53:33

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

我有这个问题,我正在创建一个连接到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)

1 个答案:

答案 0 :(得分:0)

根据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功能失败,因此返回语句没有执行,也没有发送任何通知。

相关问题