[英]Firebase Cloud Functions and Android Push Notification
I have this problem, I am creating an android application that is connected to Firebase. 我遇到了这个问题,我正在创建一个连接到Firebase的android应用程序。 Then I have my Raspberry Pi connected to Firebase, the data sent from the Pi is GPS coordinates specifically latitude and longitude.
然后,我将Raspberry Pi连接到Firebase,从Pi发送的数据是GPS坐标,特别是纬度和经度。 The main application that I want to create has a Push Notification function when data on the Firebase has been changed or the coordinates on the main node has been changed.
当Firebase上的数据已更改或主节点上的坐标已更改时,我要创建的主应用程序具有“推送通知”功能。 Here is the screenshot of my Firebase Data:
这是我的Firebase数据的屏幕截图:
Firebase Database Screenshot Firebase数据库屏幕截图
My problem is this, the cloud function that I created has found errors that I don't understand or I'm just overseeing it. 我的问题是,我创建的云函数发现了我不理解的错误,或者我正在对其进行监督。 I've looked up in the Firebase documentation, sample codes from articles and I guess nothing just seemed to work for me.
我在Firebase文档中查找了文章中的示例代码,但我想似乎没有什么适合我。 Here is the code for the cloud function and the error I got when I just manually type in data in 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)
});
The next one is with the Android Application, even though my Firebase FCM is in the gradle:app, then I manually send a message in the Firebase console, the application doesn't receive any messages on the avd or phone installed with the app. 下一个是Android应用程序,即使我的Firebase FCM位于gradle:app中,我还是在Firebase控制台中手动发送了一条消息,该应用程序在随该应用程序安装的avd或手机上未收到任何消息。 Here's a code for my MessagingService to handle foreground notifications:
这是我的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());
}
}
Then here's my android manifest: 然后这是我的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>
This is my gradle:app 这是我的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'
Here's a the error that keeps on appearing: 这是一个不断出现的错误:
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)
As per the Firebase documentation for the onWrite method, it's passed: 根据Firebase有关onWrite方法的文档,它已通过:
a functions.Change containing a non-null functions.database.DataSnapshot and an optional non-null functions.EventContext )
一个functions.Change含有非空functions.database.DataSnapshot和一个可选的非空functions.EventContext )
However in your function you're expecting an event object, which results empty. 但是,在您的函数中,您需要一个事件对象,该事件对象为空。
Following the sample code available here , you could re-write your function like so: 按照此处提供的示例代码,您可以像这样重新编写函数:
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);
});
I haven't checked the Android issue you mentioned but I guess that since the Firebase Function was failing, the return statement didn't execute and no notification was sent at all. 我没有检查过您提到的Android问题,但是我猜想由于Firebase Function失败,所以return语句没有执行,也没有任何通知发送。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.