Androidでスワイプしてアプリが終了したときにコードを処理する方法は?


104

アプリが実行されているときにホームボタンを押すと、アプリがバックグラウンドで実行されます。長押しホームボタンとは、最近のアプリのリストからそれをスワイプしてアプリを殺す場合さて、イベントのどれも好きなんonPause()onStop()またはonDestroy()プロセスが終了されるという呼び出されます。それで、サービスを停止し、通知を殺し、リスナーの登録を解除したい場合、どうすればよいですか?かなりの数の記事やブログを読みましたが、有用な情報が得られず、それに関するドキュメントも見つかりませんでした。任意の助けいただければ幸いです。前もって感謝します。


問題を解決しました。チェック
MysticMagicϡ

@MysticMagicこれはサービスで機能しますが、通知のキャンセルとリスナーの登録解除についてはどうですか?
CodeWarrior 2014年

onTaskRemovedでリスナーの登録を解除できます。できない?そして、通知をキャンセルするための同じ
MysticMagicϡ

@MysticMagicϡアプリのアップデートで同じことをしたい場合はどうすればよいですか?
reji

回答:


150

同様の問題を解決しました。

最近のアプリリストからスワイプしてアプリケーションが強制終了されたときにサービスを停止する場合にできることを次に示します。

マニフェストファイル内で、ServiceとstopWithTask同じようにフラグを維持trueします。お気に入り:

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

ただし、リスナーの登録を解除して通知を停止したいという場合は、このアプローチをお勧めします。

  1. マニフェストファイル内で、Serviceと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();  
    }

コードの他の部分も含まれている詳細については、私の質問を参照しください。

お役に立てれば。


ありがとう。この方法がスワイプのキルを識別するために使用できるかどうか考えています。シンプルな空のサービス?
キラン2014年

はい@Kiran試すことができます。:)
MysticMagicϡ

1
@MysticMagicϡこんにちは、1つの質問です。ソリューションを使用してみましたが、サーバーへのデータ送信、Googleへの分析などの長い操作がうまくいかない場合があります。このメソッドが完全に完了する前にプロセスが強制終了された可能性がありますか?また、Huaweiデバイスでこの方法を試しましたか?これらのデバイスではonTaskRemovedが呼び出されないようです。なぜ何かアイデア?
Alon Minski、2016

2
@MysticMagicϡpublic void onTaskRemoved(..)メソッドがAndroid Oで呼び出されない。他のOSでは問題なく機能するが、Android Oでは問題が発生する
Jay Patel

2
このコードは、バックグラウンドでのサービス制限のため、Android Oでは機能しません。すべてのAndroidデバイスでこれを処理する方法はありますか?
Aanal Mehta

33

これを行う1つの方法が見つかりました

このような1つのサービスを作ります

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()が実行されます。


1
この回答から1対1のコピーアンドペースト:stackoverflow.com/questions/21040339
Flot2011

17

同様の問題を解決しました。最近のタスクからスワイプした後で次の起動時に正しく動作するようにしたい場合は、以下の手順に従ってください:

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
}

うまく行って-確認済み- service.onTaskRemoved()なしにAndroidの8で使用
ギャルローマ

4
このソリューションは、アプリが再起動されたかどうかのみを検出しますが、アプリが
強制終了

6

あなたが家を押すと- onPauseonStopあなたの活動のAndroidプラットフォームにはないので、その更なる保証なので、この時点では、すべての貯蓄とクリーンアップをしなければならない、と呼ばれているonDestroyか、他のライフサイクルメソッドが呼び出されるので、プロセスが殺される可能性が通知なし。


12
提案をありがとう、しかし私は私の通知、サービス、リスナーを殺したくありません、onPause()そしてonstop()それらはユーザーがアプリを終了するとき、つまりログアウトするときだけ殺される必要があります。
CodeWarrior 2013年

1

on onPause()が呼び出されたときにデータを保存する必要があります。このライフサイクル図を見てください: Android Developer

onPause()またはの後にアプリを強制終了できることがわかりonStop()ます。

そこでデータを処理し、onRestart()\でリカバリしonCreate()ます。

幸運を!


1

システムはコールバックを呼び出さずにメモリからプロセスを削除するだけなので、スワイプを処理できません。

ユーザーが「最近のアプリ」画面を呼び出す前に、onPause()が常に呼び出されることを確認しました。したがって、isFinishing()をチェックせずに、すべてのデータをonPauseメソッドに保存する必要があります。

戻るボタンを確認するには、onBackPressedメソッドを使用します。


1
これがすべてのAndroidバージョンで唯一安全な方法だと思います。
セルジオ

@Sergioはい、これが最も安全な方法であり、大規模なアプリケーションでテストしました。
Ahmad

1

ViewModel.onCleared()は、ユーザーが「停止」やボタンを押すのではなく、スワイプして突然の終了を実行したときに、リソース(おそらくネットワーク上の別の場所で実行されているシステム)を解放することが目的である場合に役立ちます。[これが私が最初にこの質問にたどり着いた方法です]。

アプリケーションは通知を受け取らず、Activity.onDestroy()は、向きの変更などの構成変更のために呼び出されるため、答えはありません。ただし、ViewModel.onClearedは、アプリケーションがスワイプされたとき(およびユーザーがアクティビティから戻ったとき)に呼び出されます。使用するリソースがスタック内の複数のアクティビティに関連付けられている場合、参照カウントまたはその他のメカニズムを追加して、ViewModel.onClearがリソースを解放するかどうかを決定できます。

これは、ViewModelを使用する多くの理由の1つです。

- ボブ


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);

〜出来上がり!


他のコメンターが言及しているように、Android O以上のため、サービスアプローチでは機能しない可能性があります。これは、ビューモデルを使用する興味深いソリューションのようです。これは、アプリケーションが強制終了された(アプリスイッチャー画面で消去された)場合でもトリガーされますか?編集:ボブの答えは、これらのケースで機能することを示唆しています
ウィリアムリード

はい、動作します。それは私が遭遇したケースです
ドロイド

0

これはアンドロイド6,7,8,9で私のために働いた。

次のような1つのサービスを作成します。

 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));

1
そして、なぜあなたのサービスはAndroid 8以上で実行し続けるのですか?Android 8以降のスターテッドサービスに制限があることに気づきましたか?
rahil008

0

Bob Cramが答えで述べたように、View ModelのonCleared()メソッドが答えです。どちらの場合でも機能します。

  1. ユーザーがアプリをバックグラウンドからスワイプして削除したとき。
  2. ユーザーがリストのクリアボタンを使用してすべてのアプリをクリアしたとき。

サービスのonTaskRemoved()は、ユーザーがアプリをバックグラウンドからスワイプすると機能しますが、アプリを[すべて削除]ボタンを使用してクリアすると機能しません。

しかし、viewModelのonCleared()メソッドはどちらの場合でも機能します。ifを使用すると、進行中のプロセスを停止したり、リモートサーバーのタスクをクリアしたりできます。

 override fun onCleared() {
        super.onCleared()
        Log.d(TAG , "App Killed")
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.