三星Galaxy S8(Android8.0.0)FCM Instance Id无法生成求助
我帮你分析下这个问题:核心是在三星Galaxy S8(Android 8.0)设备上,FCM的Instance ID(也就是Token)无法生成,导致MainActivity里的Log.d抛出了NullPointerException,而其他设备运行正常。结合你提供的代码和报错日志,问题主要出在旧版FCM API的兼容性和同步获取Token的异步逻辑冲突上,再加上三星Android 8.0定制ROM的后台限制,才出现了这个特定设备的问题。下面是具体的诊断和修复步骤:
一、先解决直接触发崩溃的空指针问题
你在MainActivity的onCreate里直接调用FirebaseInstanceId.getInstance().getToken(),但FCM Token的生成是异步操作,在App启动初期可能还没完成,返回了null,而Log.d的第二个参数不能为null,所以触发了println needs a message的异常。
修复这个问题很简单,改用异步方式获取Token:
public class MainActivity extends AppCompatActivity { private static final String TAG = "fcmToken"; Button invokeServer; String url="http://10.0.3.2/fcm/fcmInsert.php"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 异步获取Token,避免空指针 FirebaseMessaging.getInstance().getToken() .addOnCompleteListener(task -> { if (!task.isSuccessful()) { Log.w(TAG, "获取FCM Token失败", task.getException()); return; } // 获取到有效Token String token = task.getResult(); Log.d(TAG, "FCM Token: " + token); // 这里可以把Token上传到你的服务器 // sendTokenToServer(token); }); } }
二、替换废弃的FCM API(关键修复)
你用的FirebaseInstanceIdService已经被Google废弃了,在Android 8.0及以上的后台服务限制下,尤其是三星的定制ROM,这个服务可能无法被正确触发,导致Token根本不会生成。
1. 更新FCM依赖(确保用最新版本)
在Module级别的build.gradle里更新FCM依赖:
implementation 'com.google.firebase:firebase-messaging:23.0.0' // 或更高版本
2. 重构Token获取逻辑
删除旧的FCMInstance类,把Token获取逻辑合并到FcmMessageReceiver里(它继承的FirebaseMessagingService是官方推荐的最新实现):
public class FcmMessageReceiver extends FirebaseMessagingService { private static final String TAG = "fcmToken"; // 当Token刷新时会调用这个方法 @Override public void onNewToken(String token) { super.onNewToken(token); Log.d(TAG, "刷新后的Token: " + token); // 把Token上传到你的服务器 sendTokenToServer(token); } // 保留你原有的消息接收逻辑 @Override public void onMessageReceived(RemoteMessage remoteMessage) { Log.d("fcm","收到消息"); String title= remoteMessage.getNotification().getTitle(); String body= remoteMessage.getNotification().getBody(); Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class); PendingIntent resultPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder mNotifyBuilder; NotificationManager mNotificationManager; mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); int notifyID = 9001; mNotifyBuilder = new NotificationCompat.Builder(getApplicationContext()) .setContentTitle(title) .setContentText(body) .setSmallIcon(R.mipmap.ic_launcher); mNotifyBuilder.setContentIntent(resultPendingIntent); int defaults = 0; defaults = defaults | Notification.DEFAULT_SOUND; mNotifyBuilder.setDefaults(defaults); mNotifyBuilder.setAutoCancel(true); mNotificationManager.notify(notifyID, mNotifyBuilder.build()); } // 实现Token上传到服务器的逻辑 private void sendTokenToServer(String token) { // 这里可以用OkHttp、Volley等网络库实现上传 } }
3. 更新Manifest配置
删除原有的FCMInstance服务声明,确保FcmMessageReceiver的配置正确:
<service android:name=".FcmMessageReceiver"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service>
三、针对三星Android 8.0设备的额外排查
如果上面的修复后还是有问题,可能是三星ROM的后台限制导致的:
- 关闭电池优化:进入设置 > 电池 > 电池优化 > 找到你的应用 > 设置为「不优化」
- 解除后台限制:进入设置 > 应用程序 > 你的应用 > 电池 > 关闭「后台限制」
- 更新Google Play服务:确保设备上的Google Play服务是最新版本,旧版本可能和FCM不兼容
- 清除应用缓存数据:尝试清除应用的缓存和数据,然后重启应用再测试
你提供的原代码与报错日志参考
清单文件(Manifest File):
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ideabinbd.fcmimplementation"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name=".FCMInstance"> <intent-filter> <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/> </intent-filter> </service> <service android:name=".FcmMessageReceiver"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT"/> </intent-filter> </service> </application> </manifest>
Instance Id类(已废弃):
public class FCMInstance extends FirebaseInstanceIdService { private final String TAG="fcmToken"; public String currentToken; @Override public void onTokenRefresh() { currentToken= FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, currentToken); } }
消息接收服务:
public class FcmMessageReceiver extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { Log.d("fcm","messageRecieved"); String title= remoteMessage.getNotification().getTitle(); String body= remoteMessage.getNotification().getBody(); Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class); PendingIntent resultPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder mNotifyBuilder; NotificationManager mNotificationManager; mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); int notifyID = 9001; mNotifyBuilder = new NotificationCompat.Builder(getApplicationContext()) .setContentTitle(title) .setContentText(body) .setSmallIcon(R.mipmap.ic_launcher); mNotifyBuilder.setContentIntent(resultPendingIntent); int defaults = 0; defaults = defaults | Notification.DEFAULT_SOUND; mNotifyBuilder.setDefaults(defaults); mNotifyBuilder.setAutoCancel(true); mNotificationManager.notify(notifyID, mNotifyBuilder.build()); } }
MainActivity代码:
public class MainActivity extends AppCompatActivity { private static final String TAG = "fcmToken"; Button invokeServer; String url="http://10.0.3.2/fcm/fcmInsert.php"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, FirebaseInstanceId.getInstance().getToken()); } }
报错日志:
Process: com.ideabinbd.fcmimplementation, PID: 809 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ideabinbd.fcmimplementation/com.ideabinbd.fcmimplementation.MainActivity}: java.lang.NullPointerException: println needs a message at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2955) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3030) at android.app.ActivityThread.-wrap11(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1696) at android.os.Handler.dispatchMessage(Handler.java:105) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374) Caused by: java.lang.NullPointerException: println needs a message at android.util.Log.println_native(Native Method) at android.util.Log.d(Log.java:161) at com.ideabinbd.fcmimplementation.MainActivity.onCreate(MainActivity.java:34) at android.app.Activity.performCreate(Activity.java:7174) at android.app.Instrumentation.callActivityOnCreate(I
内容的提问来源于stack exchange,提问作者Mohaimanul Chowdhury

