簡體   English   中英

當應用程序未運行時處理 android 推送通知,如 whatsapp、twitter、facebook、instagram 等

[英]Handle android push notification when app is not running like whatsapp, twitter, facebook, instagram etc

我正在開發一個像whatsapp這樣的聊天應用程序。 當應用程序運行時,我使用 websocket 連接來處理兩個用戶之間的聊天但是當應用程序被殺死或未運行時,我嘗試使用 FCM 推送通知服務來通知用戶何時收到消息,就像 whatsapp 的方式一樣做。

現在的問題是,當應用程序處於前台或后台時(從視圖中被遮擋,但仍在最近的任務菜單中),FCM 會收到推送通知,一旦應用程序從最近的任務菜單中滑出或根本沒有啟動,沒有收到通知。

我已經在這里存貨了一整周,我已經搜索並閱讀了關於 github、stackoverflow、quora 和一些博客文章的各種文章和社區對話,但我還沒有找到有用的東西。

我嘗試使用后台服務來保持 websocket 與服務器的連接,但我無法讓服務繼續運行,因為 android 在應用程序不在前台時會關閉后台服務。

I mean how do apps like whatsapp, twitter, instagram, facebook, gmail, likee, tiktok etc handle push notification such that even though the app is closed (swiped out of recent menu or not started at all) it still notifies it's users of some服務器上的更新。

這是我的代碼...在服務器上

const firebase_admin = require('firebase-admin');
var service_account = require('./service_account.json');
firebase_admin.initializeApp({
    credential: firebase_admin.credential.cert(service_account),
    databaseURL: 'https://fcm_pushnotification-b9983.firebaseio.com/'
});

app.get('/sendPushNotification', (req, res) => {
    // This registration token comes from the client FCM SDKs.
    var registrationToken = 'clIilmqTRYarMF4gcrpEeH:APA91bFjkmZP7gU836ZCAzyPZaOWU4nU4SLL5OPWNkgukt0zBe0zvn5PEQ-42g60R5UXFN0tXQISjCDcbl032j2Tc81_OZ5uAJ7Aq3_OAaIz7g56oT547LnB9wiiBIKRZhc1TWGMP7lr';

    var message = {
        notification: {
            title: 'Samuel',
            body: 'This is an urgent message!',
        },
        webpush:{
            headers:{
                Urgency:'high'
            }
        },
        android:{
            priority:'high'
        },
        token: registrationToken
    };


    // Send a message to the device corresponding to the provided
    // registration token.
    firebase_admin.messaging().send(message)
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
        res.send('Successfully sent message:- '+ response);
      })
      .catch((error) => {
        console.log('Error sending message:- ', error);
        res.send('Error sending message:'+ error);
      });
});

我在 android 上的服務 class

public class MyFirebaseMessagingService extends FirebaseMessagingService{
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    @Override
    public void onNewToken(@NonNull String token) {
        Log.d(TAG, "Refreshed token: " + token);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        sendRegistrationToServer(token);
    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        String title = remoteMessage.getNotification().getTitle();
        String body = remoteMessage.getNotification().getBody();
        this.sendNotification(new Notification(null, title, body, 0));
    }

    private void sendNotification(Notification notification){
    // Notification channel and notification is build here.
    }

}

清單

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

        <service
            android:name=".Services.MyFirebaseMessagingService"
            android:exported="true">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
        </service>

 <!-- Set custom default icon. This is used when no icon is set for incoming notification messages. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_icon"
            android:resource="@drawable/ic_heart" />
        <!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
             notification message. -->
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_color"
            android:resource="@color/red" />
        <meta-data
            android:name="com.google.firebase.messaging.default_notification_channel_id"
            android:value="@string/notification_channel_id" />

當應用程序未運行時,我是否需要請求此權限才能工作。 我什至將服務器上的通知優先級設置為可以看到的最高級別。 我對此感到沮喪。 歡迎任何幫助。

對於可能遇到類似問題的任何人:

我聯系了 firebase 支持團隊,他們表示這是由一些原始設備制造商 (OEM) 實施的電池優化引起的。 當應用程序在應用程序切換器中滑動時,應用程序將被視為強制停止,這不是默認的 Android 行為。 不幸的副作用是它可能導致您的應用程序的 FCM 服務停止運行。

檢查您的應用程序是否受任何 OEM 的電池管理功能影響的一種方法如下:

  1. 將 OEM 設備附加到 adb。
  2. 在設備上運行您的應用程序。
  3. 將應用程序從設備上的最近屏幕上滑開。
  4. 運行命令: adb shell dumpsys package MY-PACKAGE | grep stopped adb shell dumpsys package MY-PACKAGE | grep stopped

如果它顯示stopped=true ,則可以安全地假設 OEM 具有這樣的機制,並且您的應用程序受到此問題的影響。

您還可以閱讀有關此問題的更多信息以及解決此問題的可能方法: https://www.freecodecamp.org/news/why-your-push-notifications-never-see-the-light-of-day- 3fa297520793/

問題是您正在發送 fcm 數據通知,但在 android 方面,您有正常通知的代碼。

在 onMessageReceived 方法中進行以下更改

Map<String, String> data = remoteMessage.getData().get("data");
String title = data.getOrDefault("title", "");
String body = data.getOrDefault("body", "");

傳遞此標題和正文字符串值以顯示通知塊代碼以設置標題和消息文本

我在一個類似的項目中使用過 OneSignal 推送服務,我沒有任何問題,也不需要實現任何額外的邏輯才能在后台或終止時接收通知。 您仍然需要與您的應用關聯的 firebase 項目來獲取 Firebase 服務器密鑰和發件人 ID。 如果沒有具體原因需要使用 Firebase 推送服務,我建議你試試OneSignal

免費計划包括無限移動、最多 10K web 推送訂閱者、email、SMS 和 1 條應用內消息。 無需信用卡。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM