widget case that doesn't work with Oreo 8.1 - message received: W/BroadcastQueue: Background execution not allowed: receiving Intent

匿名 (未验证) 提交于 2019-12-03 00:52:01

问题:

My widget app is running fine on all android version except 8 Oreo. I get a W/BroadcastQueue: Background execution not allowed: receiving Intent message.

There is an interesting blog from CommonsWare but I don't fully understand why it applies to my case. https://commonsware.com/blog/2017/04/11/android-o-implicit-broadcast-ban.html

My case looks pretty simple: I have a widget with a button and I want to change the text's button when it is clicked.

What is the right way to fix this issue?

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> 

回答1:

It's subtle, but it is because of the implicit broadcast being used to trigger your TestWidgetReceiver. It is implicit because it is only specifying the action portion of the Intent. Make the broadcast Intent explicit by specifying the receiver class in the constructor:

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); } 


回答2:

Things are changed now a days in Android. For the security & battery consumption google introduced so many ways & increased some problem for developers. You haven't passed the Context of the TestWidgetReceiver.class to you intent.

You can do it like that in java

Intent intent = new Intent(context, TestWidgetReceiver.class);

or in kotlin

val intent = Intent(context, TestWidgetReceiver.class);

You can read more changes here

https://developer.android.com/about/versions/oreo/android-8.0-changes

Regards



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!