How to update a Widget dynamically (Not waiting 30 min for onUpdate to be called)?

34,633

Solution 1

You can use the following code to update the data of widget :

ComponentName thisWidget = new ComponentName( getContext(), <ProviderClass> );
AppWidgetManager.getInstance( getContext() ).updateAppWidget( thisWidget, rempoteViews );

Solution 2

If you look at the documentation about widgets, you are supposed to be able to set a time between 2 updates :

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:updatePeriodMillis="86400000"
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure" >

With this, you should be able to put any period you want ? (It mentions that the update might not occur directly after your call for it, and henceforce to do it as often as possible but you have to take care of the battery)

Share:
34,633
Donal Rafferty
Author by

Donal Rafferty

Software Engineer

Updated on August 01, 2022

Comments

  • Donal Rafferty
    Donal Rafferty almost 2 years

    I am currently learning about widgets in Android.

    I want to create a WIFI widget that will display the SSID, the RSSI (Signal) level.

    But I also want to be able to send it data from a service I am running that calculates the Quality of Sound over wifi.

    Here is what I have after some reading and a quick tutorial:


    public class WlanWidget extends AppWidgetProvider{
    
    RemoteViews remoteViews;
    AppWidgetManager appWidgetManager;
    ComponentName thisWidget;
    WifiManager wifiManager;
    
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new WlanTimer(context, appWidgetManager), 1, 10000);
    
    }
    
    
    private class WlanTimer extends TimerTask{
    
            RemoteViews remoteViews;
            AppWidgetManager appWidgetManager;
            ComponentName thisWidget;
    
    
    public WlanTimer(Context context, AppWidgetManager appWidgetManager) {
    
            this.appWidgetManager = appWidgetManager;
            remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
            thisWidget = new ComponentName(context, WlanWidget.class);
            wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
    
    
    }
    
    @Override
    public void run() {
    
            remoteViews.setTextViewText(R.id.widget_textview,
            wifiManager.getConnectionInfo().getSSID());
            appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }
    
    }
    

    The above seems to work ok, it updates the SSID on the widget every 10 seconds.

    However what is the most efficent way to get the information from my service that will be already running to update periodically on my widget?

    Also is there a better approach to updating the the widget rather than using a timer and timertask? (Avoid polling)

    UPDATE

    As per Karan's suggestion I have added the following code in my Service:


    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
    ComponentName thisWidget = new ComponentName( context, WlanWidget.class );
    remoteViews.setTextViewText(R.id.widget_QCLevel, " " + qcPercentage);
    AppWidgetManager.getInstance( context ).updateAppWidget( thisWidget, remoteViews );
    

    This gets run everytime the RSSI level changes but it still never updates the TextView on my widget, any ideas why?

    EDIT

    Got it working, thanks Karan

  • Donal Rafferty
    Donal Rafferty about 14 years
    From 1.6 the minimum update the OS will allow and perform is 30 minutes appart to save battery life. I need to be able to update the Widget every time the RSSI level changes significantly, the Wifi access point changes and when the calculated QoS from my service falls below or climbs above a certain level. All of which need dynamic updating on the Widget.
  • Donal Rafferty
    Donal Rafferty about 14 years
    I can put that in my service and it will update the Widget dynamically?
  • RealCasually
    RealCasually almost 12 years
    No, this is the code you use to trigger the update (I used the 4 lines above at the end of the question). I did this by adding a pending intent to a refresh button on my widget. When pressed, that intent fired a broadcast for a custom action. I caught this action in the onReceive method in my WidgetProvider and then executed this code. Works great! Thanks!