java.util.Timerよりjava.util.concurrent.ScheduledExecutorServiceのほうが柔軟
サービスの中でタイマー処理を入れようとTimerを使ったのですが、停止と再開の処理が難しく例外が多く出ました。Javaの1.5より追加された、concurrentを使うようです。
concurrentのScheduledExecutorServiceを使うと思った操作になりました。
これを使って、ネットワーク接続を監視するサービスを作りました。3GChekerという名前で公開しています。
ソース貼っときます。
package jp.co.acl_inc.G3Checker; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.Vibrator; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; public class ChekerService extends Service{ private Context context = this; private Timer timer = new Timer(true); private final Handler handler = new Handler(); private ScheduledExecutorService service; private ScheduledFuture future = null; /** * サービスをはずすときの処理です。 */ @Override public boolean onUnbind(Intent intent) { stopSelf(); service.shutdown(); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); service.shutdown(); } /** * startServiceでサービスが呼ばれたときに最初に呼ばれる処理です。 */ @Override public void onCreate() { super.onCreate(); service = Executors.newSingleThreadScheduledExecutor(); Log.d("--ACL--", "Start Service On Create"); } @Override public IBinder onBind(Intent arg0) { return iChekerServiceBinder; } /** * サービスをバインドします。 */ private final IChekerService.Stub iChekerServiceBinder = new IChekerService.Stub() { //チェックサービスをスタートします。 public void startChecker() throws RemoteException { future = service.scheduleAtFixedRate(r, 0, 60 * 1000, TimeUnit.MILLISECONDS); Log.d("--ACL--", "start checker"); } //チェックサービスをストップします(サービスの一時停止)。 public void stopChecker() throws RemoteException { if (future != null) { future.cancel(true); } Log.d("--ACL--", "stop checker"); } }; /** * スケジュールタスク */ Runnable r = new Runnable() { @Override public void run() { handler.post(new Runnable() { public void run() { myTask(); } }); } }; /** * タイマータスク */ private TimerTask timerTask = new TimerTask() { @Override public void run() { handler.post(new Runnable() { public void run() { myTask(); } }); } }; /** * タスクの実処理 */ private void myTask() { Log.d("--ACL--", "In Run of Service"); ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo ni = cm.getActiveNetworkInfo(); TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE); if( ni == null ){ Toast.makeText(context, "ネットワークに接続していません。", Toast.LENGTH_SHORT).show(); openActivity(); Log.d("--ACL--", "Network is null"); vibrate(); } else { Log.d("--ACL--", ni.toString()); if (ni.getType() == ConnectivityManager.TYPE_MOBILE) { if(!ni.isAvailable()) { Toast.makeText(context, "ネットワークが非活性です。", Toast.LENGTH_SHORT).show(); openActivity(); Log.d("--ACL--", "Not Available"); vibrate(); } if (!ni.isConnected()) { Toast.makeText(context, "ネットワークに接続していません。", Toast.LENGTH_SHORT).show(); openActivity(); Log.d("--ACL--", "Not Connected"); vibrate(); } } } } /** * バイブレーション */ private void vibrate() { Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); long[] pattern = {1000, 1000, 1000, 1000, 1000, 1000}; vibrator.vibrate(pattern, -1); } /** * アクティビティを開く */ private void openActivity() { Intent i = new Intent(getApplicationContext(),G3CheckerAvtivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(i); } }