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