简体   繁体   中英

How to update a widget periodically, say after every 5 seconds

I have a widget with simple button implementation, that whenever we click on a button it flips through a given set of images. Now if I want to flip it every 5 seconds without the button being clicked, how may I proceed?

First, I would strongly recommend you not to update a widget every 5 seconds. It would kill your battery in no time.

You can use android:updatePeriodMillis attribute in the appwidget-provider.
Take a look at Adding the AppWidgetProviderInfo Metadata on Android developer website.
The thing is, to preserve battery, you can not set a period under 30 min (1800000ms).

After setting up the update period you want, you just have to define the behavior in the onReceive() method of your AppWidgetProvider. To do this, you have to catch ACTION_APPWIDGET_UPDATE event.

@Override
public void onReceive(Context context, Intent intent) {

    final String action = intent.getAction();

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

If you really want to perform a task every 5 seconds, you can use Timer and TimerTask class :

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.

Use AlarmManager to tirgger off alarms that would send out an Update intent to your receiver.

Here's a good link which gives an example.

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

  1. When the widget is activated, in the widget service, setup the next alarm after 5 seconds.
  2. The alarm should send out a PendingIntent, that would trigger your service after 5 seconds.
  3. In your service's onStartCommand, trigger the widget update service.
  4. And setup the next alarm after 5 seconds again.

Note: But, 5 seconds, is really too fast. It would drain off your battery soon enough, depending on what else you might be doing in the background. Do think about making the updates less frequently.

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

The first change will happen after 5 seconds.

Using Handler in Kotlin you can do something like this:

In your activity or fragment

 //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);
}

Than in your Widget Provider call override onReceive method like this:

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)

    }
}

Important thing to note here is if you dont trigger //Apply Update in above method your UI changes will not reflected on widget. Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM