49

アクティビティから開始された IntentService があり、アクティビティの「キャンセル」ボタンを使用して、アクティビティからすぐにサービスを停止できるようにしたいと考えています。その「キャンセル」ボタンが押されるとすぐに、サービスがコード行の実行を停止するようにします。

これに似た質問がいくつか見つかりました (つまり、 herehereherehere ) が、適切な回答はありません。 メソッドをすぐに実行しますが、サービスを破棄する前にコードを完全にActivity.stopService()終了Service.stopSelf()させます。Service.onDestroy()onHandleIntent()

サービスのスレッドをすぐに終了する保証された方法は明らかにないため、私が見つけることができる唯一の推奨される解決策 ( here ) は、メソッドで切り替えることができるサービスにブール値のメンバー変数を持ち、onDestroy()ほぼすべての行を持つことです。コードはonHandleIntent()、その変数を参照する独自の「if」句にラップされています。それはコードを書くためのひどい方法です。

IntentService でこれを行うためのより良い方法を知っている人はいますか?

4

9 に答える 9

14

スレッドまたはプロセスをすぐに停止することは、多くの場合、汚いことです。ただし、サービスがステートレスであれば問題ありません。

マニフェストでサービスを別のプロセスとして宣言します。

<service
     android:process=":service"
     ...

その実行を停止したい場合は、そのプロセスを強制終了します。

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();

Iterator<RunningAppProcessInfo> iter = runningAppProcesses.iterator();

while(iter.hasNext()){
    RunningAppProcessInfo next = iter.next();

    String pricessName = getPackageName() + ":service";

    if(next.processName.equals(pricessName)){
        Process.killProcess(next.pid);
        break;
    }
}
于 2014-05-03T12:00:10.020 に答える
7

サービス内で BroadcastReceiver を使用しましたが、これは単に停止ブール値を true に設定するだけです。例:

private boolean stop=false;

public class StopReceiver extends BroadcastReceiver {

   public static final String ACTION_STOP = "stop";

   @Override
   public void onReceive(Context context, Intent intent) {
       stop = true;
   }
}


@Override
protected void onHandleIntent(Intent intent) {
    IntentFilter filter = new IntentFilter(StopReceiver.ACTION_STOP);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    StopReceiver receiver = new StopReceiver();
    registerReceiver(receiver, filter);

    // Do stuff ....

    //In the work you are doing
    if(stop==true){
        unregisterReceiver(receiver);
        stopSelf();
    }
}

次に、アクティビティ呼び出しから:

//STOP SERVICE
Intent sIntent = new Intent();
sIntent.setAction(StopReceiver.ACTION_STOP);
sendBroadcast(sIntent);

サービスを停止するには。

PD: 私はブール値を使用します。私の場合、ループ中にサービスを停止しますが、おそらく onReceive で unregisterReceiver と stopSelf を呼び出すことができるからです。

PD2: サービスが正常に動作している場合は unregisterReceiver を呼び出すことを忘れないでください。そうしないと、リークされた IntentReceiver エラーが発生します。

于 2014-03-20T10:14:31.950 に答える
2
@Override
protected void onHandleIntent(Intent intent) {
    String action = intent.getAction();
    if (action.equals(Action_CANCEL)) {
        stopSelf();
    } else if (action.equals(Action_START)) {
        //handle
    }
}

それがうまくいくことを願っています。

于 2012-12-24T08:37:10.280 に答える
1

を使用している場合は、コードが「停止」信号をポーリングするIntentService必要がある、説明したようなことをしていると思います。onHandleIntent()

バックグラウンド タスクが長時間実行される可能性があり、それを停止できる必要がある場合は、Service代わりにプレーンを使用する方がよいと思います。大まかに言うと、Service を次のように記述します。

  • AsyncTask を開始してバックグラウンド作業を実行する「開始」インテントを公開し、新しく作成された AsyncTask への参照を保存します。
  • 「キャンセル」インテントを公開して呼び出すAsyncTask.cancel(true)か、 onDestroy() を呼び出しAsyncTask.cancel(true)ます。
  • その後、アクティビティは「キャンセル」インテントを送信するか、単に stopService() を呼び出すことができます。

バックグラウンド作業をキャンセルする機能と引き換えに、サービスは次の責任を負います。

  • AsyncTaskdoInBackground()は、InterruptedException を適切に処理するか、定期的に Thread.interrupted() をチェックして、"early" を返す必要があります。
  • サービスは、それstopSelf()が呼び出されることを確認する必要があります (おそらく AsyncTask onPostExecute/onCancelled で)。
于 2014-03-02T21:54:51.487 に答える
-1

サービスを開始/停止するためのサンプルコードを次に示します

始めること、

Intent GPSService = new Intent(context, TrackGPS.class);
context.startService(GPSService);

止まる、

context.stopService(GPSService);

于 2012-06-29T07:59:51.323 に答える
-1
context.stopService(GPSService);
于 2014-03-13T10:14:20.760 に答える