如何正确停止前台服务?

12

我使用startForeground使我的服务在后台“持久”,防止被操作系统杀死。
我在主活动的onDestroy方法中调用stopForeground和stopService来移除服务。
问题在于,当我在最近使用的应用程序中滑动关闭应用时,调试会话仍在运行,而在“正常”情况下(不使用startForeground),调试会话将正确终止。
使用adb shell可以确认应用程序仍在运行。
startForeground创建了一个“特殊”的运行线程,无法通过简单停止前台及服务来停止该线程。
请问有什么思路吗?

3个回答

32

如果您想在清除应用程序的最近任务时停止服务,您需要在清单文件中为服务定义一个属性stopWithTask,如下所示:

如果你想要在最近任务中清除你的应用程序时停止你的服务, 你必须在清单文件中为服务定义一个stopWithTask属性,就像下面所示:

  <service
    android:enabled="true"
    android:name=".ExampleService"
    android:exported="false"
    android:stopWithTask="true" />

你可以在服务中重写onTaskRemoved方法,当应用程序的任务被清除时将调用此方法

@Override
    public void onTaskRemoved(Intent rootIntent) {
        System.out.println("onTaskRemoved called");
        super.onTaskRemoved(rootIntent);
        //do something you want
        //stop service
        this.stopSelf();
    }

谢谢!这正是我想要做的 :) - MMasmoudi
+1:这也帮助了我,谢谢!你能添加一个参考吗?因为我在官方文档中找不到 stopWithTask - Astrogator
3
注意!根据文档,在清单文件中设置了stopWithTask=true后,即使应用被移除在内存中的任务列表中,onTaskRemoved()也不会被调用。(参考链接:https://developer.android.com/reference/android/app/Service#onTaskRemoved(android.content.Intent)) - Josselin

8

我不知道是否正确,但在我的应用程序中,我在这里停止了前台服务,并且它起作用。请检查代码。

private void stopForegroundService() {

    // Stop foreground service and remove the notification.
    stopForeground(true);

    // Stop the foreground service.
    stopSelf();
}

更新

请从您的主类中以某种方式调用stopservice方法(不要从onDestroy中调用),代码如下:

    Intent intent = new Intent(this, MyForeGroundService.class);
    intent.setAction(MyForeGroundService.ACTION_STOP_FOREGROUND_SERVICE);
    startService(intent);

MyForegroundService.java

 private static final String TAG_FOREGROUND_SERVICE = "FOREGROUND_SERVICE";

public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";

public static final String ACTION_STOP_FOREGROUND_SERVICE = "ACTION_STOP_FOREGROUND_SERVICE";

@Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            String action = intent.getAction();

            switch (action) {
                case ACTION_START_FOREGROUND_SERVICE:
                    startForegroundService();
                    break;
                case ACTION_STOP_FOREGROUND_SERVICE:

                    stopForegroundService();
                    break;
            }
        }
        return START_STICKY;
    }

  private void stopForegroundService() {
    Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");

    // Stop foreground service and remove the notification.
    stopForeground(true);

    // Stop the foreground service.
    stopSelf();
}

1
我刚刚尝试了一下,输出结果是一样的。 你是否尝试在调试时滑动最近使用的应用程序关闭你的应用程序,同时你的服务正在运行? 只是为了看看调试会话是否被正确停止。 - MMasmoudi
@MahmoudMasmoudi 你说你已经在onDestroy()中实现了它?尝试从服务类内部调用此方法。请查看更新后的答案。希望能有所帮助。 - Alex
没关系,非常感谢您的帮助 :) - MMasmoudi
为什么我们不能使用mContext.stopService(mIntent);停止前台服务? - Akshay Choudhry
前台是否可以被其他并非最初创建它的活动终止? - gumuruh
显示剩余2条评论

0

另一种方式(用于库服务):

val cmp = ComponentName(this, XXXService::class.java)
    packageManager.setComponentEnabledSetting(
        cmp, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP
)

服务将立即停止。 需要时,您可以设置PackageManager.COMPONENT_ENABLED_STATE_ENABLED


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