java - 配置更改后小部件不刷新

标签 java android android-widget

我为我的应用编写了一个 AppWidget,你可以选择一个你喜欢的地方的名称,它会向你显示来自那个地方的照片。

它有一个配置 Activity(我使用了与应用程序本身相同的配置 Activity) 首次添加时,小部件及其配置处理工作正常:我选择了一个我喜欢的地方,然后我看到了图片;

问题是每当我重新启动设备(或者它退出 sleep 模式) 然后当我点击它(小部件)时,我进入配置 Activity - 更改为所需的图片但没有任何反应 当我调试时,我可以看到:

appWidgetManager.updateAppWidget(mAppWidgetId, views);
mAppWidgetId = 

有一个 id,并且 views 不是 null。 那么黑客是怎么回事? 我的想法是,在设备重新启动时,widgetId 会发生变化,并且我不会像我应该的那样处理它。 顺便说一句,如果在模拟器上尝试相同的操作,我没有问题,一切正常

这是我的代码:

list .xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.dryrun" android:versionCode="3"
    android:versionName="1.1" android:installLocation="auto">
    <uses-sdk android:minSdkVersion="8" />

    <application android:icon="@drawable/ic_launcher_test"
        android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
        android:debuggable="true"><!-- different< android:theme="@style/Theme.NoBackground" -->

        <!-- Main Activity -->
        <activity android:name=".MyActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <!-- Preferences -->

        <activity android:name=".Preferences.EditPreferences">
             <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
        </activity>

        <!-- Widgets -->

        <!--  Widget-->
        <receiver android:name=".Widget.testWidget" android:label="@string/app_widget_">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                <!--action
                    android:name="com.test.dryrun.Widget.testWidget.PREFENCES_WIDGET_CONFIGURE" /-->
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"
                android:resource="@xml/test_widget__provider" />
        </receiver>
        <service android:name=".Widget.testWidget$WidgetService" />

        <uses-permission android:name="android.permission.BIND_REMOTEVIEWS"></uses-permission>
    </application>
</manifest>

appwidget_provider xml

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
 android:minWidth="146dip"
 android:minHeight="146dip"
 android:updatePeriodMillis="0"
 android:initialLayout="@layout/test_widget"
/>

小部件类

public class testWidget extends AppWidgetProvider {
    public static String PREFENCES_WIDGET_CONFIGURE = "ActionConfigureWidget";

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Intent svcIntent = new Intent(context, WidgetService.class);
        widgets = appWidgetIds;
        context.startService(svcIntent);
    }


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

        // v1.5 fix that doesn't call onDelete Action
        final String action = intent.getAction();
        if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action))
        {
            final int appWidgetId = intent.getExtras().getInt(
                    AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID)
            {
                this.onDeleted(context, new int[] { appWidgetId });
            }
        }
        else
        {
            super.onReceive(context, intent);           
        }
    }

    //public void updateWidget()
    /**
    * @param context
    * @param remoteViews
    */
    public static void updateWidget(Context context, RemoteViews remoteViews)
    {
        String Prefix = context.getString(R.string._prefix);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        String ToShow = prefs.getString(context.getString(
                     R.string.Widget_string),
                     context.getString(R.string.default_string));

        String pkgName = context.getPackageName();
        int resID = context.getResources().getIdentifier(Prefix + ToShow, "drawable", pkgName);

        WidgetController widgetController = WidgetController.getInstance();
        widgetController.setRemoteViewImageViewSource(remoteViews, R.id.WidgetImage, resID);
    }

    public static class WidgetService extends Service
    {
        @Override
        public void onStart(Intent intent, int startId)
        {
            super.onStart(intent, startId);
            // Update the widget
            RemoteViews remoteView = buildRemoteView(this);

            // Push update to homescreen
            WidgetController.getInstance().pushUpdate(
                    remoteView, 
                    getApplicationContext(),
                    testWidget.class);

            // No more updates so stop the service and free resources
            stopSelf();
        }

        public RemoteViews buildRemoteView(Context context)
        {
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_widget);

            Intent configIntent = new Intent(context, EditPreferences.class);
            configIntent.setAction(testWidget.PREFENCES_WIDGET_CONFIGURE);


            configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgets[0]);

            //configIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            PendingIntent runtestPendingIntent = PendingIntent.getActivity(context, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.WidgetImage, runtestPendingIntent);

            WidgetController controller =  WidgetController.getInstance();

            controller.updateWidget(context, remoteViews);

            return remoteViews;
        }

        @Override
        public void onConfigurationChanged(Configuration newConfig)
        {
            int oldOrientation = this.getResources().getConfiguration().orientation;

            if(newConfig.orientation != oldOrientation)
            {
                // Update the widget
                RemoteViews remoteView = buildRemoteView(this);

                // Push update to homescreen
                WidgetController.getInstance().pushUpdate(
                        remoteView, 
                        getApplicationContext(),
                        testWidget.class);
            }
        }

        @Override
        public IBinder onBind(Intent arg0)
        {
            // TODO Auto-generated method stub
            return null;
        }
    }
}

偏好类

public class EditPreferences extends PreferenceActivity implements OnSharedPreferenceChangeListener
{
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
        Intent intent = getIntent();
        m_extras = intent.getExtras();
    }
    private Bundle m_extras;

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) 
    {
        if(key.equals(getString(R.string.rlvntString)))
        {
            Context ctx = getApplicationContext();
            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(ctx);
            setResult(RESULT_CANCELED);
            if (m_extras != null) 
            {
                Intent resultValue = new Intent();

                String stringID = AppWidgetManager.EXTRA_APPWIDGET_ID;
                mAppWidgetId = m_extras.getInt(
                            stringID, 
                            AppWidgetManager.INVALID_APPWIDGET_ID);
                RemoteViews views = new RemoteViews(ctx.getPackageName(),R.layout.test_widget);

                WidgetController.getInstance().updateWidget(ctx, views);

                appWidgetManager.updateAppWidget(mAppWidgetId, views);
                resultValue.putExtra(stringID, mAppWidgetId);
                setResult(RESULT_OK, resultValue);
                finish();
            }
        }
    }
}

最佳答案

为了将来的需要。我在我的小部件的布局 xml 中添加了一个按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"

    android:orientation="vertical" >
    <TextView
        android:id="@+id/timeout_title"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:textStyle="bold"
        android:gravity="center"/>

    <!-- ListView to be shown on widget -->
    <ListView
        android:id="@+id/timeoutListViewWidget"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_marginEnd="45dp"
        android:divider="@null"
        />

    <ImageButton
        android:id="@+id/timeout_edit"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        android:src="@drawable/pen"
        />

    <!-- Empty view is show if list items are empty -->
    <TextView
        android:id="@+id/timeOutEmpty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Veri Listesi boş"
        android:textColor="#ffffff"
        android:textSize="20sp"
        android:visibility="gone" />

</LinearLayout>

然后我在我的 widgetproviders 类中定义了 remoteviews 的地方定义了 onClick 监听器;

private RemoteViews updateWidgetListView(Context context,
                                             int appWidgetId) {

        //which layout to show on widget
        RemoteViews remoteViews = new RemoteViews(
                context.getPackageName(), R.layout.timeout_widget);

        Intent svcIntent = new Intent(context, TimeoutWidgetService.class);

        svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

        svcIntent.setData(Uri.parse(
                svcIntent.toUri(Intent.URI_INTENT_SCHEME)));

        remoteViews.setRemoteAdapter( R.id.timeoutListViewWidget, svcIntent);

        remoteViews.setEmptyView(R.id.timeOutEmpty_view, R.id.timeOutEmpty_view);

        Intent configIntent = new Intent(context, AppWidgetDepLevelActivity.class);
        configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        // Make this unique for this appWidgetId
        configIntent.setData(Uri.withAppendedPath(Uri.parse("customuri://widget/id/"), String.valueOf(appWidgetId)));
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT);

       remoteViews.setOnClickPendingIntent(R.id.timeout_edit, pendingIntent);
        return remoteViews;
    }

然后在我的 ConfigurationActivity 中我创建了包含我的配置更改的新包;

Bundle newOps = new Bundle();
newOps.putInt("level",0);

并调用了;

appWidgetManager.updateAppWidgetOptions(appWidgetId,newOps);

整个函数;

private void updateAppWidgetOptions() {
        appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
        Intent intent = getIntent();
        Bundle extras = intent.getExtras();
        if (extras != null) {
            appWidgetId = extras.getInt(
                    AppWidgetManager.EXTRA_APPWIDGET_ID,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
                finish();
            }

            AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getApplicationContext());
            RemoteViews views = new RemoteViews(getApplicationContext().getPackageName(),
                    R.layout.timeout_widget);
            Bundle newOps = new Bundle();
            newOps.putInt("level",0);
            appWidgetManager.updateAppWidgetOptions(appWidgetId,newOps);

            Intent resultValue = new Intent();

            resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

            setResult(RESULT_OK, resultValue);

            finish();
        }
    }

            

并且此函数触发了我的 appwidget 提供程序类中覆盖的 onAppWidgetOptionsChanged 函数,我在那里运行我的逻辑。

这是函数;

 @Override
    public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
        super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
        Log.d("APPWIGET","onAppWidgetOptionsChanged");
        Object level = newOptions.get("level");
        if(level!= null){
            Log.d("APPWIGET",level.toString());
        }
        Date date = new Date();
        now = date.getTime();

        this.appWidgetId = appWidgetId;
        this.appWidgetManager = appWidgetManager;
        getTimeOutReportData(context);

    }

关于java - 配置更改后小部件不刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7766779/

相关文章:

java - 在 Android 中使用反射实现向后兼容

java - 如何获取十六进制调色板

java - 在 Android 中设置委托(delegate)

android - RemoteViewService Intent 上的 setData

java - 将数据库拆分为较小的数据库。单次提交数据过多

java - MenuInflater 究竟是如何工作的?

java - 解析json列表

android - 是否可以向抽屉导航按钮添加声音?

Android 可扩展 ListView

java - 在java中的线程和标志之间交换多个对象