如何通过在Android中刷卡杀死应用程序时处理代码?

时间:2013-10-24 14:08:28

标签: android

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

10 个答案:

答案 0 :(得分:129)

我刚解决了类似的问题。

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

在您的清单文件中,将stopWithTask标记为true作为服务。像:

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

但正如你所说,你想取消注册听众并停止通知等,我建议采用这种方法:

  1. 在您的清单文件中,将stopWithTask标记为false作为服务。像:

    <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();  
    }
    
  3. 有关详细信息,请参阅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)

当您按下主页时 - 正在调用您的活动的onPauseonStop,所以此时您必须进行所有节省和清理,因为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()方法就是答案。 在两种情况下都可以使用:

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

当用户从后台滑动应用程序时,该服务的onTaskRemoved()将起作用,但是使用“全部杀死”按钮清除该应用程序时,该服务将不起作用。

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

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }