安卓。停止前台服务导致应用程序崩溃

问题描述 投票:1回答:1

先决条件。作为应用需求的一部分,我需要确保应用在后台不会被Android系统关闭(杀死)。为此,我实现了Foreground服务,尽管我在后台不做任何实际的处理,只是维护应用程序的状态。一切都很好,除了有一件事我不太清楚如何解决。

这个问题。有时(目前只有一次),我收到了这个异常。

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

这个异常是在我试图停止前台服务时抛出的,而实际上它并没有被启动。

所以,我的问题是--有没有一种方法可以正确地停止前台服务,确保它在实际停止之前没有运行?我目前发现的是,我可以为我的服务设置静态实例,并在停止服务之前将其比作null,或者获取当前运行的所有服务的列表。但这些看起来都像是一些 "黑客 "的变通方法。

下面是一些代码。MyForegroundService:

public class ForegroundService extends Service {

public static final int NOTIFICATION_ID = 1;
public static final String CHANNEL_ID = "SessionForegroundServiceChannel";
public static final String ACTION_FOREGROUND_START = "ACTION_FOREGROUND_START";
public static final String ACTION_FOREGROUND_STOP = "ACTION_FOREGROUND_STOP";

public static void startForegroundService(Context context) {
    Intent intent = new Intent(context, ForegroundService.class);
    intent.setAction(ForegroundService.ACTION_FOREGROUND_START);
    ContextCompat.startForegroundService(context, intent);
}

public static void stopForegroundService(Context context) {
    Intent intent = new Intent(context, ForegroundService.class);
    intent.setAction(ForegroundService.ACTION_FOREGROUND_STOP);
    ContextCompat.startForegroundService(context, intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if (ACTION_FOREGROUND_START.equals(intent.getAction())) {
        createNotificationChannel();
        Intent stopForegroundIntent = new Intent(this, ForegroundServiceBroadcastReceiver.class);
        PendingIntent pendingLogoutIntent = PendingIntent.getBroadcast(this,
                0, stopForegroundIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
                        ? null
                        : getString(R.string.app_short_name))
                .setContentText(getString(R.string.foreground_description))
                .setColor(getResources().getColor(R.color.color))
                .setSmallIcon(R.drawable.ic_notification)
                .addAction(R.drawable.ic_logout, getString(R.string.logout), pendingLogoutIntent)
                .build();
        startForeground(NOTIFICATION_ID, notification);
    } else if (ACTION_FOREGROUND_STOP.equals(intent.getAction())) {
        stopForeground(true);
        stopSelf();
    }
    return START_STICKY;
}

private void createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel serviceChannel = new NotificationChannel(
                CHANNEL_ID,
                getString(R.string.app_name),
                NotificationManager.IMPORTANCE_LOW
        );
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(serviceChannel);
    }
}


@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

<service
        android:name=".ui.ForegroundService"
        android:exported="false"
        android:stopWithTask="true"/>

我也有BroadcastReceiver和EventBus来监听一些事件,并根据这些事件停止前台。

你们能帮帮我吗?

android android-service foreground-service
1个回答
0
投票

让我对@Pawel评论的内容补充更多细节。

如果你没有在调用Context.startForegroundService后3秒内调用Service.startForegroundService,你就会得到这个异常,这就是全部的内容。

下面是完整的解决方案的样子。

当你需要停止前台服务时,你需要做以下工作(伪代码):

if (action == START_FOREGROUND) {
    ...
    startForeground(NOTIFICATION_ID, notification);
} else if (action == STOP_FOREGROUND) {
    startForeground(NOTIFICATION_ID, closeNotification); //in case it wasn't started before
    stopForeground(true);
    stopSelf();
}

尽管这并不明显,而且任何文档都没有直接说,当你需要... 煞风景 你需要 开场白 前停止它(如果它没有被启动)。

谢谢@Pawel的提示。

© www.soinside.com 2019 - 2024. All rights reserved.