22

Bluetooth通信を使用して(独自のプロトコルを使用して)Androidアプリを開発していますが、アプリが強制終了された瞬間を捉える必要があります。

「onDestroy()」メソッドを使用したかったのですが、アプリが強制終了されるたびに呼び出されるわけではありません。戻るボタンを押すと呼び出され、タスクマネージャーからアプリを強制終了すると呼び出されることがあります。

問題は、アプリが強制終了される前の瞬間をどのように捉えることができるかということです。

これが私が使おうとしたコードです:

@Override
public void onDestroy() {
    sendMessage(msg);
    Log.d("SampleApp", "destroy");
    super.onDestroy();
}

@Override
public void finish(){

    sendMessage(msg);
    Log.d("SampleApp", "finish");
    super.finish();
}

残念ながら、finish()が呼び出されることはなく、タスクマネージャーからアプリを閉じるたびにonDestroyが呼び出されることもありません。

どうすればこれを処理できますか?

4

3 に答える 3

15

プロセスが外部手段によって終了した場合(つまり、メモリ上の理由でアプリケーションが強制終了された場合、またはユーザーがアプリケーションを強制的に停止した場合)、アプリケーションは追加のコールバックを受け取りません。アプリがアプリケーションのクリーンアップのためにバックグラウンドに入ったときに受け取ったコールバックを処理する必要があります。

finish()は、ユーザーがアクティビティから[戻る]ボタンを押したときにのみシステムによって呼び出されますが、多くの場合、アプリケーションから直接呼び出されて、アクティビティを終了して前のアクティビティに戻ります。これは技術的にはライフサイクルコールバックではありません。

onDestroy()への呼び出しの結果としてのみアクティビティで呼び出されるfinish()ため、主にユーザーが[戻る]ボタンを押したときにのみ呼び出されます。ユーザーがHOMEボタンを押すと、フォアグラウンドアクティビティは通過するだけonPause()ですonStop()

これは、Androidがアクティビティに多くのフィードバックを提供して、ホームに移動するユーザーと別のアクティビティに移動するユーザーを区別することを意味します(アプリまたはその他から)。アクティビティ自体は、それがもはやフォアグラウンドにないことを単に知っています。Androidアプリケーションは、緊密に統合された単一の概念よりも緩いアクティビティのコレクションであるため(他のプラットフォームで慣れているように)、アプリケーション全体がいつ進められたか、移動されたかを知るための実際のシステムコールバックはありません。後方。

最終的には、アプリケーションのアクティビティがフォアグラウンドにあるかどうかの知識に依存している場合は、アプリケーションアーキテクチャを再検討することをお勧めしますが、ニーズによっては、これを実現するためのフレームワークに適した方法が他にもある場合があります。1つのオプションは、アクティブな間(つまり、との間)Serviceにすべてがバインドするアプリケーション内にバインドを実装することです。これにより、バウンドはクライアントがバウンドしている間だけ存続するという事実を活用できるため、サービスのメソッドとメソッドを監視して、現在のフォアグラウンドタスクがアプリケーションの一部ではないことを知ることができます。ActivityonStart()onStop()ServiceonCreate()onDestroy()

また、Dianne Hackbornによって書かれたこの記事は、Androidアーキテクチャと、それを使用する必要があるとGoogleがどのように考えているかをより詳細にカバーしているので興味深いと思うかもしれません。

于 2012-07-13T16:11:35.850 に答える
15

ここのドキュメントに記載されているように、onDestroy()が呼び出される保証はありません。代わりに、onPause()を使用して、アプリがバックグラウンドに移動するたびに実行したいことを実行し、アプリが強制終了されたときに実行するコードのみをonDestroy()に残します。

編集:

コメントから、アプリがバックグラウンドに移行するたびにコードを実行したいようですが、インテントを起動したためにバックグラウンドに移行した場合は実行しません。AFAIK、Androidにはデフォルトでこれを処理するメソッドはありませんが、次のようなものを使用できます。

次のようなブール値を使用します。

boolean usedIntent = false;

インテントを使用する前に、ブール値をtrueに設定します。次に、onPause()で、インテントケースのコードを次のようなifブロックに移動します。

if(usedIntent)
{
//Your code
}

最後に、onResume()で、ブール値を再びfalseに設定して、意図しない手段によってアプリがバックグラウンドに移動されたことを適切に処理できるようにします。

于 2012-07-13T15:51:22.703 に答える
2

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

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

マニフェストファイル内で、サービスのフラグ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サービスで、メソッドをオーバーライドしますonTaskRemovedstopWithTask(これは、がに設定されている場合にのみ発生しfalseます)。

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

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

  1. 以下のようなサービスを開始します

startService(new Intent(this、MyService.class));

お役に立てれば。

于 2017-11-16T08:39:24.900 に答える