广播接收器权限被拒绝

Posted

技术标签:

【中文标题】广播接收器权限被拒绝【英文标题】:Broadcast reciever permission denial 【发布时间】:2019-10-24 14:15:31 【问题描述】:

我正在开发一个应用程序,我必须在电话通话时启动一个小部件。

我已经在清单中注册了广播请求:

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
...Other permissions required for screen overlay...

我已经在清单中注册了我的广播接收器:

    <receiver android:name=".phoneReceiver"
        android:exported="true"
        android:enabled="false">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE"/>
        </intent-filter>
    </receiver>

注意:当用户按下按钮时,我会在运行时启用接收器。这也是我请求 perms 的时候,因为我的测试系统运行的是 Android 7.0

然后我在运行时通过按下按钮请求权限:

    btn.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            if(ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_PHONE_STATE)
                    != PackageManager.PERMISSION_GRANTED)
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]Manifest.permission.READ_PHONE_STATE, 2);
                showToast(getApplicationContext(), "Phone state requested");
             else
                enableWidget();    //if permissions are already granted
            
        
    );

我这样等待权限请求的结果:

@Override
public void onRequestPermissionsResult(int req, @NonNull String[] perms, @NonNull int[] results)
    switch(req)
        case 2:
            if(results.length > 0 && results[0]==PackageManager.PERMISSION_GRANTED)
                showToast(this, "Phone state granted");
                enableWidget();
            
            return;
    

enableWidget() 中,我这样启用广播接收器:

private void enableWidget()
    PackageManager pm = MainActivity.this.getPackageManager();
    ComponentName comp = new ComponentName(getApplicationContext(), phoneReceiver.class);
    pm.setComponentEnabledSetting(comp, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);
 

现在根据我的说法,只要状态发生变化,就应该调用接收器,但这不会发生。相反,我在 logcat 中得到以下信息,这让我认为接收器已启用但仍未被调用。

W/BroadcastQueue: Permission Denial: receiving Intent  act=android.intent.action.PHONE_STATE flg=0x10 (has extras)  to com.example.myapplication/.phoneReceiver requires android.permission.READ_PRIVILEGED_PHONE_STATE due to sender android (uid 1000)

我在这里错过了什么?


PS这是我的接收器的 sn-p 减去不必要的东西:

public class phoneReceiver extends BroadcastReceiver 
    @Override
    public void onReceive(Context context, Intent intent) 
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
            if(ContextCompat.checkSelfPermission(context, Manifest.permission.SYSTEM_ALERT_WINDOW)
                != PackageManager.PERMISSION_GRANTED)
                return;
            if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
                != PackageManager.PERMISSION_GRANTED)
                return;
        
        if(intent.getStringExtra(TelephonyManager.EXTRA_STATE)
            .equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
            showToast(context, "In call");
            startWidget(context);
         else if(intent.getStringExtra(TelephonyManager.EXTRA_STATE)
            .equals(TelephonyManager.EXTRA_STATE_IDLE))
            showToast(context, "Out of call");
            stopWidget(context);
        
    
    ...Definitions of showToast, start, stopWidget...


PPS我检查了系统设置中的应用权限,并且“电话”设置为开启。


我尝试通过在 Manifest 中将 Receiver 声明为:

android:enabled="true"

并删除在运行时启用小部件的部分。我仍然在运行时请求权限。我仍然遇到同样的错误。

同样的系统,在 API 级别 22 上工作。

【问题讨论】:

【参考方案1】:

清单声明的接收器:如果您的应用以 API 级别 26 或更高级别为目标,您不能使用清单声明隐式广播的接收器(不针对您的应用程序),除了一些不受该限制Exempted List 的隐式广播。在大多数情况下,您可以改用计划作业。

上下文注册接收器:只要其注册上下文有效,就接收广播。例如,如果您在 Activity 上下文中注册,只要该 Activity 未销毁,您就会收到广播。如果您在应用程序上下文中注册,只要应用程序正在运行,您就会收到广播。

由于内存改进,请查看official site 了解更多详情。

【讨论】:

现在,我的应用程序的目标是 API 级别 24。这里的目的只是了解它的工作原理,而不是创建生产应用程序。 简单来说,您已经使用有效上下文注册了您的接收器以接收数据。这个过程与学习和生产应用程序无关。详情请查看链接。 是的,但所有这些都适用于 API 级别 26 及以上,对吗?我在 24 级工作【参考方案2】:

您可以使用 JobScheduler API 来触发事件,我之前在为我的一个 APP 使用 Geofencing API 时遇到了类似的问题

【讨论】:

我正在寻找使用已有安卓功能的解决方案 好的。我想这应该是你迄今为止所做的正确方法。不知道为什么这对你不起作用。 @ParthK 嘿你能解决这个@ParthK

以上是关于广播接收器权限被拒绝的主要内容,如果未能解决你的问题,请参考以下文章

Broadcast

具有权限级别签名的Android广播接收器不接收广播

用于应用权限的 Android 广播接收器

以编程方式检查广播接收器权限

私人广播发送者和接收者权限

用户在Android应用中停用位置权限时的广播接收器?