user1759708
user1759708

Reputation: 157

TextView in android widget doesn't update

The TextView in my widgetis set correctly with the correct info when it's getting placed at the home screen. But when I update the info in the main app, the widget still shows the old info.

Manifest:

<receiver android:name=".WidgetProvider" android:label="@string/app_name" android:exported="false">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" />
</receiver>

WidgetProvider.java:

package com.example.huskeliste;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;

public class WidgetProvider extends AppWidgetProvider {

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int N = appWidgetIds.length;

        for (int i = 0; i < N; i++) {
            int widgetId = appWidgetIds[i];

            DBAdapter info = new DBAdapter(context);

            info.open();
            String data = info.getTextViewData();
            info.close();

            Intent intent = new Intent(context, Main.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
            views.setOnClickPendingIntent(R.id.loWidget, pendingIntent);
            views.setTextViewText(R.id.txtView, data);
            appWidgetManager.updateAppWidget(widgetId, views);
        }
    }
}

res - widget.xml:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="1800000">
</appwidget-provider>

layout - widget.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/loWidget"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:gravity="center"
    android:layout_margin="1dp"
    android:background="@drawable/background">

    <TextView
        android:id="@+id/txtView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="22dp"
        android:textColor="#ffffff"
        android:text="" />
</LinearLayout>

background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient android:startColor="#CC111111" android:endColor="#CC111111" android:angle="0" />
    <padding android:left="4dp" android:top="1dp" android:right="4dp" android:bottom="1dp" />
    <corners android:radius="3dp" />
</shape>

getTextViewData() from DBAdapter.java:

public String getTextViewData() {
    String[] columns = new String[] { KEY_NAME };
    Cursor c = ourDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);

    String result = "";

    for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) {           
        if (result.length() > 0) {
            result += ", ";
        }

        result += c.getString(0);
    }

    return result;
}

Anyone have a clue what's missing in my code?

Upvotes: 6

Views: 5707

Answers (2)

Bilal Şimşek
Bilal Şimşek

Reputation: 5953

For future reference;

if you want to update data on the widget, call

appWidgetManager.updateAppWidgetOptions(appWidgetId,newOps);

where you call AppWidgetManager in your configuration activity. and override onAppWidgetOptionsChanged method in your AppWidgetProvider class to get newOptions and run your logic

whole answer is on the link

Upvotes: 0

Dzhuneyt
Dzhuneyt

Reputation: 8711

You need to set an update interval in milliseconds inside your Widget provider XML. Example code:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="86400000"
    android:previewImage="@drawable/preview"
    android:initialLayout="@layout/example_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigure" 
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen|keyguard"
    android:initialKeyguardLayout="@layout/example_keyguard">
</appwidget-provider>

However, you should know that the system does not guarantee the widget to be updated as often. Also, if you want the widget to update more often (e.g. after a configuration change, as it is with your question), you need to do it manually. Here's how I proceed:

In this example my Widget class is simply called Widget.class:

public class Widget extends AppWidgetProvider {

    // TODO: Don't forget to override the onUpdate method also

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("update_widget")) {
            // Manual or automatic widget update started

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.widget);

            // Update text, images, whatever - here
            remoteViews.setTextViewText(R.id.yourTextID, "My updated text");

            // Trigger widget layout update
            AppWidgetManager.getInstance(context).updateAppWidget(
                    new ComponentName(context, Widget.class), remoteViews);
        }
    }

}

Make sure to replace the layout and the TextView with references to your widget layout.

Then whenever you want to update your widget (e.g. in the onPause method of your main activity or whenever a Save button is clicked), you call a PendingIntent:

Intent updateWidget = new Intent(context, Widget.class); // Widget.class is your widget class
updateWidget.setAction("update_widget");
PendingIntent pending = PendingIntent.getBroadcast(context, 0, updateWidget, PendingIntent.FLAG_CANCEL_CURRENT);
pending.send();

Upvotes: 5

Related Questions