Понимание метода разрешения Android 6

Я пытаюсь взять изображение из галереи и установить его в изображение, но в Android 6 есть некоторые проблемы с разрешением. Ниже приведен метод запроса разрешения. Должен ли я попросить прочитать внешнее хранилище или написать внешнее хранилище?

Вот что я сделал до сих пор:

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); } } 

Теперь мой прослушиватель кликов выбирает данные из галереи:

  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; } 

Теперь я хочу получить результат метода getPermissionToReadExternalStorage() поэтому я могу запустить Activity for picking gallery для Android 6. Как я могу получить результат класса void? И еще одна вещь – я должен написать метод для каждого разрешения, которое запрашивает мое приложение?

Поэтому я полностью переписал код для запроса разрешений. Теперь он поддерживает запрос на получение нескольких разрешений и запуск кода с правильным результатом. Также он работает с устройствами preMarshmallow, поэтому вам не нужно проверять и копировать код в этом случае.

Во-первых, создайте класс Activity с этим кодом (вы можете расширить любой необходимый вам король активности, например 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); } } 

Если вы хотите запросить разрешения от Fragments, добавьте этот класс:

 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); } } 

Ваши действия и фрагменты должны расширять эти классы вместо стандартных.

Теперь вы можете запросить разрешения, вызвав метод:

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

Если для работы приложения требуется разрешение, вы должны вызвать этот метод и указать сообщение о том, почему требуется разрешение.

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

НЕ ДОПУСКАЕТ МЕТОД ПО УМОЛЧАНИЮ, КОТОРЫЙ

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

Вот пример запроса контактов:

 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; } }); } 

ПРИМЕЧАНИЕ. Когда вы реализуете PermissionListener, не забудьте вернуть true, когда requestCode является правильным , иначе PermissionListener не будет удален из ArrayList, и вы, скорее всего, получите небольшую утечку памяти.

РЕДАКТИРОВАТЬ

Я переписал код и опубликовал в другом ответе.

Старый ответ:

Да, вы должны каждый раз проверять и запрашивать разрешение.

Обычно я пишу код следующим образом:

 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); } } 

И запустите его так:

  runPermissionCode(Manifest.permission.READ_EXTERNAL_STORAGE, READ_CONTACTS_PERMISSIONS_REQUEST, new Runnable() { @Override public void run() { // your code here } }); 

Я уверен, что это не лучший способ, но, по крайней мере, он дает возможность запросить разрешение и сделать действия более легкими.

Инициализировать свое разрешение

 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 }; 

Проверка устройства и запрос на получение разрешений

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

Проверить разрешение предоставлено Или нет

 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); } 

Обновить разрешения и метод проверки разрешений 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; } }