Android 6.0 Marshmallow中广播接收器不起作用

13
我刚刚把我的Nexus 5 升级到了Android 6系统,之前我的应用程序一直运行良好。但是现在广播接收器不起作用了。新版本中是否有什么变化?以下是我之前可用但现在在Marshmallow上无效的代码:

Android清单文件

    <intent-filter >
        <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
<uses-permission android:name="android.permission.READ_SMS" ></uses-permission>

广播接收器

public String TAG ="someClass";
private static String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (action.equalsIgnoreCase(ACTION_SMS_RECEIVED)) {
        Log.d(TAG, "Received...");
    }
}

服务

Broadcast_receiver broadcast_receiver = new Broadcast_receiver();
IntentFilter filter1 = new IntentFilter();
filter1.addAction("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(broadcast_receiver, filter1);

同样地,PHONE_STATE的广播接收器也无法工作。


你的项目的最高和最低SDK版本是多少? - Artur Szymański
最小值为18,目标值为23。 - Imdad
3个回答

16

您的应用程序的目标API级别为23,即安卓M(6.0)。在安卓M中,涉及用户权限的变化非常大。 这里有一篇很好的文章介绍了这些变化。


1
谢谢,我懂了,链接在这里 - http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html - Imdad
@Jack的糟糕代码 - 请问您能否解释一下您是如何解决这个问题的。我也遇到了完全相同的问题...谢谢! - Kanchu
1
@Kanchu,对于Android M,你需要运行时权限,仅在清单文件中声明是不够的。当使用需要该权限的功能时,请请求运行时权限。要实现运行时权限,请参阅Android开发人员指南或直接搜索谷歌(有很多链接可供参考)。 - Imdad
2
谢谢,我为此苦苦挣扎了两天,这个链接解决了问题- https://developer.android.com/training/permissions/requesting.html - Harshveer Singh

10
根据Android - 请求权限,自 Android 6.0 (API level 23) 开始,用户授予应用程序权限时,不是在安装应用程序时进行授权,而是在应用程序运行时进行授权。 用户可以随时撤销权限。
还指出:
系统权限分为两类,正常权限和危险权限:
1.正常权限不会直接影响用户的隐私。如果您的应用在其清单中列出了正常权限,则系统将自动授予权限。
2.危险权限可能会使应用访问用户的机密数据。如果您列出了危险权限,用户必须明确批准您的应用程序。
这里提供完整的危险权限正常权限列表。
基本上,这意味着需要在实际需要危险权限的情况下手动请求它。
由于在代码中可能需要多次使用它,因此您可以创建一个可重复使用的方法,检查特定权限是否已被授予,如果未授予,则向用户请求该权限。
以下是一些示例: Java
public class PermissionManager {
    //A method that can be called from any Activity, to check for specific permission
    public static void check(Activity activity, String permission, int requestCode){
        //If requested permission isn't Granted yet 
        if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
            //Request permission from user
            ActivityCompat.requestPermissions(activity,new String[]{permission},requestCode);
        }
    }
}

Kotlin

object PermissionManager {
    //A method that can be called from any Activity, to check for specific permission
    fun check(activity: Activity, permission: String, requestCode: Int) {
        //If requested permission isn't Granted yet
        if (ActivityCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
            //Request permission from user
            ActivityCompat.requestPermissions(activity, arrayOf(permission), requestCode)
        }
    }
}

使用方法:

Java

//Inside your activity:
//1. Define static constant for each permission request
public static final int REQUEST_CODE_FOR_SMS=1;
//2. When needed (for example inside .onStart event) use method PermissionManager.check for requested permission 
@Override
protected void onStart() {
    super.onStart();
    PermissionManager.check(this, Manifest.permission.RECEIVE_SMS, REQUEST_CODE_FOR_SMS);
}
//3. Handle User's response for your permission request
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if(requestCode==REQUEST_CODE_FOR_SMS){//response for SMS permission request
        if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
            //What to do if User allowed SMS permission
        }else{
            //What to do if user disallowed requested SMS permission
        }
    }
}

Kotlin

//Inside your activity:
//1. Define static constant for each permission request
val REQUEST_CODE_FOR_SMS = 1
//2. When needed (for example inside .onStart event) use method PermissionManager.check for requested permission
override fun onStart() {
    super.onStart()
    PermissionManager.check(this, Manifest.permission.RECEIVE_SMS, REQUEST_CODE_FOR_SMS)
}

//3. Handle User's response for your permission request
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
    if (requestCode == REQUEST_CODE_FOR_SMS) {//response for SMS permission request
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //What to do if User allowed SMS permission
        } else {
            //What to do if user disallowed requested SMS permission
        }
    }
}

注意:

  1. 如果您需要在Fragment实例中使用PermissionManager.check,请将getActivity()作为其第一个参数。

  2. 您可以在Service实例中使用checkSelfPermission来检查某个权限是否已被授予,但不能使用requestPermissions请求它。因为checkSelfPermission可用于任何Context,而requestPermissions仅适用于Activity


这与问题的答案不相符。我认为权限与待机模式以及未调用广播没有关系。 - Mostafa Imran

3

Marshmallow(棉花糖)正在阻止危险权限。

这并不适用于列出的情况,但可能会帮助其他人。我一直来到这个SO寻求帮助,想知道为什么我们的某些广播接收器无法正常工作。我们有一个自定义权限设置,并且设置了android:protectionLevel="dangerous"。将其更改为android:protectionLevel="signature",一切都开始正常工作了。


2
嘿,我也遇到了同样的问题。你能否解释一下,在哪里应该使用这个语句? - Jatin Khattar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接