如何修复应用休眠 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 表单
收到支付验证码后未操作,银行卡却被盗刷!原因竟是......