Activityからの呼び出し時にAlarmManagerと併用することにより、
定期的な呼び出しを行うことができる。
AlarmManagerは、引数にPendingIntentを要求するため、
PendingIntentを取得する必要がある。
ただ、特に細かい設定はなく、サービスのIntentを型変換しているような感じだ。
■定期的に動くIntentServiceを作る(AlarmManaerを利用)
1)新規のAndroidプロジェクトを以下のように作成する。
「プロジェクト名」:AlarmManagerIntentService
「ビルドターゲット」:Android 1.6
「パッケージ名」:jp.co.example.alarmmanagerintentservice
「アクティビティ名」:AlarmManagerIntentServiceActivity
2)サービスクラスを作成する。
プロジェクトのsrcのパッケージ配下に、『MyIntentService』クラスを作成
ソース内容は以下の通り。
基本的には、MyIntentServiceクラスをIntentServiceクラスの継承クラスとする。
Seriviceの継承とは異なり、コンストラクターのみ強制オーバーライドであった。
Eclipseのコードアシスタントでは、第一引数ありのコンストラクタを生成してくれる、
しかし、
ActivityからAlarmManagerを利用して呼ぶ場合、引数なしのコンストラクタが必要である。
onHandleIntentメソッドには、ログを入れた。
これは、onHandleIntentがどのスレッドで動くか調べるためだ。
結果、onHandleIntentは、時間毎に新規スレッドが生まれる形で動作した。
以下のコードにおけるIntentServiceは、
Activityと同プロセスだが、別スレッドで動作している。
package jp.co.example.alarmmanagerintentservice; import android.app.IntentService; import android.content.Intent; import android.util.Log; public class MyIntentService extends IntentService { private final String TAG = this.getClass().getSimpleName(); public MyIntentService(String name) { super(name); // TODO 自動生成されたコンストラクター・スタブ Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); } public MyIntentService() { super("MyIntentService"); // TODO 自動生成されたコンストラクター・スタブ Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); } @Override protected void onHandleIntent(Intent intent) { // TODO 自動生成されたメソッド・スタブ Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); } }3)画面にスタートボタン、ストップボタンを作る
res\layout\main.xmlに、ボタンを2つ作成。
ソースは以下のようになる。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:text="Alarm Start" android:id="@+id/start_button" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> <Button android:text="Alarm Stop" android:id="@+id/stop_button" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button> </LinearLayout>
4)サービスをスタート/ストップするアクティビティを作る
以下の処理を行っている。
スタートボタン押下処理をstartAlarmServiceメソッドとした。
ストップボタン押下処理をstopAlarmServiceメソッドとした。
詳細は、ソースコードコメントに記載する。
全体のコードは以下の通り。
package jp.co.example.alarmmanagerintentservice; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class AlarmManagerIntentServiceActivity extends Activity { private final String TAG = this.getClass().getSimpleName(); Button alarmStartButton; Button alarmStopButton; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); setContentView(R.layout.main); findViews(); alarmStartButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO 自動生成されたメソッド・スタブ startAlarmService(); } }); alarmStopButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { // TODO 自動生成されたメソッド・スタブ stopAlarmService(); } }); } protected void findViews() { alarmStartButton = (Button)findViewById(R.id.start_button); alarmStopButton = (Button)findViewById(R.id.stop_button); } protected void startAlarmService() { Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); Context context = getBaseContext(); // サービスのIntentを生成 Intent intent = new Intent(context, MyIntentService.class); // PendingIntentを取得 PendingIntent pendingIntent = PendingIntent.getService( context, -1, // requestCode is currently not used intent, // 起動するサービスのIntent PendingIntent.FLAG_UPDATE_CURRENT //flags: FLAG_CANCEL_CURRENT :過去の設定をキャンセルし現在の設定を使う。 // FLAG_NO_CREATE :存在してなければnullを返す。新規作成しない。 // FLAG_ONE_SHOT :一度だけ使用できる。 // FLAG_UPDATE_CURRENT :過去の設定があればそれを使う。再設定しない。 ); AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); alarmManager.setInexactRepeating( AlarmManager.RTC, // type: // ELAPSED_REALTIME :SystemClock.elapsedRealtime() によるアラーム時間 (スリープを含む起動してからの時間) // ELAPSED_REALTIME_WAKEUP :ELAPSED_REALTIME と同様だが、スリープしている時は起きる // INTERVAL_DAY :一日間隔 // INTERVAL_FIFTEEN_MINUTES:15分間隔 // INTERVAL_HALF_DAY :半日間隔 // INTERVAL_HALF_HOUR :30分間隔 // INTERVAL_HOUR :一時間間隔 // RTC :System.currentTimeMillis() によるアラーム時間 (UTC) // RTC_WAKEUP :RTC と同様だが、スリープしている時は起きる System.currentTimeMillis(), // triggerAtTime 5000, // interval pendingIntent // operation ); } protected void stopAlarmService() { Log.d(TAG, Thread.currentThread().getStackTrace()[2].getMethodName()); Context context = getBaseContext(); // サービスのIntentを生成 Intent intent = new Intent(context, MyIntentService.class); // PendingIntentを取得 PendingIntent pendingIntent = PendingIntent.getService( context, -1, // requestCode is currently not used intent, PendingIntent.FLAG_UPDATE_CURRENT ); AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE); alarmManager.cancel(pendingIntent); } }
5)マニフェストでサービス許可する
AndroidManifest.xmlに<service>タグにサービスクラス名を指定して、以下のようにサービスを許可する。
<application android:icon="@drawable/icon" android:label="@string/app_name"> (略) <service android:name=".MyIntentService"/> </application>
0 件のコメント:
コメントを投稿