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