Mon application de widget fonctionne correctement sur toutes les versions d'Android, à l'exception de 8 Oreo . Je reçois un message W/BroadcastQueue: Background execution not allowed: receiving Intent
.
CommonsWare propose un blog intéressant mais je ne comprends pas très bien pourquoi cela s'applique à mon cas. https://commonsware.com/blog/2017/04/11/Android-o-implicit-broadcast-ban.html
Mon cas a l'air assez simple: j'ai un widget avec un bouton et je veux changer le bouton du texte quand on clique dessus.
Quelle est la bonne façon de résoudre ce problème?
TestWidget.Java
public class TestWidget extends AppWidgetProvider {
private static RemoteViews views;
private static boolean buttonClicked = false;
public static final String ACTION_AUTO_UPDATE = "AUTO_UPDATE";
@Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
if(intent.getAction().equals(ACTION_AUTO_UPDATE))
{
Log.i("TESTWID", "get onReceive");
}
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
views = new RemoteViews(context.getPackageName(), R.layout.test_widget);
views.setOnClickPendingIntent(R.id.wid_btn_tst, setButton(context));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.i("TESTWID", "onupdate ");
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
public static PendingIntent setButton(Context context) {
Intent intent = new Intent();
intent.setAction("TEST");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static void pushWidgetUpdate(Context context, RemoteViews remoteViews) {
ComponentName myWidget = new ComponentName(context, TestWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(myWidget, remoteViews);
}
}
TestWidgetReceiver.Java
public class TestWidgetReceiver extends BroadcastReceiver{
private static boolean isButtonON = false;
@Override
public void onReceive(Context context, Intent intent) {
Log.i("TESTWID", "onReceive "+intent.getAction());
if(intent.getAction().equals("TEST")){
updateWidgetButton(context, 2);
}
}
private void updateWidgetButton(Context context, int index) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_widget);
if(index == 2) {
if(isButtonON) {
remoteViews.setTextViewText(R.id.wid_btn_tst, "Test Off");
isButtonON = false;
}
else{
remoteViews.setTextViewText(R.id.wid_btn_tst, "Test On");
isButtonON = true;
}
}
TestWidget.pushWidgetUpdate(context.getApplicationContext(), remoteViews);
}
}
Manifest.xml:
<application
Android:allowBackup="true"
Android:icon="@mipmap/ic_launcher"
Android:label="Test"
Android:roundIcon="@mipmap/ic_launcher_round"
Android:supportsRtl="true"
Android:theme="@style/AppTheme">
<activity Android:name=".MainActivity">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver Android:name=".TestWidget">
<intent-filter>
<action Android:name="Android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action Android:name="AUTO_UPDATE" />
</intent-filter>
<meta-data
Android:name="Android.appwidget.provider"
Android:resource="@xml/test_widget_info" />
</receiver>
<receiver
Android:name=".TestWidgetReceiver"
Android:label="widgetBroadcastReceiver" >
<intent-filter>
<action Android:name="TEST" />
</intent-filter>
<meta-data
Android:name="Android.appwidget.provider"
Android:resource="@xml/test_widget_info" />
</receiver>
</application>
C’est subtil, mais c’est parce que implicit broadcast est utilisé pour déclencher votre TestWidgetReceiver
. C'est implicite, car il ne s'agit que de spécifier la partie action de la variable Intent
. Rendre la diffusion Intent
explicit en spécifiant la classe du récepteur dans le constructeur:
public static PendingIntent setButton(Context context) {
Intent intent = new Intent(context, TestWidgetReceiver.class);
intent.setAction("TEST");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}