AlarmManager LifeCycle и ошибка отмены - PullRequest
1 голос
/ 05 марта 2012

У меня есть приложение, которое уже имеет widget и service, которое обновляет этот виджет каждые 5 секунд.

Вот мои AppWidgetProvider:

public class MyWidget extends AppWidgetProvider {

    PendingIntent service = null;
    AlarmManager alarmManager;

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final Intent i = new Intent(context, MyService.class);

        if(service == null) {
            service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
        }

        alarmManager.setRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime(), 1000*5, service);
    }

    @Override
    public void onDisabled(Context context) {
        Log.d("LogTag", "onDisabled");
        alarmManager.cancel(service);
        service.cancel();
    }
}

И мои Service:

public class MyService extends Service {

    int b = 5;

    @Override
    public void onCreate() { super.onCreate(); }

    public int onStartCommand(Intent intent, int flags, int startId) {
        this.buildUpdate();
        return 0;
    }   

    private void buildUpdate() {
        Log.d("AAA", "Update is coming");

        RemoteViews rmViews = new RemoteViews(getPackageName(), R.layout.widget_layout);

        rmViews.setTextViewText(R.id.hello, "Iterator: " + Integer.toString(b));

        ComponentName thisWidget = new ComponentName(this, MyWidget.class);

        AppWidgetManager manager = AppWidgetManager.getInstance(this);

        manager.updateAppWidget(thisWidget, rmViews);

        b++;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

}

Service и другие вещи в порядке.Но все же у меня есть пара вопросов обо всех этих вещах:

  1. Что за SystemClock.elapsedRealtime(), который является параметром в методе setRepeating?Указывает, когда начать?

  2. Когда я пытаюсь удалить виджет, я получаю некоторые ошибки (см. Ниже), и, к сожалению, AlarmManager по-прежнему работает, не отменяется.Чего мне не хватает?

  3. Мне нужно выполнить некоторые сетевые операции перед инициализацией (или вызовом) виджета.Виджет должен иметь некоторые данные с сервера.Должен ли я использовать AsyncTask или что?

Когда я пытаюсь удалить виджет, получаю:

03-04 23:39:51.428: E/AndroidRuntime(5646): Uncaught handler: thread main exiting due to uncaught exception
03-04 23:39:51.438: E/AndroidRuntime(5646): java.lang.RuntimeException: Unable to start receiver com.example.widget.MyWidget: java.lang.NullPointerException
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2646)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.app.ActivityThread.access$3100(ActivityThread.java:119)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1913)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.os.Looper.loop(Looper.java:123)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.app.ActivityThread.main(ActivityThread.java:4363)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at java.lang.reflect.Method.invokeNative(Native Method)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at java.lang.reflect.Method.invoke(Method.java:521)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at dalvik.system.NativeStart.main(Native Method)
03-04 23:39:51.438: E/AndroidRuntime(5646): Caused by: java.lang.NullPointerException
03-04 23:39:51.438: E/AndroidRuntime(5646):     at com.example.widget.MyWidget(MyWidget.java:33)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.appwidget.AppWidgetProvider.onReceive(AppWidgetProvider.java:76)
03-04 23:39:51.438: E/AndroidRuntime(5646):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2637)
03-04 23:39:51.438: E/AndroidRuntime(5646):     ... 10 more

1 Ответ

2 голосов
/ 05 марта 2012
  1. SystemClock.elapsedRealTime(), поскольку он у вас есть, в данный момент он находится в параметре triggerAtTime, что означает, что любое введенное вами число - это время, когда вы хотите, чтобы сработал будильник.elapsedRealtime() считается с момента загрузки системы, включая глубокий сон, в миллисекундах.Эти часы следует использовать при измерении временных интервалов, которые могут охватывать периоды системного сна.

  2. В методе onDisabled вам необходимо воссоздать весь PendingIntent.Я предполагаю, что он нулевой, потому что он на самом деле не существует, когда вы вызываете onDisabled, а существует только в onUpdate.Поэтому воссоздайте service переменную PendingIntent точно так же, как вы делали это раньше, а затем вызовите для нее команду отмены, как вы уже это делаете.

  3. AsyncTask s хороши для таких вещей, кактот.AsyncTask порождает управляемый поток в фоновом режиме и работает, пока поток пользовательского интерфейса продолжает работать, а затем может обновить поток пользовательского интерфейса, когда закончите.Так что, если вам нужно много тяжелых сетей, AsyncTask прекрасно с этим справится.Документы на AsyncTask очень полезны.Найдите их здесь .Есть много вариантов для этого в зависимости от того, что вы делаете, поэтому вам придется объяснить свою проблему по этому третьему пункту чуть более подробно, чтобы получить более индивидуальный ответ.

...