Android O:不允许后台执行:具有权限的自定义广播

Android O:不允许后台执行:具有权限的自定义广播,android,android-intent,broadcastreceiver,android-8.0-oreo,Android,Android Intent,Broadcastreceiver,Android 8.0 Oreo,在我的应用程序中,我已为另一个受许可保护的应用程序的隐式广播注册了广播接收器: <receiver android:name=".receiver.MyReceiver" android:exported="true" android:permission="owner.custom.permission"> <intent-filter> <action android:name="owner.custom.broa

在我的应用程序中,我已为另一个受许可保护的应用程序的隐式广播注册了广播接收器:

<receiver
    android:name=".receiver.MyReceiver"
    android:exported="true"
    android:permission="owner.custom.permission">
    <intent-filter>
        <action android:name="owner.custom.broadcast"/>
    </intent-filter>
</receiver>
我在
MyService
中有以下方法:

public static void enqueueWork(final Context context, final Intent work) {
        enqueueWork(context, MyService.class, 111, work);
    }
现在,每当广播
owner.custom.broadcast
时,
MyReceiver
不会被触发,我可以看到以下日志:

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

现在的问题是,我正在用另一个广播接收器收听另一个这样的第三方隐式广播,并调用那边的
MyService
,效果很好。我还在另一个广播接收器中收听
BOOT\u COMPLETED
广播,并调用那边的
MyService
,它在那里也可以正常工作。
这个错误的可能原因是什么,这有助于我确定我是否遗漏了什么

更新:
我现在只是试图让广播接收器触发,但我仍然得到相同的错误。我正在尝试在接收器中插入一条记录线:

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.i(TAG, "Received the broadcast");
    }
}
试试这个 我在一年前遇到过类似的问题,对此我不太确定,但由于后台不允许执行,因此使用在前台执行,您可以通过启动连接到通知的服务来实现这一点,然后在您的服务中,您可以触发广播,这应该可以正常工作


我希望我的回答能对您有所帮助。

我不确定这个解决方案为什么有效(也许其他人可以详细说明原因),但我能够通过在清单中声明权限并使用相同的权限来触发广播接收器。请在下面查找代码更改:

<permission
    android:name="owner.custom.permission"
    android:protectionLevel="signatureOrSystem">
</permission>
.
.
.
<uses-permission android:name="owner.custom.permission" />

.
.
.

Android O限制隐式广播,您无法在接收器中执行后台服务

但是,它只限制静态接收器,您可以在代码中注册接收器以触发服务

当然,在某些情况下,您不想“以编程方式”执行此操作,那么您应该检查错误情况,从这个链接(第1275行)中,我发现了错误(不确定这是否与您的系统版本相同)

我们可以看到访问此代码块的条件很少,我们逐个分析它们,我们所要做的就是使条件等于
false

(r.intent.getFlags()&intent.FLAG\u RECEIVER\u EXCLUDE\u BACKGROUND)!=0
这意味着如果我们不希望背景接收到意图,那么条件将为真,通常,我们不添加此标志,因为我们希望背景接收广播,请继续

r.intent.getComponent()==null
在我们的任何情况下,它都不应该为空,请继续

r.intent.getPackage()==null
同上,请继续

r.intent.getFlags()&intent.FLAG\u RECEIVER\u INCLUDE\u BACKGROUND)=0
这意味着我们不能有一个名为
Intent的标志。flag\u RECEIVER\u INCLUDE\u BACKGROUND
,我想我们可以试试这个,但您会在Intent类中看到:

/**
*如果设置,广播将始终转到后台的清单接收者(缓存)
*(或不运行)应用程序,不管默认情况下是否会这样做。通过
*默认情况下,只有在广播指定了
*显式组件或包名称。
*
*注意:dumpstate以数字形式使用此标志,因此当其值更改时
*那里的广播代码也必须更改为匹配。
*
*@隐藏
*/
公共静态最终整数标志接收器包括背景=0x01000000;
它是隐藏的,但您可以在项目中硬编码整数,现在将此标志添加到您的意图中,以尝试代码是否有效

intent.addFlags(0x01000000)
祝你好运:)


注意:此解决方案无法解析为接收系统隐式广播以运行后台任务。

这是一个老问题,但我找到了一个适合我的解决方案

如上所述

上下文注册的接收器接收广播时,只要其 注册上下文是有效的。例如,如果您在 在活动上下文中,只要活动处于活动状态,您就可以接收广播 没有被摧毁。如果向应用程序上下文注册,则 只要应用程序正在运行,就可以接收广播

我必须完全删除清单中的接收方声明,并在运行时使用应用程序上下文注册接收方

IntentFilter filter = new IntentFilter("owner.custom.broadcast");
getContext().getApplicationContext().registerReceiver(new MyReceiver(), filter);
然后

public class MyReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        context.unregisterReceiver(this);
        // ....
    }
}

可能重复,但当我在获得许可的情况下收听不同的第三方广播并以相同的方式触发相同的服务时,为什么它会工作。自定义广播不是显式广播吗?不是隐式的?如果我对那些条件写的整个else-if块进行注释呢?你想构建自己的Android ROM吗@ShadowYes@library545是的,你可以,但出于安全考虑,我建议不要。如果您希望自己的服务通过此检查器来执行某些“特殊操作”,则可以在这些条件之后添加外部条件。例如,将key和secret添加到intent包中,并检查handled intent@Shadow的key和secret,当然,最简单的方法是让您的服务使用系统签名进行apk签名
public class MyReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        context.unregisterReceiver(this);
        // ....
    }
}