在Android中更新App Widget的多个实例

时间:2013-07-20 15:40:47

标签: android user-interface android-widget

尝试创建app小部件的多个实例并分别更新每个实例,但无法找到我们无法正常工作的原因。以下是从here收集并稍加修改的代码:

package com.example.widgetagain;

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

public class MyWidgetProvider extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
            int[] appWidgetIds) {

        for (int appWidSingle = 0; appWidSingle < appWidgetIds.length; appWidSingle++) {
            // initializing widget layout
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                    R.layout.widget_main);

            // register for button event
            remoteViews.setOnClickPendingIntent(R.id.sync_button,
                    buildButtonPendingIntent(context, appWidSingle));

            // updating view with initial data
            remoteViews.setTextViewText(R.id.title, getTitle());
            remoteViews.setTextViewText(R.id.desc, getDesc());

            // request for widget update
            pushWidgetUpdate(context, remoteViews, appWidSingle);
        }

    }

    public static PendingIntent buildButtonPendingIntent(Context context, int appWidgetSingleId) {
        ++MyWidgetIntentReceiver.clickCount;

        Intent clickIntent = new Intent(context, MyWidgetIntentReceiver.class);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetSingleId);
        clickIntent.setAction("WidgetUtils.WIDGET_UPDATE_ACTION");
        return PendingIntent.getBroadcast(context, appWidgetSingleId, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        // initiate widget update request
        /*Intent intent = new Intent();
        intent.setAction("WidgetUtils.WIDGET_UPDATE_ACTION");
        return PendingIntent.getBroadcast(context, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);*/
    }

    private static CharSequence getDesc() {
        return "Sync to see some of our funniest joke collections";
    }

    private static CharSequence getTitle() {
        return "Funny Jokes";
    }

    public static void pushWidgetUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {

        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_main);

        Intent clickIntent = new Intent(context, MyWidgetIntentReceiver.class);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetSingleId);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetSingleId, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        views.setOnClickPendingIntent(R.id.sync_button, pendingIntent);
        manager.updateAppWidget(appWidgetSingleId, views);
    }
}  

package com.example.widgetagain;

import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;

public class MyWidgetIntentReceiver extends BroadcastReceiver {
    public static int clickCount = 0;
    private String msg[] = null;
    int widgetId;

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

    /*  if (intent.getAction()==null) {
            Bundle extras = intent.getExtras();
            if(extras!=null) {
                widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
                // do something for the widget that has appWidgetId = widgetId
            }
        }
        else {
            //super.onReceive(context, intent);
        }*/

        if (intent.getAction().equals("WidgetUtils.WIDGET_UPDATE_ACTION")) {

            Bundle extras = intent.getExtras();
            if(extras!=null) {
                widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
                // do something for the widget that has appWidgetId = widgetId
            }

            updateWidgetPictureAndButtonListener(context, widgetId);
        }
    }

    private void updateWidgetPictureAndButtonListener(Context context, int widgetId) {
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                R.layout.widget_main);

        // updating view
        remoteViews.setTextViewText(R.id.title, getTitle());
        remoteViews.setTextViewText(R.id.desc, getDesc(context));

        // re-registering for click listener
        remoteViews.setOnClickPendingIntent(R.id.sync_button,
                MyWidgetProvider.buildButtonPendingIntent(context, widgetId));

        MyWidgetProvider.pushWidgetUpdate(context.getApplicationContext(),remoteViews, widgetId);
    }

    private String getDesc(Context context) {
        // some static jokes from xml
        msg = context.getResources().getStringArray(R.array.string_array_name);
        if (clickCount >= msg.length) {
            clickCount = 0;
        }
        return msg[clickCount];
    }

    private String getTitle() {
        return "Funny Jokes";
    }
}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.widgetagain"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver android:name=".MyWidgetProvider" >
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>

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

        <receiver
            android:name=".MyWidgetIntentReceiver"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="WidgetUtils.WIDGET_UPDATE_ACTION" />
            </intent-filter>

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

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_main"
    android:minHeight="146dp"
    android:minWidth="292dp"
    android:previewImage="@drawable/ic_launcher"
    android:updatePeriodMillis="1000000" >
</appwidget-provider>

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5sp"
    android:background="@drawable/ic_launcher"
    android:orientation="vertical" >

    <RelativeLayout
        android:id="@+id/buttonContainer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" >

        <Button
            android:id="@+id/sync_button"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:background="@drawable/ic_launcher"
            android:text="" />
    </RelativeLayout>

    <LinearLayout
        android:id="@+id/contentContainer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_above="@id/buttonContainer"
        android:layout_alignParentTop="true"
        android:orientation="vertical"
        android:padding="8dp" >

        <TextView
            android:id="@+id/title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:maxLines="2"
            android:paddingBottom="5dp"
            android:text=""
            android:textColor="#fcfcfc"
            android:textSize="16sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/desc"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:maxLines="5"
            android:text=""
            android:textColor="#fcfcfc"
            android:textSize="13sp"
            android:textStyle="normal" />
    </LinearLayout>

</RelativeLayout>

2 个答案:

答案 0 :(得分:3)

根据您发布的内容,似乎是这样:

// request for widget update
pushWidgetUpdate(context, remoteViews, appWidSingle);

应该看起来像这样:

// request for widget update
pushWidgetUpdate(context, remoteViews, appWidgetIds[appWidSingle]);

同样地:

// register for button event
remoteViews.setOnClickPendingIntent(R.id.sync_button,
    buildButtonPendingIntent(context, appWidSingle));

应该是:

// register for button event
remoteViews.setOnClickPendingIntent(R.id.sync_button,
    buildButtonPendingIntent(context, appWidgetIds[appWidSingle]));

答案 1 :(得分:1)

除了j__m提到的错误之外,这部分代码也不正确:

public static void pushWidgetUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {

        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_main);

        Intent clickIntent = new Intent(context, MyWidgetIntentReceiver.class);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetSingleId);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetSingleId, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        views.setOnClickPendingIntent(R.id.sync_button, pendingIntent);
        manager.updateAppWidget(appWidgetSingleId, views);
    }

即每次创建新的远程视图而不是在pushwidgetupdate方法中使用传递的remoteview。因此上面的代码改为:

public static void pushWidgetUpdate(Context context, RemoteViews remoteViews, int appWidgetSingleId) {

        AppWidgetManager manager = AppWidgetManager.getInstance(context);

        Intent clickIntent = new Intent(context, MyWidgetIntentReceiver.class);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetSingleId);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetSingleId, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        remoteViews.setOnClickPendingIntent(R.id.sync_button, pendingIntent);
        manager.updateAppWidget(appWidgetSingleId, views);
    }