###前提・実現したいこと
Androidアプリを開発しています。作成中のプログラムは「スタートボタンをクリックすると、バックグラウンドにて、一定時間後待機したのち処理を開始する」というものです。
現在は、バックグラウンド処理を途中で停止させる機能を追加実装するところでハマってしまいました。そこでServiceを停止させる方法についてアドバイス頂きたいです。
ソースコード内のコメントの仕方など、初心者で我流のためお見苦しいところがあるかも知れませんが、どうかよろしくお願いいたします。
###発生している問題・エラーメッセージ
疑問1:こちらのServiceはそもそも停止しているのか(ストップボタンを押す押さないで挙動が異なるも、本当に停止しているようには思えない)。
疑問2:停止していない場合に、次にTryするべきことについてアドバイス。
コードを実行して得られるLogはこちらです。
◆ストップボタンを押さない場合
12-18 13:55:33.353 16600-16600/com.example.android.asobisugi D/Check: Inside findLauncherApp: com.sonyericsson.home
12-18 13:55:48.224 16600-16600/com.example.android.asobisugi D/Check: I'm inside onCreate() in CountTimeService.class.
12-18 13:55:48.238 16600-16600/com.example.android.asobisugi D/Check: [service starting] I'm inside onStartCommand().
12-18 13:55:48.245 16600-19103/com.example.android.asobisugi D/Check: 1分待機. Thread ID: 13221
12-18 13:56:48.280 16600-19103/com.example.android.asobisugi D/Check: After Thread.sleep() and stopSelf() Thread ID: 13221
12-18 13:56:48.281 16600-16600/com.example.android.asobisugi D/Check: onDestroy()が呼出。Thread ID: 1
◆ストップボタンを押した場合
12-18 13:59:18.976 16600-16600/com.example.android.asobisugi D/Check: I'm inside onCreate() in CountTimeService.class.←スタートボタン押下
12-18 13:59:18.978 16600-16600/com.example.android.asobisugi D/Check: [service starting] I'm inside onStartCommand().
12-18 13:59:18.982 16600-19369/com.example.android.asobisugi D/Check: 1分待機. Thread ID: 13224
12-18 14:00:19.020 16600-16600/com.example.android.asobisugi D/Check: onDestroy()が呼出。Thread ID: 1←ストップボタン押下
12-18 14:00:19.020 16600-19369/com.example.android.asobisugi D/Check: After Thread.sleep() and stopSelf() Thread ID: 13224
###該当のソースコード
※Serviceの停止処理はMainActivityから行うようにしています。(下部参照)
public class CountTimeService extends Service {
private final String TAG = "Check"; // onCreate()にて初期化 private Looper mServiceLooper; private ServiceHandler mServiceHandler; String action; String launcherPackName; // Looperから受け取る処理を実行するHandlerを継承したクラス private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { try { Log.d(TAG, "1分待機. Thread ID: " + Thread.currentThread().getId()); Thread.sleep(60000); } catch (InterruptedException e) { // Restore interrupt status. Thread.currentThread().interrupt(); } stopSelf(msg.arg1); Log.d(TAG, "After Thread.sleep() and stopSelf() Thread ID: " + Thread.currentThread().getId()); } } @Override public void onCreate() { Log.d(TAG, "I'm inside onCreate() in CountTimeService.class."); // 別スレッドを生成 HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); // Get the HandlerThread's Looper and use it for our Handler mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "[service starting] I'm inside onStartCommand()."); Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); action = intent.getAction(); launcherPackName = intent.getPackage(); Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; mServiceHandler.sendMessage(msg); return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Log.d(TAG, "onDestroy()が呼出。Thread ID: " + Thread.currentThread().getId()); Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); }
}
※MainActivityのonCreate()にて以下のclickListenerから停止のIntentを投げる仕組み。
Button stopBtn = (Button) findViewById(R.id.stop_btn); stopBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent( MainActivity.this, CountTimeService.class); stopService(intent); Log.d("Check", "stopService()を実行。 Thread ID: " + Thread.currentThread().getId()); } });
###試したこと
【経過】
①IntentServiceを使ってバックグラウンド処理を実装。
→順次処理のため?、停止対象のIntentServiceが完了するまで停止処理が実行されない。
→booleanの変数を追加し、プログラムの要所要所にIf文でstopSelf()/stopService()を呼び出すようにした(https://stackoverflow.com/questions/11258083/how-to-force-an-intentservice-to-stop-immediately-with-a-cancel-button-from-an-a)。スレッドが違うからか?うまくいかない。
②AsyncTaskを使うことも考えたが、長時間処理には非推奨のため断念(使い方によっては30分~数時間動作する想定)。
③ノーマルなServiceを使ってみた(※現在)
###補足情報(言語/FW/ツール等のバージョンなど)
あなたの回答
tips
プレビュー