gpt4 book ai didi

android - 重新启动后,小部件 onUpdate 未在单击按钮时设置 pendingIntent

转载 作者:太空宇宙 更新时间:2023-11-03 10:34:40 24 4
gpt4 key购买 nike

我正在创建一个测试小部件,通过单击它的按钮来显示随机数。一切都独立地在我的 ProvideronUpdate 中,包括 pendingIntent。它工作正常,但在重新启动手机后 views.setOnClickPendingIntent 无法正常工作,尽管 RemoteViews 重新创建没有问题,但按钮变得无响应。

public class TestWidget extends AppWidgetProvider {
static HashMap<Integer, BroadcastReceiver> br = new HashMap<>();

static void updateAppWidget(Context context, final AppWidgetManager appWidgetManager,
final int appWidgetId) {
context = context.getApplicationContext();
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_widget);

BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
views.setTextViewText(R.id.appwidget_text, Math.random() + "");
appWidgetManager.updateAppWidget(appWidgetId, views);
}
};
br.put(appWidgetId, broadcastReceiver);//to unregister later

Intent intent = new Intent("action");
IntentFilter intentFilter = new IntentFilter("action");

context.registerReceiver(broadcastReceiver, intentFilter);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.appwidget_button, pendingIntent);

appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}

@Override
public void onDeleted(Context context, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
context.unregisterReceiver(br.get(appWidgetId));
}
}
}

list :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aeza.sta">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">

<receiver android:name=".TestWidget" android:enabled="true" android:exported="false" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>

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

<activity android:name=".TestWidgetConfigureActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
</application>

</manifest>

最佳答案

AppWidgetProvider 中动态注册 BroadcastReceiver 充其量是一个不稳定的解决方案。 AppWidgetProvider 本身是一个 BroadcastReceiver,那些静态注册在应用程序 list 中的实例应该是相当短暂的。

但是,由于 AppWidgetProvider 是一个 BroadcastReceiver,我们可以利用它,并在点击 时简单地定位您的 TestWidget PendingIntent。我们还可以将 Widget ID 作为附加项附加到此处的 Intent,以便在点击触发时更新正确的 ID。例如:

Intent intent = new Intent(context, TestWidget.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
appWidgetId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.appwidget_button, pendingIntent);

请注意,我们还为 PendingIntentrequestCode 使用了 appWidgetId。为每个 Widget 实例使用不同的 PendingIntent 很重要,以免错误的 Widget 实例被更新为错误的额外内容。使用已经唯一的 Widget ID 可以让我们轻松做到这一点。

然后我们覆盖TestWidgetonReceive()方法,并检查Intent的 Action 来判断这是否是我们的点击广播, 或从系统广播的普通 Widget 事件。在上面的例子中,我们没有设置 Action ,所以我们在这里简单地检查是否为 null。但是,您当然可以指定一个操作 String,在某些情况下这样做可能更可取;例如,如果您的 Widget 中有多个 Button,并且需要区分它们的点击广播。

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
updateWidgetText(context, appWidgetId, Math.random() + "");
}
}
else {
super.onReceive(context, intent);
}
}

在上面,您可以看到,如果我们发现它不是我们的,我们会将广播传递给 super 方法。 AppWidgetProvideronReceive() 将检查 Intent,并按照惯例委托(delegate)给适当的事件方法。

除了是一个稳定的解决方案之外,这种方法还有另一个好处,即不需要为每个 Widget 实例创建、注册然后取消注册一个单独的 BroadcastReceiver 实例。虽然我们添加了 onReceive() 方法,但我们可以删除所有动态 BroadcastReceiver 代码,因此我们的 TestWidget 类仍然很短简单。

public class TestWidget extends AppWidgetProvider {

@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
if (appWidgetId != -1) {
updateWidgetText(context, appWidgetId, Math.random() + "");
}
}
else {
super.onReceive(context, intent);
}
}

static void updateWidgetText(Context context, int appWidgetId, String newText) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_widget);
views.setTextViewText(R.id.appwidget_text, newText);
AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, views);
}

static void updateAppWidget(Context context, final AppWidgetManager appWidgetManager,
final int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.test_widget);

Intent intent = new Intent(context, TestWidget.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
appWidgetId,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.appwidget_button, pendingIntent);

appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
}

关于android - 重新启动后,小部件 onUpdate 未在单击按钮时设置 pendingIntent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49018694/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com