2015-03-17 3 views
1

Я прочитал каждый вопрос о Android, AlarmManager и отмене.Не удалось отменить повторный будильник Android

я в настоящее время использую Activity начиная приемник через:

long msInterval = 1; 
Intent intent = new Intent(this, Updater.class); 
intent.setAction("theAction"); 

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 12, intent, 0); 
Updater.origin = pendingIntent; 

AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); 
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (msInterval), msInterval, pendingIntent); 

Это запускает приемник Updater одну миллисекунду после того, как этот код был вызван, с запросом кодом 12 (выбираются произвольно, используя 0 производит то же самое некорректное поведение) , Он также устанавливает источник обновления для текущего запланированного PendingIntent, который позже используется для отмены тревоги.

Updater выглядит следующим образом:

public class Updater extends BroadcastReceiver { 

    public static int flaggedClose = 0; 
    public static PendingIntent origin; 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     // Do some work 
     Log.w("running", "run"); 

     if (Updater.flaggedClose != 0) { 
      if(flaggedClose == 1) { 
       Toast.makeText(context, "Finished!", Toast.LENGTH_SHORT).show(); 
      } 
      flaggedClose++; // Only show Toast once 
      Log.w("running", "close"); 

      origin.cancel(); 
      AlarmManager alarms = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 
      alarms.cancel(origin); 
     } 
    } 
} 

Что она делает в данный момент, это просто войти сообщение «Выполнить», которое сделано ~ 1000 раз/сек. Когда вызывается действие onStop(), Updater.flaggedClose установлено в 1. Я вижу это в Logcat, так как он начинает печатать предупреждение журнала «закрыть». Тем не менее, будильник все еще включен, поэтому каждое другое зарегистрированное сообщение «запускается», а все остальные «закрываются». В лучшем случае сигнал тревоги закрывается через несколько секунд. В худшем случае мне нужно перезагрузить телефон. В описании AlarmManager в нем указано, что закрытие закрывается «Любая тревога любого типа, чье намерение соответствует этому (как определено filterEquals (Intent)), будет отменено». Почему все еще срабатывает тревога?

+0

Что вы подразумеваете под будильником не отменяете? – Apurva

+0

@apurva: Тревога все еще срабатывает. Я надеялся, что он будет «закрываться» один раз, затем «alarms.cancel (origin)», «отменит все аварийные сигналы и, таким образом, больше не будет регистрироваться сообщение. Сейчас я вижу, по меньшей мере, еще 100 зарегистрированных сообщений, что означает, что должно быть еще 100 тревог. – Pphoenix

+0

@Pphoenix вы можете увеличить интервал тревоги до чего-то значительно большего (для целей тестирования)? 1 мс довольно короткий, мне интересно, эти 100 «лишние» тревоги уже срабатывают до того, как произойдет отмена. Я не уверен, что 'AlarmManager' предназначен для вашего прецедента. http://developer.android.com/reference/android/app/AlarmManager.html прочитал примечание в * bold * –

ответ

1

Как указано в комментариях, возможно, что «эти 100« лишних »сигналов тревоги уже срабатывали до отмены. Для любого другого, у кого есть такая же проблема, вот решение. Я тестировал AlarmManager и, похоже, работал лучше всего, если у вас есть задержка не менее 200 мс. для более низкой задержки используйте Handler. Пример из вопроса с помощью обработчика:

public class MainActivity extends Activity { 

    private boolean pressed = false; 
    private boolean done = false; 
    private Handler worker; 
    private Runnable method; 
    long msInterval = 1; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     worker = new Handler(); 
     method = getMethod(); 

     Button toggle = (Button)(findViewById(R.id.toggle)); 
     toggle.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       if(!pressed) { 
        worker.post(method); 
        pressed = true; 
       } else { 
        done = true; 
       } 
      } 
     }); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     done = true; 
    } 

    private Runnable getMethod() { 
     return new Runnable() { 
      public void run() { 
       Log.w("running", "run"); 
       if (done) { 
        Toast.makeText(getApplicationContext(), "Finished!", Toast.LENGTH_SHORT).show(); 
        Log.w("running", "close"); 
       } else { 
        worker.postDelayed(method, msInterval); 
       } 
      } 
     }; 
    } 
} 

На первом нажатии кнопки обработчик запускается исполняемым, и на каждом вызове с выполняемым называет себя. При втором нажатии на кнопку done устанавливается значение true, поэтому runnable заканчивается после одного раунда (очистки).

Смежные вопросы