Intentによるサービス起動

Last-modified: 2013-07-06 (土) 17:08:13

サンプルとして、起動後にカウントダウンを実行し、ゼロになったら終了するサービスと、
そのサービスを起動するアクティビティを例に解説します。

 

アクティビティの作成

サービスを起動するアクティビティを作成します。
ボタンを一つだけ配置したServiceStartActivityを用意します。

 

  fileServiceStartActivity.java …サービスを起動するアクティビティクラス。
  fileservice_start.xml …レイアウトファイル

 

Intentによるサービスの起動

ServiceStartActivityでは、ボタンのクリック時にサービスの起動処理を行っています。

Intent intent = new Intent(ServiceStartActivity.this, CountDownService.class);
startService(intent);

Intentによるサービスの起動はアクティビティの起動によく似ていますが、
Activity起動の時とは違い、コンストラクタには送信元のContextと、起動するServiceのクラスを指定します。
Intentを生成したらContextのstartService()メソッドを利用して、起動を実行します。

 

サービスの作成

処理を実行するサービスを作成します。
サンプルでは、以下のクラスから構成されるサービスを作成します。
(以降のサンプルソースのパッケージは"org.sample.service"となっています。)

 

  fileCountDownService.java …サービス本体。起動時、終了時のメッセージ表示とCountDownThreadの実行。
  fileCountDownThread.java …カウントダウンの実行スレッド。
  fileShowCountToastThread.java …カウント表示スレッド。

 

サービスはServiceクラスを継承し、onStart()メソッドにサービスが実行する処理を実装します。

public class CountDownService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onStart(Intent intent, int startId) {
        Toast.makeText(this, "Service has been started.", Toast.LENGTH_SHORT).show();
        CountDownThread thread = new CountDownThread(this);
        thread.start();
    }
    @Override
    public void onDestroy() {
        Toast.makeText(this, "Service has been terminated.", Toast.LENGTH_SHORT).show();
    }
}

Serviceクラスを継承すると、onBind()を実装する必要があります。
クライアントからのサービスのバインドに応答しない場合は、nullを返すようにします。

 

カウントダウンの処理を実際に行うのはCountDownThreadクラスです。
CountDownThreadのコンストラクタにはオーナーであるServiceのContextを指定するようにします。

public CountDownThread(Context context) {
    mContext = context;
    mHandler = new Handler();
}

また、コンストラクタではメッセージ表示の為にHandlerインスタンスを生成し、
run()メソッドにおいて、カウントを表示する要求をHandlerにpost→1秒待機を10回繰り返す処理を行っています。

@Override
public void run() {
    try {
        for (int count = MAX_COUNT; count >= 0; count--) {
            mHandler.post(new ShowCountToastThread(mContext, count));
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    …
}

Threadで行われる処理の中で、画面更新などのUIスレッドに関わる処理をそのまま実行しようとすると、
エラーが発生します。
これはAndroidがシングルスレッドモデルを採用している為で、AsynTaskの場合と同様に、
Handlerに画面更新のタイミングを委ねる必要があります。

 

IntentによるServiceの停止

CountDownThreadでは、処理が完了するとオーナーであるServiceの停止を実行します。
Intentを利用したServiceの停止はサービス起動時と同様にContextのstopService()メソッドを利用します。

Intent intent = new Intent(mContext, CountDownService.class);
mContext.stopService(intent);
 

AndroidManifest.xmlへの登録

作成したサービスをアプリケーションで実行する場合には、
"service"タグを使用してマニフェストファイルに登録します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.sample.service"
    android:versionCode="1"
    android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".ServiceStartActivity" 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は "service"タグを利用してマニフェストファイルに登録する -->
        <service android:name=".CountDownService" />
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>