126

如果我的应用程序正在运行并且我按下主页按钮,该应用程序将进入后台。现在,如果我长按主页按钮并通过从最近的应用程序列表中滑动它来终止该应用程序,则不会调用任何事件onPause()onStop()或者不会onDestroy()调用该进程而是终止该进程。因此,如果我希望我的服务停止、终止通知并取消注册侦听器,我该怎么做?我阅读了很多文章和博客,但没有得到任何有用的信息,也没有找到任何关于它的文档。任何帮助,将不胜感激。提前致谢。

4

10 回答 10

176

我刚刚解决了类似的问题。

如果只是通过从最近的应用程序列表中滑动来终止应用程序时停止服务,那么您可以执行以下操作。

在您的清单文件中,将标志保留stopWithTasktrue服务。喜欢:

<service
    android:name="com.myapp.MyService"
    android:stopWithTask="true" />

但是正如您所说,您要注销侦听器并停止通知等,我建议采用这种方法:

  1. 在您的清单文件中,将标志保留stopWithTaskfalse服务。喜欢:

    <service
        android:name="com.myapp.MyService"
        android:stopWithTask="false" />
    
  2. 现在在您的MyService服务中,覆盖方法onTaskRemoved。(仅当stopWithTask设置为时才会触发false)。

    public void onTaskRemoved(Intent rootIntent) {
    
        //unregister listeners
        //do any other cleanup if required
    
        //stop service
        stopSelf();  
    }
    

有关更多详细信息,请参阅我的问题,其中也包含代码的其他部分。

希望这可以帮助。

于 2014-11-12T08:38:15.963 回答
37

我们需要创建一个服务,从最近的服务中清除应用程序

public class ClearService extends Service {

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("ClearService", "Service Started");
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("ClearService", "Service Destroyed");
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.e("ClearService", "END");
        //Code here
        stopSelf();
    }
}
  1. manifest.xml
<service android:name="com.package.ClearService" android:stopWithTask="false" />
  1. 然后在您的启动活动中启动此服务
startService(new Intent(getBaseContext(), ClearService.class));

现在,每当您从 android 最近清除您的应用程序时,onTaskRemoved()就会执行此方法。

于 2017-03-17T11:49:45.487 回答
20

我解决了类似的问题。如果您希望在从最近的任务中滑动并在下次启动时正常运行,请按照以下步骤操作:-

1)在共享首选项中保存进程ID:

SharedPreferencesUtils.getInstance().putInt(SharedPreferencesUtils.APP_PROCESS_ID, android.os.Process.myPid());

2)从最近的任务中清除后从启动器启动应用程序时,请执行以下操作:

int previousProcessID = mSharedPreferencesUtils.getInt(SharedPreferencesUtils.APP_PROCESS_ID);

int currentProcessID = android.os.Process.myPid();

if ((previousProcessID == currentProcessID)) {
    // This ensures application not killed yet either by clearing recent or anyway
} else {
    // This ensures application killed either by clearing recent or by anyother means
}
于 2015-10-07T13:34:16.640 回答
6

当你按下 home -onPause并且onStop你的 Activity 正在被调用时,所以此时你必须进行所有的保存和清理,因为 Android 平台并不能进一步保证onDestroy会调用该方法或任何其他生命周期方法,因此该进程可能会被终止没有任何通知。

于 2013-10-24T14:16:57.723 回答
3

ViewModel.onCleared() 可能很有用,如果目标是在用户通过滑动而不是按“停止”或按钮执行意外退出时释放一些资源(可能是网络上其他地方运行的系统)。[这就是我最初提出这个问题的方式]。

应用程序没有收到通知,并且 Activity.onDestroy() 被调用以进行配置更改,例如方向更改,因此答案不存在。但是 ViewModel.onCleared 会在应用程序被滑走时调用(以及当用户退出活动时)。如果您要使用的资源与堆栈中的多个活动相关联,您可以添加引用计数或其他一些机制来决定 ViewModel.onClear 是否应该释放资源。

这是使用 ViewModel 模式的又一个很好的理由

于 2019-09-10T15:48:43.697 回答
2

我真的不知道为什么上述方法对我的情况不起作用,即使我设置android:stopWithTask="false"onTaskRemoved()未调用。

另一种好方法是使用AndroidViewModel. 这甚至适用于用户在按下后退按钮时退出应用程序的情况。

只需将类绑定ViewModel到您的MainActivity然后执行您的任务onCleared()回调。

例子:

public class MainViewModel extends AndroidViewModel {
    public MainViewModel(@NonNull Application application) {
        super(application);
    }

    @Override
    protected void onCleared() {
        // Do your task here
        Log.e("MainViewModel", "OnCleared mainViewModel");
        super.onCleared();
    }
}

然后将其绑定到您的 MainActivity:

MainViewModel viewModel = new ViewModelProvider(this).get(MainViewModel.class);

~ 瞧!

于 2020-03-04T19:30:21.300 回答
1

调用on 时,您需要保存数据onPause()。看这个生命周期图: Android Developer

你可以看到一个应用可以在onPause()或之后被杀死onStop()

onRestart()在那里处理您的数据并在\中恢复它onCreate()

祝你好运!

于 2013-10-24T14:33:53.720 回答
1

您无法处理滑动,因为系统只是从内存中删除您的进程而不调用任何回调。

我已经检查过,在用户调用“最近的应用程序”屏幕之前,总是会调用 onPause()。所以你需要在onPause方法中保存所有数据而不检查isFinishing()。

要检查后退按钮,请使用 onBackPressed 方法。

于 2017-07-28T10:46:36.627 回答
1

正如 Bob Cram 在他的回答中提到的,View Model 的 onCleared()方法就是答案。它适用于两种情况:

  1. 当用户通过从后台滑动应用程序来删除应用程序时。
  2. 当用户使用清除列表按钮清除所有应用程序时。

服务的 onTaskRemoved() 将在用户从后台滑动应用程序时起作用,但在使用 kill all 按钮清除应用程序时将不起作用。

但是 viewModel 的 onCleared() 方法在这两种情况下都有效。您可以使用 if 停止任何正在进行的进程或清除远程服务器中的任何任务。

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }
于 2020-07-12T05:25:27.777 回答
0

这在 android 6,7,8,9 上对我有用。

像这样制作一项服务:

 public class OnClearFromRecentService extends Service {

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

 @Override public int onStartCommand(Intent intent, int flags, int
 startId) {
     Log.d("ClearFromRecentService", "Service Started");
     return START_NOT_STICKY; }

 @Override public void onDestroy() {
     super.onDestroy();
     Log.d("ClearFromRecentService", "Service Destroyed"); }

 @Override public void onTaskRemoved(Intent rootIntent) {
     Log.e("ClearFromRecentService", "END");
     //Code here
     stopSelf(); } }

2)在以下位置注册此服务manifest.xml

<service android:name="com.example.OnClearFromRecentService"
 android:stopWithTask="false" />

3)然后在您的启动活动上启动此服务

 startService(new Intent(getBaseContext(),
 OnClearFromRecentService.class));
于 2019-08-26T23:52:41.857 回答