2015-12-10 15 views
5

Sto cercando di acquisire un'immagine dalla Galleria e impostarla su una visualizzazione di immagini ma in Android 6 ci sono alcuni problemi di autorizzazione. Di seguito è il metodo per chiedere il permesso. Dovrei chiedere di leggere la memoria esterna o scrivere una memoria esterna?Comprendere il metodo di autorizzazione di Android 6

Ecco quello che ho fatto finora:

private static final int READ_CONTACTS_PERMISSIONS_REQUEST = 1; 


    public void getPermissionToReadExternalStorage() { 

    if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) 
      != PackageManager.PERMISSION_GRANTED) { 

     if (shouldShowRequestPermissionRationale(
       Manifest.permission.READ_EXTERNAL_STORAGE)) { 

      requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        READ_CONTACTS_PERMISSIONS_REQUEST); 
     }}} 
    @Override 
      public void onRequestPermissionsResult(int requestCode, 
                @NonNull String permissions[], 
                @NonNull int[] grantResults){ 
       // Make sure it's our original READ_CONTACTS request 
       if (requestCode == READ_CONTACTS_PERMISSIONS_REQUEST) { 
        if (grantResults.length == 1 && 
          grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
         Toast.makeText(getActivity(), "Read Contacts permission granted", Toast.LENGTH_SHORT).show(); 

        } else { 
         Toast.makeText(getActivity(), "Read Contacts permission denied", Toast.LENGTH_SHORT).show(); 
        } 
       } else { 
        super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
       } 
      } 

Ora il mio al clic ascoltatore a prendere i dati dalla Galleria:

 pro.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
      intent.setType("image/*"); 
      if (android.os.Build.VERSION.SDK_INT >= 23) { 
       getPermissionToReadExternalStorage(); 
       if (getPermissionToReadExternalStorage() this???? <==) 
       startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0); 
      } else { 
       startActivityForResult(Intent.createChooser(intent, "Select Picture"), 0); 
     }} 

    }); 
    return v; 
} 

Ora voglio ottenere risultato del metodo getPermissionToReadExternalStorage() così Posso avviare Activity for picking gallery per Android 6. Come posso ottenere il risultato della classe void? E un'altra cosa è scrivere un metodo per ogni permesso richiesto dalla mia app?

risposta

6

Quindi ho completamente riscritto il codice per richiedere le autorizzazioni. Ora supporta la richiesta di permessi multipli e il codice in esecuzione con il risultato corretto. Funziona anche con i dispositivi preMarshmallow, quindi non è necessario controllare e copiare il codice in quel caso.

In primo luogo, creare una classe di attività con questo codice (È possibile estendere ad ogni tipo di attività è necessario, ad esempio AppCompatActivity):

public abstract class PermissionActivity extends AppCompatActivity { 

    private final ArrayList<PermissionListener> permissionListeners = new ArrayList<>(); 

    @SuppressWarnings("unused") 
    public void requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) { 
     requestPermissions(requestCode, requestPermissions, null, permissionListener); 
    } 

    @SuppressWarnings("unused") 
    public void requestPermissions(final int requestCode, String[] requestPermissions, String message, final PermissionListener permissionListener) { 
     final int[] grantResults = new int[requestPermissions.length]; 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
      ArrayList<String> list_notGranted = new ArrayList<>(); 

      for (String requestPermission : requestPermissions) 
       if (ContextCompat.checkSelfPermission(this, requestPermission) != PackageManager.PERMISSION_GRANTED) 
        list_notGranted.add(requestPermission); 

      if (list_notGranted.size() > 0) { 
       permissionListeners.add(permissionListener); 

       requestPermissions = list_notGranted.toArray(new String[list_notGranted.size()]); 

       if (message != null) { 
        boolean shouldShowRequestPermissionRationale = false; 

        for (String permission : requestPermissions) 
         if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) { 
          shouldShowRequestPermissionRationale = true; 
          break; 
         } 

        if (shouldShowRequestPermissionRationale) { 
         final String[] f_requestPermissions = requestPermissions; 

         AlertDialog.Builder builder = new AlertDialog.Builder(this); 

         builder.setMessage(message); 

         DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() { 

          @TargetApi(Build.VERSION_CODES.M) 
          @Override 
          public void onClick(DialogInterface dialog, int which) { 
           switch (which) { 
            case DialogInterface.BUTTON_POSITIVE: 
             PermissionActivity.super.requestPermissions(f_requestPermissions, requestCode); 
             break; 
            default: 
             for (int i = 0; i < grantResults.length; i++) 
              grantResults[i] = PackageManager.PERMISSION_DENIED; 

             if (permissionListener != null) 
              permissionListener.onResult(requestCode, f_requestPermissions, grantResults); 
             break; 
           } 
          } 
         }; 

         builder.setPositiveButton("OK", onClickListener); 
         builder.setNegativeButton("Cancel", onClickListener); 

         builder.show(); 
        } else { 
         super.requestPermissions(requestPermissions, requestCode); 
        } 
       } else { 
        super.requestPermissions(requestPermissions, requestCode); 
       } 
      } else { 
       for (int i = 0; i < grantResults.length; i++) 
        grantResults[i] = PackageManager.PERMISSION_GRANTED; 

       if (permissionListener != null) 
        permissionListener.onResult(requestCode, requestPermissions, grantResults); 
      } 
     } else { 
      if (permissionListener != null) { 
       for (int i = 0; i < grantResults.length; i++) 
        grantResults[i] = PackageManager.PERMISSION_GRANTED; 

       permissionListener.onResult(requestCode, requestPermissions, grantResults); 
      } 
     } 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { 
     for (Iterator<PermissionListener> it = permissionListeners.iterator(); it.hasNext();) { 
      PermissionListener permissionListener = it.next(); 
      if (permissionListener.onResult(requestCode, permissions, grantResults)) { 
       it.remove(); 
      } 
     } 
    } 

    public interface PermissionListener { 

     boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults); 

    } 
} 

Se si desidera richiedere autorizzazioni dalla Frammenti, aggiungere questa classe:

public class PermissionFragment extends Fragment { 

    @SuppressWarnings("unused") 
    public void requestPermissions(int requestCode, String[] requestPermissions, PermissionActivity.PermissionListener permissionListener) { 
     requestPermissions(requestCode, requestPermissions, null, permissionListener); 
    } 

    @SuppressWarnings("unused") 
    public void requestPermissions(final int requestCode, String[] requestPermissions, String message, PermissionActivity.PermissionListener permissionListener) { 
     ((PermissionActivity) getActivity()).requestPermissions(requestCode, requestPermissions, message, permissionListener); 
    } 
} 

Le tue attività e frammenti dovrebbero estendere queste classi anziché quelle standard.

Ora siete pronti per richiedere i permessi chiamando un metodo:

requestPermissions(int requestCode, String[] requestPermissions, PermissionListener permissionListener) 

Se si richiede la licenza per l'applicazione al lavoro, si dovrebbe chiamare questo metodo e specificare il messaggio che il motivo per cui si richiede la licenza .

requestPermissions(int requestCode, String[] requestPermissions, String message, PermissionListener permissionListener) 

NON MISSCALL il metodo di default, che è

// DON'T USE THIS ONE! 
requestPermissions(String[] requestPermissions, int requestCode) 
// DON'T USE THIS ONE! 

Ecco l'esempio di contatti che chiedono:

private void requestAndLoadContacts() { 
    String[] permissions = new String[]{Manifest.permission.READ_CONTACTS}; 

    requestPermissions(REQUEST_PERMISSIONS_CONTACTS, permissions, "Read contacts permission is required for the app to work!", new PermissionListener() { 

     @Override 
     public boolean onResult(int requestCode, String[] requestPermissions, int[] grantResults) { 
      // Check if the requestCode is ours 
      if (requestCode == REQUEST_PERMISSIONS_CONTACTS) { 
       // Check if the permission is correct and is granted 
       if (requestPermissions[0].equals(Manifest.permission.READ_CONTACTS) && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
        // Permission granted 
        // Calling a method to actually load the contacts 
        loadContacts(); 
       } else { 
        // Permission not granted 
        Toast.makeText(MainActivity.this, "Access denied!", Toast.LENGTH_SHORT).show(); 
       } 

       return true; 
      } 

      return false; 
     } 
    }); 
} 

NOTA: Quando si implementa il PermissionListener, non dimenticare a restituisce true quando il codice di richiesta è quello corretto, diverso rwise il PermissionListener non verrà rimosso da da ArrayList e molto probabilmente si verificherà una piccola perdita di memoria.

+0

Grazie amico. Ti ho preso. –

+0

Buona idea! È possibile migliorare l'uso di ContextCompat che gestisce le vecchie versioni di Android? Grazie! – Gilian

+1

Ma "permissionListeners.remove (permissionListener);" non lanciare un ConcurrentModificationException? – Gilian

0

EDIT

Ho rewritted il codice e pubblicato in un'altra risposta.

Vecchia risposta:

Sì, è necessario controllare e chiedere il permesso ogni volta.

Di solito scrivo il codice come questo:

private int requestPermissionCode; 
private Runnable requestPermissionRunnable; 

private void runPermissionCode(String requestPermission, int requestCode, Runnable codeToRun) { 
    if (android.os.Build.VERSION.SDK_INT >= 23) { 
     if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) 
       != PackageManager.PERMISSION_GRANTED) { 

      requestPermissionCode = requestCode; 
      requestPermissionRunnable = codeToRun; 

      requestPermissions(new String[]{requestPermission}, 
        requestCode); 
     } 
    } else { 
     codeToRun.run(); 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, 
             @NonNull String permissions[], 
             @NonNull int[] grantResults) { 
    if (requestCode == requestPermissionCode) { 
     if (grantResults.length == 1 && 
       grantResults[0] == PackageManager.PERMISSION_GRANTED) { 

      if (requestPermissionRunnable != null) 
       requestPermissionRunnable.run(); 
     } else { 
      Toast.makeText(getActivity(), "Permission denied", Toast.LENGTH_SHORT).show(); 
     } 
    } else { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
    } 
} 

ed eseguirlo in questo modo:

runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() { 

     @Override 
     public void run() { 
      // your code here 
     } 
    }); 

Sono sicuro che non è un modo migliore, ma almeno dà la possibilità di richiedere il permesso e rendere le azioni più facili.

+0

ma come si usa ?? o lo usi quando l'utente sta per cliccare qualcosa ????? Quindi il permesso è concesso puoi fare il tuo compito.? come lo useresti nel mio caso? o in ogni altro caso, mostrami il codice con il tipo di ascoltatore. –

0

inizializzare il vostro permesso

private static final int INITIAL_REQUEST = 1337; 
private static final int GET_ACCOUNTS = INITIAL_REQUEST+2; 
private static final int LOCATION_REQUEST =INITIAL_REQUEST+3; 

private static final String[] INITIAL_PERMS = { 
     Manifest.permission.GET_ACCOUNTS, 
     Manifest.permission.INTERNET, 
     Manifest.permission.ACCESS_FINE_LOCATION 
}; 

Verificare la presenza del dispositivo e richiesta di permessi è concessa

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     if (!canAccessAccounts()|| !canAccessLocation() ||!canAccessInternet()) { 
      requestPermissions(INITIAL_PERMS, INITIAL_REQUEST); 
     } 
    } 

check permesso o non

private boolean canAccessAccounts() { 

    return (hasPermission(Manifest.permission.GET_ACCOUNTS)); 
} 
private boolean canAccessLocation() { 

    return (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)); 
} 
private boolean canAccessInternet() { 
    return (hasPermission(Manifest.permission.INTERNET)); 
} 
private boolean hasPermission(String perm) { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     return (PackageManager.PERMISSION_GRANTED == checkSelfPermission(perm)); 
    } 
    return (true); 
} 

Aggiorna permessi e check metodo per le autorizzazioni di onRequestPermissionsResult

void UpdatePermissions(){ 

    canAccessInternet(); 
    canAccessLocation(); 
    canAccessInternet(); 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
    UpdatePermissions(); 
    switch(requestCode) { 
     case GET_ACCOUNTS: 
      if (canAccessAccounts()) { 

      } 
      else { 

      } 
      break; 

     case LOCATION_REQUEST: 
      if (canAccessLocation()) { 

      } 
      else { 

      } 
      break; 

     case INITIAL_REQUEST: 
      if(canAccessInternet()){ 

      }else { 

      } 
      break; 

    } 
} 
Problemi correlati