Reputation: 820
In my application I have registered a broadcast receiver for an implicit broadcast by another application protected with permission :
<receiver
android:name=".receiver.MyReceiver"
android:exported="true"
android:permission="owner.custom.permission">
<intent-filter>
<action android:name="owner.custom.broadcast"/>
</intent-filter>
</receiver>
In MyReceiver#onReceive()
I am invoking a JobIntentService MyService
using enqueueWork()
:
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
Log.i(TAG, "Received the broadcast");
MyService.enqueueWork(context, getServiceIntent(context));
}
private Intent getServiceIntent(final Context context) {
final Intent intent = new Intent(context, MyService.class);
intent.putExtra("someKey", true);
return intent;
}
}
I have the following method in MyService
:
public static void enqueueWork(final Context context, final Intent work) {
enqueueWork(context, MyService.class, 111, work);
}
Now whenever owner.custom.broadcast
is broadcast, MyReceiver
is not triggered and I can see the following logs :
07-23 03:56:29.755 3335 3361 W BroadcastQueue: Background execution not allowed: receiving Intent { act=owner.custom.broadcast flg=0x10 } to com.amazon.myApp/.receiver.MyReceiver
Now the thing is I am listening to another such 3rd party implicit broadcast with a different broadcast receiver and invoking MyService
over there and it works fine. I am also listening for BOOT_COMPLETED
broadcast in a yet another broadcast receiver and invoking MyService
over there and it works fine there too.
What are the possible causes for this error which would help me identify if I'm missing something.
UPDATE :
I am now just trying to get the broadcast receiver to trigger but I am still getting the same error. I am trying with nothing but a log line in the receiver :
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
Log.i(TAG, "Received the broadcast");
}
}
Upvotes: 3
Views: 11060
Reputation: 313
This is an old question, but I found a solution which worked for me.
As mentioned here
Context-registered receivers receive broadcasts as long as their registering context is valid. For an example, if you register within an Activity context, you receive broadcasts as long as the activity is not destroyed. If you register with the Application context, you receive broadcasts as long as the app is running.
I had to remove the receiver declaration in the Manifest completely and register my receiver during runtime, using the Application context!
IntentFilter filter = new IntentFilter("owner.custom.broadcast");
getContext().getApplicationContext().registerReceiver(new MyReceiver(), filter);
and then
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
context.unregisterReceiver(this);
// ....
}
}
Upvotes: 1
Reputation: 396
Android O limits the implicit broadcast, you can't execute a background service in the receiver.
However, it only limits the static receivers, you can register your receiver in the code to trigger your service.
Of course, in some case, you don't want to do it "programmatically", then you should check the error case, from this link http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java#1275 (Line:1275), I find the error (not sure if this is the same as your system version).
We can see there are few conditions to access to this code block, we analyze them one by one, all we want to do is make the condition equals false
:
(r.intent.getFlags()&Intent.FLAG_RECEIVER_EXCLUDE_BACKGROUND) != 0
It means if we don't want the background to receive the intent the condition will be true, and usually, we don't add this flag because we want the background to receive the broadcast, go ahead.
r.intent.getComponent() == null
It should not be null in any of our case, go ahead.
r.intent.getPackage() == null
Same above, go ahead.
r.intent.getFlags()&Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND) == 0
It means we cannot have a flag called Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
, I think we can try this, but you will see this in the Intent class:
/**
* If set, the broadcast will always go to manifest receivers in background (cached
* or not running) apps, regardless of whether that would be done by default. By
* default they will only receive broadcasts if the broadcast has specified an
* explicit component or package name.
*
* NOTE: dumpstate uses this flag numerically, so when its value is changed
* the broadcast code there must also be changed to match.
*
* @hide
*/
public static final int FLAG_RECEIVER_INCLUDE_BACKGROUND = 0x01000000;
It's hidden, but you can just hardcode the integer in your project, now add this flag to your intent to try if your code is work.
intent.addFlags(0x01000000)
Good luck :)
Note: this solution will NOT resolve to receive the system implicit broadcast to run background tasks.
Upvotes: 4
Reputation: 820
I'm not sure why this solution worked (maybe someone else can elaborate on why) but I was able to get my broadcast receiver to trigger by declaring the permission in my Manifest itself and and also using the same. Find the code changes below :
<permission
android:name="owner.custom.permission"
android:protectionLevel="signatureOrSystem">
</permission>
.
.
.
<uses-permission android:name="owner.custom.permission" />
Upvotes: 0
Reputation: 296
I faced a similar problem year ago, I'm not pretty sure of this, but since its not allowed for background execution then execute it in foreground using Foreground Service, you can achieve that by starting a service that is connected to a notification, then in your service you can trigger your broadcast and that should work.
I hope my answer helps you.
Upvotes: 0