#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((ソースは様々なサイトの記述を参考にさせていただいています(部分部分は結構そのままだったりします、ごめんなさい)。&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: [[[android>日記/Category/android]]] - 06:18:55
~
RIGHT:&blog2trackback();
#comment(above)
#blog2navi()