如何定期更新小部件,比如每5秒钟更新一次?

15

我有一个小部件,它有一个简单的按钮实现。每当我们点击按钮时,它会翻转到给定的一组图像中。现在,如果我想让它每5秒钟翻转一次而不需要点击按钮,应该怎么做呢?


我需要为此使用服务吗? - Atihska
4个回答

17
首先,我强烈建议您不要每5秒更新一次小部件。这会在短时间内消耗掉您的电池。
您可以在appwidget-provider中使用android:updatePeriodMillis属性。在Android开发者网站上查看添加AppWidgetProviderInfo元数据
问题是,为了节省电池电量,您不能将更新周期设置在30分钟以下(1800000毫秒)。
设置所需的更新周期后,您只需要在AppWidgetProvider的onReceive()方法中定义行为即可。为此,您必须捕获ACTION_APPWIDGET_UPDATE事件。
@Override
public void onReceive(Context context, Intent intent) {

    final String action = intent.getAction();

    if (ACTION_APPWIDGET_UPDATE.equals(action)) {
        // Update your widget here.
    }
}

如果您真的想每5秒执行一次任务,可以使用TimerTimerTask类:
final Handler handler = new Handler();
Timer timer = new Timer();

TimerTask task = new TimerTask() {

    @Override
    public void run() {
        handler.post(new Runnable() {
            public void run() {  
                // send a broadcast to the widget.
            }
        });
    }
};
timer.scheduleAtFixedRate(task, 0, 5000); // Executes the task every 5 seconds.

4
这个放在哪里? - Richard Barraclough

5
使用AlarmManager触发警报,该警报将发送更新意图到您的接收器。以下是一个很好的链接,提供了示例。

http://www.parallelrealities.co.uk/2011/09/using-alarmmanager-for-updating-android.html

  1. 当小部件被激活时,在小部件服务中设置下一个闹钟,间隔为5秒。
  2. 闹钟应该发送一个PendingIntent,在5秒后触发你的服务。
  3. 在你的服务的onStartCommand方法中,触发小部件更新服务。
  4. 然后再次设置下一个闹钟,间隔为5秒。

注意:但是,5秒真的太快了。这会根据你在后台做什么而很快耗尽你的电池。请考虑减少更新频率。


什么小部件服务? 如何发送? 我找不到 onStartCommand 函数。 - Richard Barraclough

3
使用Kotlin中的Handler,您可以像这样做:
在您的活动或片段中:
 //update interval for widget
val UPDATE_INTERVAL = 1000L

//Handler to repeat update
private val updateWidgetHandler = Handler()

//runnable to update widget
private var updateWidgetRunnable: Runnable = Runnable {
    run {

        //Update Widget
        sendUpdateBroadcast()

        // Re-run it after the update interval
        updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
    }
}

private fun sendUpdateBroadcast() {
    val updateWidgetIntent = Intent(this, YourWidget::class.java)
    updateWidgetIntent.action = ACTION_APPWIDGET_UPDATE
    val ids = AppWidgetManager.getInstance(application)
        .getAppWidgetIds(ComponentName(application, YourWidget::class.java))
    updateWidgetIntent.putExtra(EXTRA_APPWIDGET_IDS, ids)
    sendBroadcast(updateWidgetIntent)
}



// START updating in foreground
override fun onResume() {
    super.onResume()
    updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
}


// REMOVE callback if app in background
override fun onPause() {
    super.onPause()
    // uncomment to pause updating widget when app is in Background
    // updateWidgetHandler.removeCallbacks(updateWidgetRunnable);
}

在您的小部件提供程序中,调用override onReceive方法,像这样:最初的回答。
override fun onReceive(context: Context, intent: Intent) {

    if (ACTION_APPWIDGET_UPDATE == intent.action) {

        // Update your widget here.
        val remoteViews =
            RemoteViews(
                context.packageName,
                R.layout.your_widget
            )

        // Update Text and images
       updateViews(remoteViews)

        //Apply Update
        AppWidgetManager.getInstance(context).updateAppWidget(
            ComponentName(context, ComWidget::class.java)
            , remoteViews)

    }
}

重要的一点是,如果您不在上述方法中触发“应用更新”,则您的UI更改将不会反映在小部件上。希望这可以帮助您。最初的回答。

但是因为它是一个小部件,所以没有“Fragment”或“Activity”。 - Richard Barraclough
你不能在 onReceive 中启动计时器,因为这会在操作系统每次发送更新请求到小部件时启动一个新的计时器。 - Richard Barraclough

0
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
    public void run() {
        runOnUiThread(new Runnable() {
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    }
}, 5000, 5000);

第一个变化将在5秒后发生。


3
这段代码应该放在Android小部件(android-widget)的Provider类或Service类中? - Atihska
bitmap 来自哪里? - Richard Barraclough
runOnUiThread 需要活动引用,我应该把所有这些代码放在哪里? - Shubham Gupta

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