2015-10-09 13 views
17

Sto studiando il nuovo modello di autorizzazione di Android Marshmallow ma sto affrontando un problema che trovo strano.checkSelfPermission restituisce PERMISSION_GRANTED per autorizzazione revocata con targetSdkVersion <= 22

Un'applicazione con targetSdkVersion 22 (quindi non ancora utilizzando il nuovo modello di permesso di Android Marshmallow) dichiara il READ_CONTACTS autorizzazione nel manifesto:

<uses-permission android:name="android.permission.READ_CONTACTS" /> 

e cerca di leggere il numero di telefono di un contatto via Intent.ACTION_PICK:

Intent intent = new Intent(Intent.ACTION_PICK); 
intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); 
startActivityForResult(intent, PICK_CONTACT_REQUEST); 

Quando si esegue su un dispositivo con Marshmallow MRA58K, dopo revoco il permesso dopo aver installato l'applicazione tramite ADB, il metodo ContextCompat.checkSelfPermission() ancora restituisce 0.123., ma l'operazione fallisce in seguito quando si accede ai contatti perché viene restituito un cursore senza record. Come ho capito, questa è la strategia predefinita "retrocompatibilità" per evitare l'arresto di un'app legacy.

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == PICK_CONTACT_REQUEST && resultCode == Activity.RESULT_OK) { 
     Log.i("", "Permission granted: " + (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED)); 
     Uri contactUri = data.getData(); 
     Cursor c = null; 
     try { 
      c = getContentResolver().query(contactUri, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER}, null, null, null); 
      if (c != null && c.moveToFirst()) { 
       Log.i("", "got phone number: " + c.getString(0)); 
      } else { 
       Log.w("", "No data received"); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      if (c != null) { 
       c.close(); 
      } 
     } 
    } else { 
     super.onActivityResult(requestCode, resultCode, data); 
    } 
} 

Come posso rilevare in modo sicuro se l'utente esplicitamente prima dell'autorizzazione prima di tentare l'operazione?

Ho anche provato il campione ufficiale di Google in https://github.com/googlesamples/android-RuntimePermissions impostando il targetSdkVersion-22 con lo stesso risultato: si registra che l'autorizzazione viene concessa anche se l'utente revocato esso, formica quindi l'operazione non riesce.

Grazie;)

+1

"il metodo ContextCompat.checkSelfPermission() restituisce ancora PERMISSION_GRANTED" - corretto. 'checkSelfPermission()' restituirà 'PERMISSION_GRANTED' il 100% del tempo per le app con' targetSdkVersion' di 22 e inferiori. "Come posso rilevare in modo sicuro se l'utente esplicitamente prima dell'autorizzazione prima di tentare l'operazione?" - Non puoi in generale. Nel tuo caso, potresti provare a 'query()' perché esiste qualcosa di noto (ad es. Nome), e se ottieni zero risultati, sai che non hai accesso ai dati di contatto. – CommonsWare

+1

Ricorda che se tutto ciò che fai è lavorare con il contatto selezionato proprio quando viene selezionato il contatto, non hai bisogno di 'READ_CONTACTS' affatto, per qualsiasi versione di Android, poiché ti viene automaticamente concesso l'accesso solo per il contatto selezionato . Potresti provare a rimuovere completamente tale autorizzazione, in quanto ciò impedirebbe all'utente di revocarlo. Il tuo caso porta alcuni effetti interessanti; Proverò a eseguire alcuni esperimenti correlati la prossima settimana. – CommonsWare

+0

Hmm, questa mi sembra una pessima scelta di design API. Quindi non c'è altro modo per rilevare un'autorizzazione revocata prima di tentare l'operazione? Forse usando AppOps? – Venator85

risposta

11

Utilizzare l'android.support.v4.content.PermissionChecker

https://developer.android.com/reference/android/support/v4/content/PermissionChecker.html

+1

Funziona come un fascino!Grazie – Venator85

+0

Il mio caso d'uso è un po 'diverso (fotocamera), ma ecco quello che ho trovato: la sostituzione di 'ContextCompat.checkSelfPermission' con' PermissionsChecker.checkSelfPermission' aiuta a verificare se hai davvero il permesso. Il problema è che se stai attivando 'requestPermissions' in base a questo controllo e l'utente fa clic su * Nega *,' onRequestPermissionsResult' riceverà comunque un 'PERMISSION_GRANTED' nella matrice' grantResults'. – TWiStErRob

+0

@TWiStErRob in questo caso, in teoria, è sufficiente verificare nuovamente con 'PermissionChecker' che le autorizzazioni richieste siano concesse. Ma, se usi 'targetSDK' 22 (o inferiore), nel caso in cui l'utente conceda l'autorizzazione, ucciderà la procedura dell'app e il callback non verrà richiamato. Quindi, l'unico modo per gestire correttamente questo è l'aggiornamento a 'targetSDK' 23 – Muzikant

0

Per poter utilizzare i nuovi modelli di autorizzazione (e controllare se la vostra applicazione ha o meno il permesso), è necessario aggiornare lo SDK di destinazione a 23. Non ha alcun senso per mantenere bersaglio 22.

+3

In realtà ha senso in alcuni casi. –

Problemi correlati