IntentServiceを使って非同期処理を行う


IntentServiceはアプリケーションのバックグラウンドで処理を行うための方法です。名前の通り、Serviceを拡張していますので、基本的な扱い方はServiceと同じです。

IntentServiceの特徴

バックグラウンドで処理を行うということは、アプリケーションの動作と関係なく(非同期で)仕事することになります。一般的には以下の処理シーケンスが必要です。

  • 別スレッドを作成
  • 仕事のキューイング
  • 順次とりだして実行する

開発者が毎回作成するには煩雑です。IntentServiceを使えば、これらの処理手順を簡略化、簡単に実行することができます(同一プロセス内で別スレッドを作成するため、厳密にServiceと同じではないようです)。

IntentServiceとAsyncTaskの違い

以前紹介したAsynctaskを使って非同期処理を行う もAndroidアプリケーションのUIスレッドと内部処理を分離する手法の一つです。

動作は似ていますが、IntentServiceはアプリケーションの動作状況に依存しないで、自分の仕事がなくなるまでバックグラウンドで処理を行える利点があります。アプリケーションがフォアグラウンド(前面)に位置していなくても、処理が中断されることがありません。IntentServiceはAsyncTaskと異なり再利用(複数呼び出し)も可能です。

逆に処理中のプログレスバー表示など進捗表示など逐次結果を反映させる処理はAsyncTaskのほうが簡単です。IntentServiceとAsyncTaskは非同期処理の特性に応じて使い分けるべきでしょう。

続きはサンプルコードと注意点です。

AndroidManifest.xmlに登録する

IntentServiceはサービスですのでマニフェストファイルに登録します。

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".IntentServiceActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
	<service android:name="MyIntentService"></service>
    </application>

マニフェストファイルへの登録を忘れるとIntentServiceの呼び出しで失敗してしまいます。特にエラーが出ないため忘れがちなポイントです。注意してください。

IntentServiceを実装する

サービス名のソースファイルを作成します(MyIntentSerfice.javaなど)

public class MyIntentService extends IntentService{

	public MyIntentService(String name) {
		super(name);
		// TODO 自動生成されたコンストラクター・スタブ
	}

	public MyIntentService(){
		// ActivityのstartService(intent);で呼び出されるコンストラクタはこちら
		super("MyIntentService");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		// 非同期処理を行うメソッド。タスクはonHandleIntentメソッド内で実行する
		Log.d("IntentService","onHandleIntent Start");
	}
}

自動生成の使ってIntentServiceを作ると、public MyIntentService(String name)がコンストラクタとして作成されますが、実際には引数がないpublic MyIntentService()コンストラクタが必要です。

IntentServiceの内部では、IntentServiceを起動したあと自動的にワーカースレッドにより仕事のキューイングが行われています。(別スレッドで)サービスは仕事を逐次実行していきます。IntentServiceに複数の仕事(インテント)をキューイングするケースでも、同時に処理できる作業は1つです。

Activityからインテントサービス(非同期処理)を呼び出す

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //MyIntentServiceを起動する
    	Intent intent = new Intent(this, MyIntentService.class);
    	this.startService(intent);
    }

Activity#startService(Intent)を使い、MyIntentServiceを起動します。起動後は何度でもstartService(intent)で仕事をキューイングできます。順次、IntentService#onHandleIntentメソッドが呼び出されて非同期処理を行います。

IntentServiceに引数を渡す

Intent.putExtraを使ってStringなど付加情報の受け渡しが行えます。

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //MyIntentServiceを起動する
    	Intent intent = new Intent(this, MyIntentService.class);
    	intent.putExtra("IntentServiceCommand","TestText");
    	this.startService(intent);
    }

サンプルコードでは、Stringデータなので
IntentService#onHandleIntentでgetStringExtraを使って受け取ります。

	@Override
	protected void onHandleIntent(Intent intent) {
		// 非同期処理を行うメソッド。タスクはonHandleIntentメソッド内で実行する
		Log.d("IntentService","onHandleIntent Start");
		Log.d("IntentService","intent msg:" + intent.getStringExtra("IntentServiceCommand") );
	}

受信例です。

10-26 02:40:57.855: DEBUG/IntentService(478): onHandleIntent Start
10-26 02:40:57.855: DEBUG/IntentService(478): intent msg:TestText
2 Comments