Je viens de mettre à jour mon Nexus 5 vers Android 6, jusqu'à présent mon application fonctionnait bien, mais maintenant les récepteurs de diffusion ne fonctionnent pas. Quelque chose a changé dans la nouvelle version? Voici le code que j'ai essayé qui fonctionnait sur les versions précédentes mais pas dans Marshmallow -
Manifeste 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>
récepteur de diffusion
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...");
}
}
Service
Broadcast_receiver broadcast_receiver = new Broadcast_receiver();
IntentFilter filter1 = new IntentFilter();
filter1.addAction("Android.provider.Telephony.SMS_RECEIVED");
registerReceiver(broadcast_receiver, filter1);
De même, le récepteur de diffusion pour PHONE_STATE ne fonctionne pas non plus.
Le niveau d'API cible de votre application est de 23, soit Android M (6.0). Dans Android M, il y a d'énormes changements liés aux autorisations utilisateur. Ici est un bel article expliquant les changements.
Comme indiqué dans Android - Demande d'autorisations
À partir de Android 6.0 (API niveau 23), les utilisateurs accordent des autorisations aux applications pendant que l'application est en cours d'exécution, pas lorsqu'ils installent l'application ... L'utilisateur peut révoquer les autorisations à tout moment .. .
Il est également indiqué que:
Les autorisations système sont divisées en deux catégories, normales et dangereuses:
Les autorisations normales ne compromettent pas directement la confidentialité de l'utilisateur. Si votre application répertorie une autorisation normale dans son manifeste, le système accorde automatiquement l'autorisation
Des autorisations dangereuses peuvent donner à l'application accès aux données confidentielles de l'utilisateur. Si vous indiquez une autorisation dangereuse, l'utilisateur doit explicitement approuver votre application
Voici la liste complète des autorisations dangereuses et autorisations normales
Tout cela signifie essentiellement que vous devez demander manuellement une autorisation dangereuse, lorsqu'elle est réellement nécessaire.
Puisqu'il peut potentiellement être nécessaire plusieurs fois dans votre code, vous pouvez créer une méthode réutilisable qui vérifie si une autorisation spécifique est déjà accordée et si elle ne l'est pas - pour la demander à l'utilisateur.
Voici un exemple:
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)
}
}
}
Usage:
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
}
}
}
Remarque:
Si vous devez utiliser PermissionManager.check
À l'intérieur de l'instance Fragment
, utilisez: getActivity()
comme premier paramètre.
Vous pouvez utiliser checkSelfPermission
à l'intérieur de l'instance Service
, pour vérifier si une autorisation est déjà accordée, mais pas requestPermissions
pour le demander. Parce que checkSelfPermission
peut être utilisé pour n'importe quel Context
, mais requestPermissions
uniquement pour Activity
Marshmallow bloque les autorisations dangereuses.
Cela ne s'applique pas au scénario répertorié, mais cela pourrait aider quelqu'un d'autre. Je n'arrêtais pas d'y arriver SO pour savoir pourquoi certains de nos récepteurs de diffusion ne fonctionnaient pas. Nous avons une configuration d'autorisation personnalisée et avions le Android:protectionLevel="dangerous"
. Changé en Android:protectionLevel= "signature"
et tout a commencé à fonctionner.