致命异常:android.app.RemoteServiceException。Context.startForegroundService() 没有调用 Service.startForeground()。

4

我们最近实施了前台服务,但在Android 9中(仅限三星设备),一些用户遇到了一些重复的崩溃问题,我们不知道是什么原因导致的。有人遇到过相同的问题吗?这个问题有解决方法吗?

Fatal Exception: android.app.RemoteServiceException Context.startForegroundService() did not then call Service.startForeground()

android.app.ActivityThread$H.handleMessage (ActivityThread.java:1874)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:214)
android.app.ActivityThread.main (ActivityThread.java:7073)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:964)

AndroidManigest.xml

<service
        android:name="com.sotg.base.util.GeoNotification"
        android:exported="true"
        android:foregroundServiceType="location" />

GeoNotificationManager.kt

    override fun startService() {
        val geoService = Intent(context, GeoNotification::class.java)
        geoService.action = GeoNotification.START_SERVICE_ACTION

        // for android Oreo and higher start as foreground
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            context.startForegroundService(geoService)
        } else {
            context.startService(geoService)
        }
    }

    override fun stopService() {

        // Shouldn't initialize the service to stop it when the service is not running.
        if (!GeoNotification.isServiceRunning()) return;

        val geoService = Intent(context, GeoNotification::class.java)
        geoService.action = GeoNotification.STOP_TRACKING_ACTION
        runCatching { context.startService(geoService) }
                .onFailure(analytics::logException)
    }

GoeNotification.java

    private static boolean isServiceRunning;

    public static boolean isServiceRunning() {
        return isServiceRunning;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        isServiceRunning = false;
    }

    @Override
    public void onDestroy() {
        stopTracking();
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (START_SERVICE_ACTION.equals(intent.getAction())) {
            startTracking();
        } else if (STOP_TRACKING_ACTION.equals(intent.getAction())) {
            stopTracking();
        } else {
            Log.w(TAG, "Unknown action for location service");
        }

        // Service restarts if it gets terminated
        // the original Intent is re-delivered to the onStartCommand
        // method when using START_REDELIVER_INTENT.
        return START_REDELIVER_INTENT;
    }

 private void startTracking() {

        if (isServiceRunning) return;

        // create notification and config as foreground only for android Oreo and higher
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(Constants.NOTIFY_SURVEY_GCM, createForegroundNotification(this));
        }

        isServiceRunning = true;

       ...
    }

    private void stopTracking() {

        if (!isServiceRunning) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                stopForeground(true);
            }
            stopSelf();
            return;
        }

        // stop location updates on partner SDKs
       ....
        stopSelf();
        isServiceRunning = false;
    }

    public static Notification createForegroundNotification(Context context) {
            NotificationChannelUtil.INSTANCE.getPreparedManager(context);
            String channel = NotificationChannelUtil.INSTANCE.getSYSTEM_CHANNEL_ID();

            // The PendingIntent to launch activity.
            PendingIntent activityPendingIntent = PendingIntent.getActivity(context, 0,
                    new Intent(context, MainTabActivity.class), 0);

            NotificationCompat.Action settingsAction = NotificationUtil.createSettingAction(context);

            String title = context.getResources().getString(R.string.foreground_service_notification_title);
            String desc = context.getResources().getString(R.string.foreground_service_notification_description);
            String expandedText = context.getResources().getString(R.string.foreground_service_notification_description_expanded);

            NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channel)
                    .setContentIntent(activityPendingIntent)
                    .setSmallIcon(R.drawable.noti)
                    .setContentTitle(title)
                    .setContentText(desc)
                    .setStyle(new NotificationCompat.BigTextStyle()
                            .bigText(expandedText))
                    .addAction(settingsAction)
                    .setColorized(false)
                    .setOngoing(true);

            return builder.build();
        }


它没有被接受的答案是唯一的问题吗?它有几个得到高票的答案 - 你试过它们了吗? - Ryan M
@RyanM 我无法重现这个 bug。在发布后,一些用户遇到了这个问题,我在 Firebase 上看到了崩溃信息。我会尝试一些解决方法。谢谢。 - Arian A
2个回答

2
我曾在使用安卓8.0及以上版本的三星和华为设备时遇到同样的问题,错误信息也相同。
如果我没记错的话,自从安卓8.0及以上版本,使用startService()startForegroundService()时需要调用startForeground()
我通过在服务类的onCreate函数中添加以下代码解决了这个问题:创建一个通知并使用startForeground()启动它。
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    NotificationChannel mNotificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_NONE);
    mNotificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
    mNotificationManager.createNotificationChannel(mNotificationChannel);
    Notification note = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Reboot Sequence")
            .setContentText("Rescheduling Alarms")
            .setSmallIcon(R.drawable.ic_alarm_24dp)
            .build();
    startForeground(1, note);
}

我希望这会对您有所帮助。


谢谢@Fatih,我会尝试这个。 - Arian A

0
即使使用startForeground()启动通知,此问题仍可能发生。该问题是由某些设备上的软件漏洞引起的,因此无法在应用程序代码中解决。唯一现实的解决方案是进入Play开发者控制台的崩溃和ANR,并找到问题设备。然后进入同一开发者控制台的设备管理器,并排除这些设备。我已经看到华为HUAWEI Y5引起了很多这些崩溃。

这不是一个好的解决方案。对我来说,在S8、S9、S9+、Pixel 6上都会出现这个问题。我不能把问题归咎于设备上的操作系统。 - Alex
1
如果在S8、S9和S9+上发生了这种情况,很可能是由于您的应用程序代码引起的。我从未在这些设备上看到过这个异常。然后,您应该根据startForeGroundservice()的建议更新您的代码。但即使您这样做了,这个异常仍然可能会在一些低质量的设备上发生。这就是我回答的意思。 - Eyvind Almqvist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接