July 6, 2012

startService()で始めるService

startService()で始めるServiceとは、intentを使ってServiceを起動し、バックグラウンドで指定された処理を実行するものです。

最も簡単に実装するには、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