private void stopAlert(Alarm alarm) {
   mVibrator.cancel();
   mCondition.open();
   mNotificationManager.cancel(alarm.hashCode());
   Log.d(TAG, "Stoped the alert.: " + alarm.dump());
   stopSelf();
 }
  @SuppressWarnings("deprecation")
  private void showNotification(Alarm alarm) {
    String title = getString(R.string.app_name) + ": " + alarm.getLavel();
    String message = "アラームは" + alarm.getDuration() + "分間鳴って停止しました。"; // TODO リソースへ
    String ticker = title;

    Notification notification =
        new Notification(R.drawable.ic_launcher, ticker, System.currentTimeMillis());
    Intent doNothing = new Intent();
    notification.setLatestEventInfo(
        this, title, message, PendingIntent.getActivity(this, 0, doNothing, 0));

    mNotificationManager.notify(alarm.hashCode(), notification);
  }
 private void startAlert(Alarm alarm) {
   // TODO 勝手にアラートが停止するようなら、foregroundにすることを検討。
   // foregroundにする場合は目的地到着のNotificationもここで行うべきか。
   // APIではonStartCommand()の間はforegroundと定義されているので問題ない
   // はずだが。Vibratorのスレッドまで停止されることがあるかもしれない。
   // startForeground(id, notification);
   // stopForeground(removeNotification);
   mCondition.close();
   vibrate(alarm);
   Log.d(TAG, "Started the alert.: " + alarm.dump());
 }
 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
   Log.d(TAG, "Start onStartCommand()");
   Alarm alarm = Alarm.find(intent.getExtras().getLong("alarm.id"));
   boolean isStop = intent.getExtras().getBoolean("action.stop"); // TODO Intent.ACTIONを使ったほうが良い?
   if (isStop) {
     stopAlert(alarm);
   } else {
     startAlert(alarm);
   }
   return START_NOT_STICKY;
 }