如何真正每分钟更新一个小部件

ten*_*ays 7 android scheduled-tasks android-widget

我很难过.我知道这个问题已经被回答了一百次,但我没有尝试过.

我的问题:我制作了一个需要在每分钟精确刷新的Android小部件,就像所有时钟小部件一样.(这个小部件告诉我在我的火车离开前剩下多少分钟,一分钟的错误使它无用).

以下是我的尝试以及各自的结果:

  • 我把android:updatePeriodMillis="60000"我的appwidget_info.xml.但是,正如API Docs中所述,"请求的更新updatePeriodMillis不会每30分钟发送一次以上",实际上这就是我的小部件更新的频率.
  • 我试过用了AlarmManager.在我的WidgetProvider.onEnabled:

    AlarmManager am = (AlarmManager)context.getSystemService
            (Context.ALARM_SERVICE);
    Calendar calendar = Calendar.getInstance();
    long now = System.currentTimeMillis();
    // start at the next minute
    calendar.setTimeInMillis(now + 60000 - (now % 60000));
    am.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 60000,
            createUpdateIntent(context));
    
    Run Code Online (Sandbox Code Playgroud)

    然而,正如API文档中所述,"从API 19开始,所有重复警报都是不精确的",实际上我的小部件实际上每五分钟左右更新一次.

  • 基于前一点,我尝试设置targetSdkVersion为18并且没有看到任何差异(每五分钟更新一次).
  • setRepeating文件似乎使用建议setExact.我尝试了以下内容.在我的更新逻辑结束时:

    Calendar calendar = Calendar.getInstance();
    long now = System.currentTimeMillis();
    long delta = 60000 - (now % 60000);
    
    Log.d(LOG_TAG, "Scheduling another update in "+ (delta/1000) +" seconds");
    calendar.setTimeInMillis(now + delta);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), //UPDATE_PERIOD_SECONDS * 1000,
            createUpdateIntent(context));
    
    Run Code Online (Sandbox Code Playgroud)

    它可以完美地工作几分钟,然后每五分钟左右恢复更新一次(甚至不会接近微小的变化).以下是收到更新意图时的一些时间戳:

    • 21:44:17.962
    • 21:52:37.232
    • 21:59:13.872
    • 22:00:00.012←嘿突然它再次变得准确?
    • 22:01:47.352
    • 22:02:25.132
    • 22:06:56.202
  • 有人建议使用Handler.我定义了Service在启用窗口小部件提供程序时启动的内容,并在更新代码后执行此操作:

    int delay = (int)(60000 - (System.currentTimeMillis() % 60000));
    Log.d(LOG_TAG, "Scheduling another update in " + delay/1000 + " seconds");
    new Handler().postDelayed(new Runnable() {
        public void run() {
            Log.d(LOG_TAG, "Scheduled update running");
            updateAppWidget();
        }
    }, delay);
    
    Run Code Online (Sandbox Code Playgroud)

    并且这个工作完美地工作了几个小时,但随后服务突然被杀死并且" 计划在巨大延迟后重新启动 ".具体而言,小部件只是在某个时刻陷入困境而根本没有得到更新.

我在网上看到的其他一些选项:上面的链接帖子建议创建一个前台服务(如果我理解正确的话,意味着在我已经拥挤的状态栏中有一个永久可见的图标.我没有每个时钟的一个永久图标我使用的小部件,这是不必要的).另一个建议是从服务中运行一个高优先级的线程,这感觉非常过分.

我也看到了使用Timers和推荐的建议,BroadcastReceiver但前者据说"不适合任务",我记得在做后者时遇到了麻烦.我想我必须在服务中执行它,然后服务就像我使用Handlers 时一样被杀死.

应该注意的AlarmManager是,当手机连接到电脑时似乎运行良好(大概是因为这意味着电池正在充电),这无济于事,因为大多数时候我想知道我的火车什么时候会离开的时候是我已经在途中......

由于它Handler是完全准确的,但只是一段时间后停止工作,并且AlarmManager选项太不准确但不会停止工作,我想通过AlarmManager每十分钟左右启动一次服务来组合它们,并让该服务使用一个Handler来每分钟更新一次显示.不知怎的,我觉得这会被Android检测为一个强大的生猪并被杀死,无论如何我肯定我必须遗漏一些明显的东西.它不应该很难做到什么本质上是一个纯文本的时钟部件.

编辑:如果重要的话,我在三星Galaxy Note 4(2016-06-01)和Android 6.0.1上使用我的小部件.

Rab*_*ant 0

使用小部件本身作为延迟可运行的主机。小部件有一个 postDelayed 方法。

如果小部件被杀死并重新创建,那么还重新创建可运行对象作为基本初始化的一部分。

编辑:

上述建议基于不准确的假设,即 OP 正在编写自定义视图,而不是应用程序小部件。对于应用程序小部件,我最好的建议是:

  • 使用 ONE 图标创建前台服务。
  • 该服务管理所有小部件,单击通知图标将显示各种处于活动状态的提醒和/允许管理它们