如何修复应用休眠 1 分钟后未收到 Firebase FCM 的通知

Posted

技术标签:

【中文标题】如何修复应用休眠 1 分钟后未收到 Firebase FCM 的通知【英文标题】:How to fix notification Firebase FCM not recieved after app sleeping 1 min 【发布时间】:2021-12-12 00:49:04 【问题描述】:

我的应用程序约会有问题,我使用功能云 Firebase 发送通知,但在 1 分钟睡眠应用程序后未收到通知,就在我单击按钮以打开手机收到通知时,我看到应用程序何时连接始终显示有线 USB 通知。 这个笔记我认为是电池。所以如果有人有任何想法,我将在下面分享我的代码谢谢

清单:

<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

 <service
        android:name=".Utils.Notify"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

通知服务:

public class Notify extends com.google.firebase.messaging.FirebaseMessagingService 

String CHANNEL_ID = "my_channel_010555";            // The id of the channel.
DataFire dataFire;
int i=0;


@Override
public void onNewToken(@NonNull String s) 
    super.onNewToken(s);



@Override
public void onMessageReceived(@NotNull RemoteMessage remoteMessage) 
    super.onMessageReceived(remoteMessage);
    FirebaseDatabase.getInstance().getReference().child("testnotifi").setValue("good");

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        //alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(time,broadcast1),broadcast1);
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), broadcast1);
     else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), broadcast1);
     else 
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), broadcast1);
    

    dataFire=new DataFire();

    /////// first you need to create in file index.js  //////////////////
    final String from_user_id = remoteMessage.getData().get("userIDvisited");
    final String state_app = remoteMessage.getData().get("state_app");
    final String notification_state = remoteMessage.getData().get("notification_state");

    notification(remoteMessage,from_user_id,notification_state);




private  void notification(RemoteMessage remoteMessage, String from_user_id, String notification_state)
    Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"+ getApplicationContext().getPackageName() + "/" + R.raw.piece_of_cake);

    String notificationTitle = remoteMessage.getData().get("title");
    String notificationMessage = remoteMessage.getData().get("body");
    //String click_action = remoteMessage.getNotification().getClickAction();

    @SuppressLint("WrongConstant") NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setBadgeIconType(R.drawable.luul_icon)
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.luul_icon))
                    .setAutoCancel(true)
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setWhen(System.currentTimeMillis())
                    .setSmallIcon(R.drawable.luul_icon)
                    .setContentTitle(notificationTitle)
                    .setContentText(notificationMessage)
                    .setVibrate(new long[]0, 500, 1000)
                    .setDefaults(Notification.DEFAULT_LIGHTS)
                    .setSound(soundUri);


    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
        mBuilder.setSmallIcon(R.drawable.ic_notify_app);
        mBuilder.setColor(getColor(R.color.colorPrimary));
     else 
        mBuilder.setSmallIcon(R.drawable.luul_icon);
    


    Intent resultIntent = new Intent("com.xxx.xxx_TARGET_NOTIFICATION_messages");
    resultIntent.putExtra("userIDvisited", from_user_id);
    resultIntent.putExtra("notification_state", notification_state);

    /////////// Because clicking the notification opens a new ("special") activity, there's
    /////////// no need to create an artificial back stack.
    PendingIntent resultPendingIntent =
            PendingIntent.getActivity(
                    this,
                    0,
                    resultIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT
            );
    //////////////////////////////////
    mBuilder.setContentIntent(resultPendingIntent);

    // Sets an ID for the notification
    int mNotificationId = (int) System.currentTimeMillis();
    // Gets an instance of the NotificationManager service
    NotificationManager mNotifyMgr =
            (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 

        if (mNotifyMgr != null) 
            List<NotificationChannel> channelList = mNotifyMgr.getNotificationChannels();

            for (int i = 0; channelList != null && i < channelList.size(); i++) 
                mNotifyMgr.deleteNotificationChannel(channelList.get(i).getId());
            
        

        CharSequence name = "NotifyChannelWork";                   
        String descrition = "NotifyChannelDescWork";                   
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_HIGH);
        channel.setDescription(descrition);
        channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
        channel.setSound(soundUri,
                new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                        .setLegacyStreamType(AudioManager.STREAM_RING)
                        .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION).build());

        if (mNotifyMgr != null)
            mNotifyMgr.createNotificationChannel(channel);
    

    PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    @SuppressLint("InvalidWakeLockTag")
    PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
            "MyWakelockTag");
    wakeLock.acquire();


    //to release the screen lock
    KeyguardManager keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardManager.KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("TAG");
    //add permission in the manifest file for the disablekeyguard
    keyguardLock.disableKeyguard();

    // Builds the notification and issues it.
    mNotifyMgr.notify(mNotificationId, mBuilder.build());


使用 Node.js index.js 的函数:

 if(notification_state=="message")
                
                                    const payload = 

                                            data:
                                                    title : `$username`,
                                                    body  : `$last_message`,
                                                    userIDvisited : from_user_id,
                                                    state_app:state_app,
                                                    notification_state:notification_state,
                                                    priority:"high"
                                                
                                            ;

                                    return admin.messaging().sendToDevice(token_id,payload).then(response => 
                                        console.log('this was the notification Feature ');

                                    );
                    

【问题讨论】:

【参考方案1】:

查看Google Firebase Cloud Messaging,我找到了Handle notification messages in a background app和Background restricted app的解决方案。

在后台应用中处理通知消息:

当您的应用处于后台时,Android 会将通知消息定向到系统托盘。默认情况下,用户点击通知会打开应用启动器。 这包括同时包含通知和数据负载的消息(以及从通知控制台发送的所有消息)。

在这些情况下,通知会传递到设备的系统托盘,而数据负载会在启动器 Activity 的意图的附加部分中传递。

后台受限应用:

FCM 可能不会向用户放入background restriction 的应用传递消息(例如通过:设置 -> 应用和通知 -> [应用名称] -> 电池)。一旦您的应用程序从后台限制中删除,新消息将像以前一样传递到该应用程序。为防止消息丢失和其他背景限制影响,请务必避免 Android vitals 努力列出的不良行为。

解决方案:

我已将 Google Play 服务从电池优化中列入白名单,因此它永远不会死机,并以编程方式调整 WIFI 设置,即使在深度睡眠时也能运行。现在,即使处于睡眠模式,手表也会收到通知。

【讨论】:

以上是关于如何修复应用休眠 1 分钟后未收到 Firebase FCM 的通知的主要内容,如果未能解决你的问题,请参考以下文章

如何修复谷歌不可见 reCAPTCHA 验证后未提交的 Ajax 表单

收到支付验证码后未操作,银行卡却被盗刷!原因竟是......

ios 应用更新后未收到 Firebase/APNS 通知

设备休眠时重新唤醒应用程序的 FCM 推送通知无效

Android - 包含 click_action 后未收到 FCM 推送通知

无法修复初学者休眠程序中的错误[重复]