実現したいこと
AndroidのService内で15秒毎にサーバにリクエストを投げる
Java
1package net.aaa.sample; 2 3import android.app.Service; 4import android.content.Context; 5import android.content.Intent; 6import android.os.Handler; 7import android.os.IBinder; 8import android.util.Log; 9 10import net.aaa.sample.MyLoader; 11 12import org.json.JSONObject; 13 14import java.util.ArrayList; 15import java.util.Date; 16import java.util.List; 17import java.util.Timer; 18import java.util.TimerTask; 19 20/** 21 * Reference: 22 * http://blog.oukasoft.com/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0/%E3%80%90android%E3%80%91%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%EF%BC%88service%EF%BC%89%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%90%E3%83%83%E3%82%AF%E3%82%B0%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89/ 23 */ 24public class MyService extends Service { 25 26 private static boolean running = false; 27 28 private Timer mTimer = null; 29 Handler mHandler = new Handler(); 30 private Context context; 31 32 public MyService() { 33 } 34 35 @Override 36 public void onCreate() { 37 Log.i("MyService", "onCreate"); 38 context = this.getApplicationContext(); 39 } 40 @Override 41 public int onStartCommand(Intent intent, int flags, int startId) { 42 Log.i("MyService", "onStartCommand"); 43 44 if(running){ 45 return START_STICKY; 46 } 47 48 mTimer = new Timer(true); 49 mTimer.schedule( new TimerTask(){ 50 @Override 51 public void run(){ 52 mHandler.post( new Runnable(){ 53 public void run(){ 54 Log.d( "MyService" , "Timer run" ); 55 bgMain(); 56 } 57 }); 58 } 59 }, 1000, 1000*15); 60 61 running = true; 62 63 return START_STICKY; 64 } 65 66 @Override 67 public IBinder onBind(Intent intent) { 68 Log.i("MyService", "onBind"); 69 return null; 70 } 71 72 // 15秒に一度この関数が呼ばれserverにアクセスします 73 private void bgMain() { 74 // get data from server 75 MyLoader asyncJsonLoader = new MyLoader(new MyLoader.AsyncCallback() { 76 // 実行前 77 public void preExecute() { 78 } 79 80 // 実行後 81 public void postExecute(JSONObject result) { 82 // do something 83 //... 84 } 85 86 // 実行中 87 public void progressUpdate(int progress) { 88 } 89 90 // キャンセル 91 public void cancel() { 92 } 93 }); 94 // 処理を実行 95 asyncJsonLoader.executeWithDto(context); 96 } 97}
問題
ある条件下で、指定したはずの15秒毎に実行されず、数分〜数時間毎に実行されてしまいます。
画面を切るとこの問題が起きはじめ、3分以内に30秒毎くらいの間隔に落ちます。時間が立つとさらにこの遅れは拡大してゆき、最終的に1時間以上に広がることもあります。
再現条件
少なくともAndroid 6.0.1(実機)とAndroid 4.1.2(実機)で問題が起こることを確認しています。
・Androidの電源ボタンを一度押し、画面をOffにすると問題が再現します
・ただし画面がOffであっても充電中の場合は問題は起きませんでした(このためDebugが非常に困難です。Timerの中でサーバにアクセスしているので、そのサーバのaccessログを見ることで問題を確認しました)
質問
いかなる状況であってもTimerを必ず15秒毎に実行したいのですが、どのように書き換えればよいでしょうか?
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/02/28 16:16
2016/02/29 09:12