在SharedPreference中存储全局布尔值失效问题求助
问题分析与解决方案
兄弟,我太懂你一下午折腾无果的崩溃了——刚上手Firebase推送确实容易踩这些隐蔽的小坑!咱们来拆解一下你遇到的问题:
核心可能原因:FCM通知类型的“隐形规则”
这是新手最容易踩的坑:Firebase Cloud Messaging(FCM)分两种消息类型,通知消息和数据消息,它们的处理逻辑完全不同:
- 如果是从Firebase控制台发送的纯通知消息(只填了Notification标签的内容),当你的App在后台时,FCM会直接把通知推送到系统托盘,根本不会经过你的
FirebaseMessagingService的onMessageReceived()方法!这时候你在Service里写的SharedPreferences判断完全没机会执行。 - 只有数据消息(只填Data标签),或者组合消息(同时填了Notification和Data),才会让
onMessageReceived()触发,你的判断逻辑才能生效。
其他可能的排查点
SharedPreferences的上下文一致性
你在Activity里用mContext.getSharedPreferences("notifications", MODE_PRIVATE)存储,在Service里用getApplicationContext().getSharedPreferences(...)获取,理论上是同一个实例,但保险起见,在Service里直接用getSharedPreferences("notifications", MODE_PRIVATE)试试(Service本身就是Context子类),避免上下文差异导致的读取问题。apply()的异步特性
editor.apply()是异步写入磁盘的,如果存储后立刻发送测试通知,可能还没完成写入。排查时可以临时换成editor.commit()(同步写入)测试,确认写入后再改回apply()(推荐用apply,因为不阻塞主线程)。
修复后的完整示例代码
1. 确保存储逻辑正确
// 存储布尔值的代码(Activity中) SharedPreferences notificationsPref = getSharedPreferences("notifications", MODE_PRIVATE); SharedPreferences.Editor editor = notificationsPref.edit(); editor.putBoolean("receiveNotifications", false); editor.apply(); // 测试时可临时换成editor.commit()
2. FirebaseMessagingService中的正确处理
public class MyFirebaseMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { // 处理数据消息(无论App前后台都会触发) if (remoteMessage.getData().size() > 0) { String contentTitle = remoteMessage.getData().get("title"); String messageBody = remoteMessage.getData().get("body"); handleNotification(contentTitle, messageBody); } // 处理通知消息(只有App在前台时才会走到这里) if (remoteMessage.getNotification() != null) { String contentTitle = remoteMessage.getNotification().getTitle(); String messageBody = remoteMessage.getNotification().getBody(); handleNotification(contentTitle, messageBody); } } private void handleNotification(String title, String body) { // 读取SharedPreferences的开关状态 SharedPreferences sharedPreferences = getSharedPreferences("notifications", MODE_PRIVATE); Boolean areNotificationsAllowed = sharedPreferences.getBoolean("receiveNotifications", true); if (areNotificationsAllowed) { sendNotification(title, body); } } // 适配Android O及以上的通知发送逻辑 private void sendNotification(String title, String body) { Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE ); String channelId = "app_notification_channel"; Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId) .setSmallIcon(R.drawable.ic_notification) .setContentTitle(title) .setContentText(body) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // 创建通知渠道(Android O及以上必需) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel( channelId, "应用通知", NotificationManager.IMPORTANCE_DEFAULT ); notificationManager.createNotificationChannel(channel); } notificationManager.notify(0, notificationBuilder.build()); } }
测试注意事项
测试时一定要发送数据消息或者组合消息,比如用接口工具调用FCM的API发送:
{ "to": "你的设备推送Token", "data": { "title": "测试标题", "body": "测试内容" } }
这样才能确保你的onMessageReceived()被触发,开关逻辑生效。
内容的提问来源于stack exchange,提问作者Mwikala Kangwa
相关产品推荐
相关产品推荐

