2

Trying to create multiple instances of app widget and update each of them separately, but can't find our why it's not working properly. Here is the code, collected from here and modified somewhat:

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>
4

2 回答 2

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]));
于 2013-07-20T16:11:06.257 回答
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 方法中使用传递的远程视图。因此上面的代码改为:

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);
    }
于 2013-07-20T17:41:34.637 回答