skimemo


skimemo - 日記/2013-08-18/WakeLockじゃなくてAlarmManagerを使って定期的な処理を継続する の変更点


#blog2navi()
*WakeLockじゃなくてAlarmManagerを使って定期的な処理を継続する [#g3b90759]

バックグラウンドで処理を行いたい場合、Sleepしてしまうと処理が止まってしまうため、WakeLockを使うといいように書いてあったりします。~
[[http://techbooster.org/android/application/4429/:http://techbooster.org/android/application/4429/]]~

私もSleep中に処理が止まってしまうのに悩んでいたので、「これだっ」と思って早速実装してみましたが、どうも一度寝てしまうと起きてくれません。~
同じ事に悩んでいる人はいるらしく、検索していると&color(red){WakeLockはWake状態をLockするためのもので、SleepをWakeするためのものではない};事が分かりました。~
[[http://stackoverflow.com/questions/16450947/how-to-wake-the-android-device-from-deep-sleep-using-wake-lock:http://stackoverflow.com/questions/16450947/how-to-wake-the-android-device-from-deep-sleep-using-wake-lock]]~

上記の記事ではAlarmManagerを使えとあり、試してみたところうまくいったので簡単にまとめてみます。~
~
概要としては、ServiceからAlarmを仕掛け、Alarmが起動したらcallbackしてService内の処理を実行します。~
~
まずはService内からAlarmを仕掛けます。~
~
InfoTransferService.java((ソースは様々なサイトの記述を参考にさせていただいています(部分部分は結構そのままだったりします、ごめんなさい)。~でも大変助かっています、ありがとうございます。))
InfoTransferService.java((ソースは様々なサイトの記述を参考にさせていただいています(部分部分は結構そのままだったりします、ごめんなさい)。&br;でも大変助かっています、ありがとうございます。))
#code(java){{

private InfoTransferBroadcastReceiver ibr;
private Integer interval = 0;	// Interval

@Override
public void onCreate() {
		:(略)
    // AlarmのListener & broadcastを仕掛ける
    ibr = new InfoTransferBroadcastReceiver();
    IntentFilter alarmFilter = new IntentFilter();
    this.registerReceiver(ibr, alarmFilter);
    ibr.setListener(this);  // callback用のリスナー
		:(略)
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
		:(略)
	interval = Integer.parseInt(intent.getStringExtra("interval"));  // intervalをUIから受け取る例
	createTimer();	// intervalを受け取った後に実行
		:(略)
}

@Override
public void onDestroy() {
		:(略)
	// Alarmのキャンセル
	cancelTimer();
	// AlarmのListenerを外す
	ibr.removeListener();
	// Alarm用Broadcast解除
	unregisterReceiver(ibr);
		:(略)
}

// Alarmセット
private void createTimer() {
	Intent i = new Intent(this, InfoTransferBroadcastReceiver.class); // Receiverを呼び出すインテントを作成
	PendingIntent sender = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); // 既存の仕掛けがあったらCancel
    	 
	long firstTime = SystemClock.elapsedRealtime();
	firstTime += interval*1000;  // 本当は、intervalがヘンな値だったら仕掛けないようにした方が良い
	AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); // AlramManager取得
	// 繰り返し設定
	am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, interval*1000, sender);
}
private void cancelTimer() { 
	Log.d(TAG,"cancelTimer");
	//タイマーのキャンセル処理
	Intent i = new Intent(this, InfoTransferBroadcastReceiver.class); // Receiverを呼び出すインテントを作成
	PendingIntent sender = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); // 既存の仕掛けがあったらCancel
	AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); // AlramManager取得
	am.cancel(sender);
}
/**
 * WakeUp時の処理。Receiverからcallbackで呼ばれる。
 */
public void wakeupAlarm() {
	Log.d(TAG,"wakeupAlarm");
	// 処理を書く
}
}}
InfoTransferBroadcastReceiver.java
#code(java){{
public class InfoTransferBroadcastReceiver extends BroadcastReceiver {
	
	static private InfoTransferBroadcastReceiverInterface listener = null;
	static final String TAG = "InfoTransferBroadcastReceiver";

	@Override
	public void onReceive(Context context, Intent intent)
	{
		Log.d(TAG,"onReceive");
		listener.wakeupAlarm();
	}
	// Listener set
	public void setListener( InfoTransferBroadcastReceiverInterface listener ){
		Log.d(TAG,"setListener");
		InfoTransferBroadcastReceiver.listener = listener;
	}
	// Listener delete
	public void removeListener(){
		Log.d(TAG,"removeListener");
		InfoTransferBroadcastReceiver.listener = null;
	}

}
}}
InfoTransferBroadcastReceiverInterface.java
#code(java){{
public interface InfoTransferBroadcastReceiverInterface extends EventListener {
	public void wakeupAlarm();
}
}}
これでソースの実装は完了です。~
しかし、実はここまで書いてもAlarmは起動してくれません。色々調べてみると、manifestファイルにReceiverの記述が必要なことが分かりました。~
~
AndroidManifest.xml
#code(xml){{
		:(略)
	<receiver android:name="InfoTransferBroadcastReceiver" />
		:(略)
}}
ここについうっかり''android:process=":remote"''とか書いてしまうと、Alarmで起動されるたびにlistenerがnullになってしまい、callbackできません。android:processはしていしないようにしましょう。
----
#htmlinsert(20130818_alarm.html)
----
RIGHT:Category: &#x5b;[[android>日記/Category/android]]&#x5d; - 06:18:55
~
RIGHT:&blog2trackback();
#comment(above)
#blog2navi()