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 件のコメント:
コメントを投稿