最も簡単に実装するには、Serviceクラスでなく、IntentServiceクラスを利用することです。その場合下記の例のようになります。ServiceクラスそのものはUIスレッドで動作するため、ブロックしないために通常はスレッドを作って、そちらで処理を実行しますが、IntentServiceはそのような面倒な処理がすべて実装されていて、コンストラクタとスレッドで実行する処理内容をonHandleIntent()をオーバーライドして実装するだけです。onHandleIntentはもちろん別スレッドで実行されます。
例:呼び出し側のstartService()
startService(new Intent(getApplicationContext(), SampleService.class));
例:受け取り側のService
public class SampleService extends IntentService { public SampleService() { super("SampleService"); } @Override protected void onHandleIntent(Intent intent) { Log.i(TAB,"onHandleIntent"); // Execute something... } }
あえてService()で実装しなければいけないケースは、マルチスレッドで同時実行したい特殊な例だけです。IntentServiceはシングルスレッドのため、実行中に次の要求(startService())がきた場合はキューイングされ、逐次実行になります。すべての処理がおわるとIntentServiceは終了します。
参考までにあえてIntentServiceと同じ動作をするものをServiceを使って作成すると下記のようになります。
public class SampleService extends Service { private ServiceHandler mServiceHandler; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // Execute something... // Stop the service with start id stopSelf(msg.arg1); } } @Override public void onCreate() { // Create and start new thread and handler HandlerThread thread = new HandlerThread("SampleService", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceHandler = new ServiceHandler(thread.getLooper()); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // Create message Message msg = mServiceHandler.obtainMessage(); // Set start id msg.arg1 = startId; // Send message mServiceHandler.sendMessage(msg); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } }
簡単に説明するとonCreate()でThreadとHandlerを新規作成します。Handlerは継承したユーザークラスを作り、handleMessage()に処理を記述します。startService()するとonStartCommand()がコールされ、Handlerから生成したMessageをThreadに送信し、Thread上でそのMessageとともにhandlerMessage()が実行されます。
マルチスレッドにする場合はonCreate()ではなくonStartCommand()がくるたびにスレッドを生成するようにするなど工夫する必要があります。
参考:Android Developers:Services
No comments:
Post a Comment