【问题标题】:Using TimerTask and Timer with Widget AppWidgetProvider将 TimerTask 和 Timer 与 Widget AppWidgetProvider 一起使用
【发布时间】:2015-07-29 02:34:02
【问题描述】:

我正在使用 Android 创建一个时钟小部件。我测试了时钟,逻辑看起来不错,但我需要让它每分钟更新一次。

我在我的 XML 中将 updatePeriodMillis 设置为 60000,但 Android 将其限制为 30 分钟,因此它仅每半小时更新一次。

我做了一些研究,发现 Service 或 AlarmManager 可能有效,但我调用的方法需要通过 onUpdate() 方法传递给它的 AppWidgetManager 和 AppWidgetId。

我尝试了两种(类似的)方法来使分钟更新正常工作:

static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager,
                            final int appWidgetId) {

    final Handler mHandler = new Handler();
    TimerTask minuteTask = new TimerTask() {

        @Override
        public void run() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {

                    //Do Stuff
            });
        }
    };

    timer = new Timer();

    // schedule the task to run starting now and then every minute
    timer.scheduleAtFixedRate(minuteTask, 0l, 1000 * 60);

}

和:

static void updateAppWidget(final Context context, final AppWidgetManager appWidgetManager,
                            final int appWidgetId) {

    TimerTask minuteTask = new TimerTask() {

        @Override
        public void run() {

            //Do stuff
        }
    };

    timer = new Timer();

    // schedule the task to run starting now and then every minute
    timer.scheduleAtFixedRate(minuteTask, 0l, 1000 * 60);

}

非常感谢任何帮助。

谢谢。

编辑:在我调试和发布这篇文章的时间里,我最终将应用程序安装了半个小时。首次调用 onUpdate() 半小时后,计时器似乎已启动,但在最初的 30 分钟内仍无法正常工作。

【问题讨论】:

    标签: android timer widget timertask appwidgetprovider


    【解决方案1】:

    好的,终于搞定了(有考试,因此职位之间的差距很长)。

    我最终使用了一项服务、待定意图和警报管理器来满足我的需求。

    ClockWidget.class:

    private static final String TAG = ClockWidget.class.getSimpleName();
    
    @Override
    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
        super.onReceive(context, intent);
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        ComponentName componentName = new ComponentName(context, ClockWidget.class);
        onUpdate(context, appWidgetManager, appWidgetManager.getAppWidgetIds(componentName));
    }
    
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.d(TAG, "onUpdate");
    
        ComponentName componentName = new ComponentName(context, ClockWidget.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(componentName);
    
        Intent intent = new Intent(context.getApplicationContext(), UpdateService.class);
        intent.setAction(UpdateService.ACTION_UPDATE);
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
        context.startService(intent);
    
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    
        final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    
        m.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60, pendingIntent);
    }
    

    UpdateService.class:

    private static final String TAG = UpdateService.class.getSimpleName();
    
    public static final String ACTION_UPDATE = "uk.co.thebillington.laxe.ACTION_UPDATE";
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent == null) {
            return super.onStartCommand(null, flags, startId);
        }
    
        String action = intent.getAction();
        if (action == null) {
            return super.onStartCommand(intent, flags, startId);
        }
    
        Log.d(TAG, String.format("onStartCommand: %s", action));
    
        if (action.equals(ACTION_UPDATE)) {
            int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
            for (int widgetId : allWidgetIds) {
                updateWidget(widgetId);
            }
        }
    
        return super.onStartCommand(intent, flags, startId);
    }
    
    private void updateWidget(int widgetId) {
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
    
        RemoteViews views = new RemoteViews(this.getPackageName(), R.layout.clock);
    
        //Do stuff
    
        appWidgetManager.updateAppWidget(widgetId, views);
    }
    

    【讨论】:

      【解决方案2】:

      我做了一些研究,发现 Service 或 AlarmManager 可能有效,但我调用的方法需要通过 onUpdate() 方法传递给它的 AppWidgetManager 和 AppWidgetId。

      将应用小部件 ID 保存在文件中。或者,使用updateAppWidget() 的风格,将ComponentName(而不是应用小部件ID)作为第一个参数,将应用小部件的所有实例更新为相同的RemoteViews。

      您可以从您的IntentService using getInstance() 获取您的AppWidgetManager。

      我尝试了两种(类似的)方法来让分钟更新工作

      这是没有意义的,因为它只会在您的进程运行时起作用。

      【讨论】:

      • 感谢您的提示。我现在创建了一个将所有应用程序小部件 ID 添加到共享首选项的方法,并且我在我的 onEnabled 方法中设置了一个重复警报。然后我有一个意图服务,它从共享首选项中获取 ID,然后 AppWidgetManager 使用 getInstance() 调用 updateAppWidget(this, appWidgetManager, id) 但应用程序仍然没有更新。我认为这可能是因为我的服务没有正确启动。有没有办法测试我的服务是否正在运行?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多