FCM数据消息无法正常运行

时间:2018-07-21 22:41:18

标签: java android firebase firebase-cloud-messaging

我正在使用数据消息,即使应用程序被杀死,在后台或在前景中,我们也可以发送消息。我正在使用FCM。 但就我而言,有时我的应用程序无法收到这些消息。我正在从一个应用程序向另一个应用程序发送消息。有时,即使该应用被杀死或从后台删除,该应用也会收到消息,但有时却不会。 当我打开该应用程序时,突然出现该消息。收到特定消息时,我将开始活动。我知道即使应用程序被杀死,在后台或在前景中,数据消息也被用于发送消息,但是我遇到这样的问题。请帮忙 !.. 我希望它是绝对的。 我只是希望我的应用程序始终连接到FirebaseMessagingServices,即使它被杀死也是如此。我对服务一无所知,有人说我需要创建一个前台服务。如何创建它并实现到FirebaseMessagingServices ??

MYFirebaseMessaging.java

package com.example.praful.ubercoustomer.Service;

import android.app.Notification;
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.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;

import com.example.praful.ubercoustomer.AcceptedWindow;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.CompanycancelledtheBooking;
import com.example.praful.ubercoustomer.DeclinedWindow;
import com.example.praful.ubercoustomer.Helper.NotificationHelper;
import com.example.praful.ubercoustomer.Onthewayandimreached;
import com.example.praful.ubercoustomer.R;
import com.example.praful.ubercoustomer.RateActivity;
import com.example.praful.ubercoustomer.VerifyingCompletedBooking;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

import java.util.Map;

public class MyFirebaseMessaging extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(final RemoteMessage remoteMessage) {


        if (remoteMessage.getData() != null) {
            Map<String, String> data = remoteMessage.getData();
            String title = data.get("title");
            final String companyName = data.get("CompanyName");
            final String BookingIdC = data.get("BookingIdC");
            final String BookingIdT = data.get("BookingIdT");
            final String companyPhone = data.get("CompanyPhone");
            final String companyRates = data.get("CompanyRates");
            final String companyId = data.get("CompanyId");
            final String Date = data.get("Date");
            final String companyIdC = data.get("companyIdC");
            final String Time = data.get("Time");
            final String Id = data.get("Id");
            final String Address = data.get("Address");
            final String Bookingid = data.get("Bookingid");
            final String TimeCB = data.get("TimeCB");
            final String DateCB = data.get("DateCB");
            final String EventType = data.get("EventType");
            final String messageCB = data.get("messageCB");
            final String AddressCB = data.get("AddressCB");
            final String companythatcancelledthebooking = data.get("CompanyNamethatcancelledthebooking");

            final String message = data.get("message");
            //  remoteMessage.getNotification().getTitle() = title and  remoteMessage.getNotification().getBody() = message
            if (title != null && title.equals("Cancel")) {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(MyFirebaseMessaging.this, DeclinedWindow.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);

                        Common.isCompanyFound = false;
                        Common.companyId = "";
                        Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
                    }
                });
            } else if (title != null && title.equals("cancelAdvanceBooking")) {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(getBaseContext(), CompanycancelledtheBooking.class);
                        intent.putExtra("DateCB", DateCB);
                        intent.putExtra("TimeCB", TimeCB);
                        intent.putExtra("messageCB", messageCB);
                        intent.putExtra("AddressCB", AddressCB);
                        intent.putExtra("EventType", EventType);
                        intent.putExtra("Id", Id);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);

                        Common.isCompanyFound = false;
                        Common.companyId = "";
                        Toast.makeText(MyFirebaseMessaging.this, "" + messageCB, Toast.LENGTH_SHORT).show();
                    }
                });

            } else if (title != null && title.equals("Accept")) {


                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(MyFirebaseMessaging.this, AcceptedWindow.class);
                        intent.putExtra("Date", Date);
                        intent.putExtra("Time", Time);
                        intent.putExtra("Address", Address);
                        intent.putExtra("companyName", companyName);
                        intent.putExtra("companyPhone", companyPhone);
                        intent.putExtra("companyRates", companyRates);
                        intent.putExtra("companyId", companyId);
                        intent.putExtra("Bookingid", Bookingid);
                        intent.putExtra("EventType", EventType);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);
                        Common.isCompanyFound = false;
                        Common.companyId = "";


                        Toast.makeText(MyFirebaseMessaging.this, "" + message, Toast.LENGTH_SHORT).show();
                    }
                });

            } else if (title != null && title.equals("Arrived")) {
                Handler handler = new Handler(Looper.getMainLooper());

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                            showArrivedNotifAPI26(message);
                        else
                            showArrivedNotif(message);

                    }
                });
            } else if (title != null && title.equals("Completed")) {

                openRateactivity(message);
            } else if (title != null && title.equals("completedAdvancebooking")) {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(MyFirebaseMessaging.this, VerifyingCompletedBooking.class);
                        intent.putExtra("BookingIdC", BookingIdC);
                        intent.putExtra("message", message);
                        intent.putExtra("companyid", companyIdC);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);

                    }
                });
            } else if (title != null && title.equals("Ontheway")) {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
                        intent.putExtra("message", message);
                        intent.putExtra("BookingIdT", BookingIdT);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);

                    }
                });
            } else if (title != null && title.equals("Reached")) {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Intent intent = new Intent(MyFirebaseMessaging.this, Onthewayandimreached.class);
                        intent.putExtra("message", message);
                        intent.putExtra("BookingIdT", BookingIdT);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

                        startActivity(intent);

                    }
                });
            }

        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void showArrivedNotifAPI26(String body) {
        PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
                new Intent(), PendingIntent.FLAG_ONE_SHOT);

        Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationHelper notificationHelper = new NotificationHelper(getBaseContext());
        Notification.Builder builder = notificationHelper.getUberNotification("Arrived", body, contentIntent, defaultSound);
        notificationHelper.getManager().notify(1, builder.build());

    }

    private void openRateactivity(String body) {

        Intent intent = new Intent(this, RateActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    private void showArrivedNotif(String body) {
        PendingIntent contentIntent = PendingIntent.getActivity(getBaseContext(), 0,
                new Intent(), PendingIntent.FLAG_ONE_SHOT);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(getBaseContext());
        builder.setAutoCancel(true)
                .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND)
                .setWhen(System.currentTimeMillis()).
                setSmallIcon(R.drawable.ic_menu_camera)
                .setContentTitle("Arrived")
                .setContentText(body)
                .setContentIntent(contentIntent);

        NotificationManager manager = (NotificationManager) getBaseContext().getSystemService(Context.NOTIFICATION_SERVICE);
        manager.notify(1, builder.build());
    }

}

MyFirebaseIdService

package com.example.praful.ubercoustomer.Service;

import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.example.praful.ubercoustomer.Common.Common;
import com.example.praful.ubercoustomer.Model.Token;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class MyFirebaseIdService extends FirebaseInstanceIdService {
    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();

        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        updateTokenToServer(refreshedToken);

    }

    private void updateTokenToServer(String refreshedToken) {

        FirebaseDatabase db =FirebaseDatabase.getInstance();
        DatabaseReference tokens = db.getReference(Common.token_table);

        Token token = new Token(refreshedToken);
        if(FirebaseAuth.getInstance().getCurrentUser() != null)
            tokens.child(FirebaseAuth.getInstance().getCurrentUser().getUid()).setValue(token);

    }
}

1 个答案:

答案 0 :(得分:1)

  • 首先检查此远程消息是否包含有效负载,可能是有效负载由于任何原因而损坏。

    public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private static final String TAG = "REMOTE_MSG";
    
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if (remoteMessage == null)
            return;
    
        // check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.e(TAG, "Notification body: " + remoteMessage.getNotification().getBody());
            createNotification(remoteMessage.getNotification());
        }
    
        // check if message contains a data payload
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "From: " + remoteMessage.getFrom());
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }
    }
    
  • 请勿强制更新数据库上的FCM设备令牌。

    public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
    private static final String TAG = "FCM_ID";
    
    @Override
    public void onTokenRefresh() {
        // get hold of the registration token
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        // lg the token
        Log.d(TAG, "Refreshed token: " + refreshedToken);
        sendRegistrationToServer(refreshedToken);
    }
    private void sendRegistrationToServer(String token) {
        // implement this method if you want to store the token on your server
    }
    }
    

更新1

  • Firebase repo issue所述,该问题与设备有关,请尝试从设备的另一个角度进行研究。

更新2 来自firebase repo贡献者的报价 kroikie

  

如果应用被“杀死”或强制停止,FCM不会处理消息。   当用户杀死某个应用程序时,表明该用户没有   希望该应用程序运行,以便该应用程序直到用户运行   明确地再次启动它。

     

请注意,从“最新消息”列表中滑动应用程序不应“杀死”或强制执行   停下来。如果从最新消息中刷过后仍未收到邮件   列表,然后请识别这些设备,我们将与   制造商纠正这种行为。

     

仅当应用程序处于前台时才能够处理消息   或背景按预期工作。

更新3

  • 尝试在此问题上提及的骇客。

    1. 将此行插入Manifest.xml

      <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
      <uses-permission android:name="android.permission.WAKE_LOCK" />
      
    2. 这是因为DOZE模式和电池优化,您只需要关闭所有应用程序或特定应用程序的电池优化即可。转到设置>>应用>>选择您的应用>>电池>> 电池优化>选择您的应用>>选择不优化。 问题解决了。

    3. 现在(对于APP IS CLOSED情况),我将Notification文本写到文件中,如果extras == null且notificationText.txt存在,则读取此文本……这是愚蠢的解决方案,但它可以工作。当应用以其他方式关闭时,我该如何捕捉这些额外好处。

更新4

  

用户可以在设置>电池>中手动配置白名单。   电池优化。另外,系统提供了应用程序的方法   要求用户将其列入白名单。

     

应用可以触发ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS目的   将用户直接带到电池优化,他们可以   添加应用。拥有REQUEST_IGNORE_BATTERY_OPTIMIZATIONS的应用   权限可以触发系统对话框,让用户将应用添加到   直接进入白名单,而无需进行设置。该应用会触发   ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS意图触发   对话。用户可以手动将应用从白名单中删除   需要。

  • 以编程方式打开“电池优化”,请选中此answer

注意这一点

  

在要求用户将您的应用添加到白名单之前,请确保   应用符合白名单可接受的用例。

     

注意:   Google Play政策禁止应用程式要求直接豁免   Android 6.0+中的电源管理功能(打ze和应用待机)   除非该应用的核心功能受到不利影响。

更新5

  • 从此PowerManager.isIgnoringBatteryOptimizations()中检查answer

  • 禁用电池优化时,请考虑首先检查是否已已禁用,然后无需显示对话框,否则可以显示对话框。

     /**
      * return false if in settings "Not optimized" and true if "Optimizing battery use"
      */
    private boolean checkBatteryOptimized() {
    final PowerManager pwrm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            return !pwrm.isIgnoringBatteryOptimizations(getBaseContext().getPackageName());
        }
    }catch (Exception ignored){}
    return false;
    }
    
    private void startBatteryOptimizeDialog(){
     try {
    Intent intent = new Intent(android.provider.Settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
    intent.setData(Uri.parse("package:PUT_YOUR_PACKAGE_NAME_HERE"));
    startActivity(intent);
    
     } catch (ActivityNotFoundException e) {
       e.printStackTrace();
    }
    }