如果我的应用程序正在运行,我按下主页按钮,该应用程序将进入后台。现在,如果长按主页按钮并通过从最近的应用列表中滑动来终止该应用,则不会调用onPause()
,onStop()
或onDestroy()
等任何事件,而是会终止该过程。因此,如果我希望我的服务停止,杀死通知和取消注册听众,我该怎么做?我阅读了不少文章和博客,但没有得到任何有用的信息,我也找不到任何有关它的文档。
任何帮助,将不胜感激。
提前致谢。
答案 0 :(得分:129)
我刚解决了类似的问题。
如果通过从最近的应用列表中滑动来杀死应用程序时,如果只是停止服务,则可以执行以下操作。
在您的清单文件中,将stopWithTask
标记为true
作为服务。像:
<service
android:name="com.myapp.MyService"
android:stopWithTask="true" />
但正如你所说,你想取消注册听众并停止通知等,我建议采用这种方法:
在您的清单文件中,将stopWithTask
标记为false
作为服务。像:
<service
android:name="com.myapp.MyService"
android:stopWithTask="false" />
现在在您的MyService
服务中,覆盖方法onTaskRemoved
。 (仅当stopWithTask
设置为false
时才会触发。
public void onTaskRemoved(Intent rootIntent) {
//unregister listeners
//do any other cleanup if required
//stop service
stopSelf();
}
有关详细信息,请参阅my question,其中包含其他部分代码。
希望这有帮助。
答案 1 :(得分:30)
找到一种方法来做到这一点
制作一个这样的服务
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));
现在每当你从android最近清除你的应用程序然后这个方法onTaskRemoved()将执行。
答案 2 :(得分:11)
我解决了类似的问题。如果您想要从最近的任务中滑动并在下次启动它时表现正常,请按照以下步骤操作: -
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
}
答案 3 :(得分:5)
当您按下主页时 - 正在调用您的活动的onPause
和onStop
,所以此时您必须进行所有节省和清理,因为Android平台无法进一步保证将调用onDestroy
或任何其他生命周期方法,因此可以在没有任何通知的情况下终止该进程。
答案 4 :(得分:1)
您需要在调用onPause()
时保存数据。
看看这个生命周期图:
Android Developer
您可以看到应用可能会在onPause()
或onStop()
之后被杀死。
处理您的数据并在onRestart()
\ onCreate()
中恢复。
答案 5 :(得分:1)
我真的不知道为什么即使将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);
〜瞧!
答案 6 :(得分:0)
您无法处理滑动,因为系统只会在不调用任何回调的情况下从内存中删除您的进程。
我已经检查过,在用户调用“最近的应用”屏幕之前,将始终调用onPause()。因此,您需要在onPause方法中保存所有数据,而不检查isFinishing()。
要查看后退按钮,请使用onBackPressed方法。
答案 7 :(得分: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));
答案 8 :(得分:0)
ViewModel.onCleared()很有用,如果目标是在用户通过轻扫而不是通过按“停止”键来执行意外退出时释放某些资源(也许是系统在网络上其他地方运行的系统)按钮。 [这是我最初提出这个问题的方式。]
应用程序未收到通知,Activity.onDestroy()被要求进行配置更改(例如方向更改),因此答案不存在。但是,当滑动应用程序时(以及用户退出活动时),将调用ViewModel.onCleared。如果要使用的资源与堆栈中的多个活动相关联,则可以添加引用计数或其他某种机制来确定ViewModel.onClear是否应释放该资源。
这是使用ViewModel的许多很好的理由。
-鲍勃
答案 9 :(得分:0)
正如鲍勃·克拉姆(Bob Cram)在回答中提到的那样, View Model的onCleared()方法就是答案。 在两种情况下都可以使用:
当用户从后台滑动应用程序时,该服务的onTaskRemoved()将起作用,但是使用“全部杀死”按钮清除该应用程序时,该服务将不起作用。
但是viewModel的onCleared()方法在两种情况下都有效。您可以使用是否停止远程服务器上正在进行的进程或清除任何任务。
override fun onCleared() {
super.onCleared()
Log.d(TAG , "App Killed")
}