如何创建一个持久的AlarmManager

24

编辑:根据CommonsWare的答复澄清了问题。

我们通过AlarmManager安排定时器,每60秒触发一次。当我们的应用程序被杀死时,我们的闹钟似乎不再执行。有没有办法让这些闹钟在应用程序被手动或系统杀死时仍然持续存在?

对我们来说,这是一个问题,因为我们有一个小部件应用程序显示时间。这意味着我们需要每分钟更新时间。为了避免AppWidgetProvider的onUpdate方法的30分钟更新限制,我们使用AlarmManager。它通常运行得很好,但一些用户报告时间不同步。经过与他们几次交谈后,我怀疑我们的应用程序正在被任务管理器应用程序手动杀死或Android自身正在杀死我们的应用程序。

欢迎任何其他解决根本问题(在小部件中保持时间同步)的替代方案。

以下是我们执行以安排闹钟的代码:

Intent intent = new Intent(UPDATE_TIME);
PendingIntent pIntent = PendingIntent.getBroadcast(ctx,
  0 /* no requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT );

// get alarm params
Date d = new Date();
long timeTilMinuteChange = 60*1000-d.getSeconds()*1000;
long startTime = System.currentTimeMillis() + + timeTilMinuteChange;

AlarmManager am = (AlarmManager) ctx.getSystemService(Context.
am.cancel(pIntent);
am.set(AlarmManager.RTC, System.currentTimeMillis(), pIntent);
        am.setRepeating(AlarmManager.RTC, startTime, 60000, pIntent);

我认为闹钟管理器没有被杀死,但可能是数据变得陈旧了。你使用静态变量了吗?请记住,Android可以(而且将)关闭appwidget进程(它是一个接收器),你是否使用任何绑定到AppWidgetProvider类的变量? - Efi MK
我没有使用静态变量,但是我使用了一个静态类。基本上它的工作方式是我们的AppWidgetProvider调用TimeManager.start(context)。TimeManager.start设置了一个重复的闹钟。 - christoff
@EfiMK 我知道这是一个很久以前的帖子,但是由于我在其他地方找不到答案,请指导一下在appwidgetprovider类中使用静态变量的问题。 - Atihska
2个回答

14
无论何时我们的应用程序被杀死,AlarmManager并不会被杀死。但您的闹钟会被取消。如果用户强制停止或结束您的任务,您的闹钟将被取消。在Android 3.1+版中,如果用户强制停止了您的应用程序,除非用户手动启动您的一个活动,否则您的代码将不会再次运行。
理想情况下,您的应用程序不应该以任何方式编写,使得Android有任何原因要摆脱您。对于像您描述的这样的问题,您应该使用指向已注册清单BroadcastReceiver的getBroadcast()PendingIntent,或者您应该使用指向IntentService的getService()PendingIntent。在任一情况下,您的代码将运行一小段时间,然后您的进程将有资格被Android回收,如果需要的话不会出现问题。
在我看来,手动或自动的任务结束器似乎是取消闹钟的更可能罪犯。

闹钟已取消:感谢澄清。我在 Android 团队的办公时间 g+ hangout 上提出了这个问题,甚至他们似乎对这种行为感到困惑。这在哪里有记录? - christoff
重新获取广播/服务挂起意图:我正在使用您描述的getBroadcast()。我在上面添加了一些相关代码。 - christoff
关于Android 3.1:服务方面怎么样?我刚试着在我的Galaxy Nexus上结束一个应用程序,但其中一个服务自动重新启动了。 - christoff
2
你对我闹钟被取消该如何处理有什么建议吗?Android团队中的一位成员建议在服务中重新安排闹钟,因为系统会自动重新启动它。 - christoff
这真的很糟糕。Android 应该即使被手动杀死或者某个任务管理器结束,也能重新启动重复闹钟。 - Johann

1
关于文档中的闹钟管理器 - 解释有些混乱,老实说我还没有完全理解。我有一段小部分代码用于小部件部分,在我的情况下解决了这个问题。
package com.test.mytestwidget;

import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;  

public class MyWidgetProvider extends AppWidgetProvider {   

    private PendingIntent service = null;  

    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);                

        final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  

        final Calendar TIME = Calendar.getInstance();  
        TIME.set(Calendar.MINUTE, 0);  
        TIME.set(Calendar.SECOND, 0);  
        TIME.set(Calendar.MILLISECOND, 0);  

        final Intent i = new Intent(context, UpdateWidgetService.class);  

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

        m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 30000, service);  

     }

     @Override  
     public void onDisabled(Context context)  
     {              
         final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  

         m.cancel(service);  
         super.onDisabled(context);
     }      

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接