Ошибка разрешения на хранение в Marshmallow
в Lollipop функция загрузки отлично работает в моем приложении, но когда я обновился до Marshmallow, мое приложение падает и выдает эту ошибку при попытке загрузить из интернета на SD-карту:
Neither user nor current process has android.permission.WRITE_EXTERNAL_STORAGE
Он жалуется на эту строку кода:
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
у меня есть разрешения в манифесте наружного применения:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
я очистил и перестроил проект, но он все равно падает.
11 ответов:
вы должны проверить, если пользователь предоставил разрешение на внешнее хранилище с помощью:
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { Log.v(TAG,"Permission is granted"); //File write logic here return true; }
если нет, вам нужно попросить пользователя предоставить вашему приложению разрешение:
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
конечно, это только для зефира устройств, так что вам нужно проверить, если ваше приложение работает на зефир:
if (Build.VERSION.SDK_INT >= 23) { //do your check here }
также убедитесь, что ваша деятельность реализует
OnRequestPermissionResult
все разрешение выглядит так это:
public boolean isStoragePermissionGranted() { if (Build.VERSION.SDK_INT >= 23) { if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { Log.v(TAG,"Permission is granted"); return true; } else { Log.v(TAG,"Permission is revoked"); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1); return false; } } else { //permission is automatically granted on sdk<23 upon installation Log.v(TAG,"Permission is granted"); return true; } }
результат разрешения обратного вызова:
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]); //resume tasks needing this permission } }
система разрешений Android является одним из самых больших проблем безопасности все наряду с тем, что эти разрешения запрашиваются во время установки. Однажды установлено, приложение сможет получить доступ ко всем вещам предоставлено без подтверждения пользователя какое именно приложение делает с разрешения.
Android 6.0 Marshmallow вводит одно из самых больших изменений в модель разрешений с добавлением разрешений среды выполнения, новая разрешение модель, которая заменяет существующие разрешения времени установки модель, когда вы нацелены на API 23 и приложение работает на Android 6.0+ устройство
вежливость идет запрос разрешений во время выполнения .
пример
объявить как Global
private static final int PERMISSION_REQUEST_CODE = 1;
добавьте это в свой
onCreate()
разделпосле setContentView (R. layout.your_xml);
if (Build.VERSION.SDK_INT >= 23) { if (checkPermission()) { // Code for above or equal 23 API Oriented Device // Your Permission granted already .Do next code } else { requestPermission(); // Code for permission } } else { // Code for Below 23 API Oriented Device // Do next code }
добавляем checkPermission () и requestPermission()
private boolean checkPermission() { int result = ContextCompat.checkSelfPermission(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); if (result == PackageManager.PERMISSION_GRANTED) { return true; } else { return false; } } private void requestPermission() { if (ActivityCompat.shouldShowRequestPermissionRationale(Your_Activity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { Toast.makeText(Your_Activity.this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show(); } else { ActivityCompat.requestPermissions(Your_Activity.this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSION_REQUEST_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.e("value", "Permission Granted, Now you can use local drive ."); } else { Log.e("value", "Permission Denied, You cannot use local drive ."); } break; } }
справка
этот интерфейс является контрактом на получение результатов для запрос разрешений.
Если нет определенного требования записи на внешнее хранилище, вы всегда можете сохранить файлы в каталоге приложений. В моем случае я должен был сохранить файлы и после потери 2 до 3 дней я узнал, если я изменить путь хранения от
Environment.getExternalStorageDirectory()
до
getApplicationContext().getFilesDir().getPath() //which returns the internal app files directory path
он работает как шарм на всех устройствах. Это связано с тем, что для записи на внешнее хранилище вам нужны дополнительные разрешения, но запись во внутренний каталог приложений проста.
проверьте несколько разрешений на уровне API 23 Шаг 1:
String[] permissions = new String[]{ Manifest.permission.INTERNET, Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.VIBRATE, Manifest.permission.RECORD_AUDIO, };
Шаг 2:
private boolean checkPermissions() { int result; List<String> listPermissionsNeeded = new ArrayList<>(); for (String p : permissions) { result = ContextCompat.checkSelfPermission(this, p); if (result != PackageManager.PERMISSION_GRANTED) { listPermissionsNeeded.add(p); } } if (!listPermissionsNeeded.isEmpty()) { ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100); return false; } return true; }
Шаг 3:
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { if (requestCode == 100) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // do something } return; } }
Шаг 4: в onCreate деятельности checkPermissions ();
вам нужно использовать разрешение времени выполнения в зефире https://developer.android.com/training/permissions/requesting.html
вы можете проверить информацию о приложении - > разрешение
ваше приложение получить разрешение на запись на внешний носитель или нет
Кажется, пользователь отклонил разрешение и приложение пытается записать на внешний диск, вызывая ошибку.
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_READ_CONTACTS: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. } else { // permission denied, boo! Disable the // functionality that depends on this permission. } return; } // other 'case' lines to check for other // permissions this app might request } }
проверить https://developer.android.com/training/permissions/requesting.html
Это видео даст вам лучшее представление о UX, обработка разрешений во время выполненияhttps://www.youtube.com/watch?v=iZqDdvhTZj0
из версии marshmallow разработчики должны запрашивать разрешения на выполнение для пользователя. Позвольте мне дать вам весь процесс для запроса разрешений во время выполнения.
Я использую ссылку отсюда:зефир разрешения во время выполнения android.
сначала создайте метод, который проверяет, все ли разрешения даны или нет
private boolean checkAndRequestPermissions() { int camerapermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); int writepermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); int permissionLocation = ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION); int permissionRecordAudio = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO); List<String> listPermissionsNeeded = new ArrayList<>(); if (camerapermission != PackageManager.PERMISSION_GRANTED) { listPermissionsNeeded.add(Manifest.permission.CAMERA); } if (writepermission != PackageManager.PERMISSION_GRANTED) { listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); } if (permissionLocation != PackageManager.PERMISSION_GRANTED) { listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION); } if (permissionRecordAudio != PackageManager.PERMISSION_GRANTED) { listPermissionsNeeded.add(Manifest.permission.RECORD_AUDIO); } if (!listPermissionsNeeded.isEmpty()) { ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS); return false; } return true; }
теперь вот код, который выполняется после выше метода. Мы будем переопределять
onRequestPermissionsResult()
способ :@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { Log.d(TAG, "Permission callback called-------"); switch (requestCode) { case REQUEST_ID_MULTIPLE_PERMISSIONS: { Map<String, Integer> perms = new HashMap<>(); // Initialize the map with both permissions perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED); perms.put(Manifest.permission.RECORD_AUDIO, PackageManager.PERMISSION_GRANTED); // Fill with actual results from user if (grantResults.length > 0) { for (int i = 0; i < permissions.length; i++) perms.put(permissions[i], grantResults[i]); // Check for both permissions if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "sms & location services permission granted"); // process the normal flow Intent i = new Intent(MainActivity.this, WelcomeActivity.class); startActivity(i); finish(); //else any one or both the permissions are not granted } else { Log.d(TAG, "Some permissions are not granted ask again "); //permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission // // shouldShowRequestPermissionRationale will return true //show the dialog or snackbar saying its necessary and try again otherwise proceed with setup. if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) { showDialogOK("Service Permissions are required for this app", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_POSITIVE: checkAndRequestPermissions(); break; case DialogInterface.BUTTON_NEGATIVE: // proceed with logic by disabling the related features or quit the app. finish(); break; } } }); } //permission is denied (and never ask again is checked) //shouldShowRequestPermissionRationale will return false else { explain("You need to give some mandatory permissions to continue. Do you want to go to app settings?"); // //proceed with logic by disabling the related features or quit the app. } } } } } }
если пользователь нажимает на запретить затем
showDialogOK()
метод будет использоваться для отображения диалогаесли пользователь нажимает на запретить и щелкает флажок с надписью "Никогда не спрашивайте снова", потом
explain()
метод будет использоваться для отображения диалогового окна.методы отображения диалогов:
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) { new AlertDialog.Builder(this) .setMessage(message) .setPositiveButton("OK", okListener) .setNegativeButton("Cancel", okListener) .create() .show(); } private void explain(String msg){ final android.support.v7.app.AlertDialog.Builder dialog = new android.support.v7.app.AlertDialog.Builder(this); dialog.setMessage(msg) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { // permissionsclass.requestPermission(type,code); startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.exampledemo.parsaniahardik.marshmallowpermission"))); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface paramDialogInterface, int paramInt) { finish(); } }); dialog.show(); }
выше фрагмент кода запрашивает четыре разрешения одновременно. Вы также можете запросить любое количество разрешений в вашем любом деятельность согласно вашим требованиям.
после долгих поисков этот код работает для меня:
проверьте разрешение уже есть: Проверка разрешения WRITE_EXTERNAL_STORAGE разрешена или нет?
if(isReadStorageAllowed()){ //If permission is already having then showing the toast //Toast.makeText(SplashActivity.this,"You already have the permission",Toast.LENGTH_LONG).show(); //Existing the method with return return; }else{ requestStoragePermission(); } private boolean isReadStorageAllowed() { //Getting the permission status int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); //If permission is granted returning true if (result == PackageManager.PERMISSION_GRANTED) return true; //If permission is not granted returning false return false; } //Requesting permission private void requestStoragePermission(){ if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)){ //If the user has denied the permission previously your code will come to this block //Here you can explain why you need this permission //Explain here why you need this permission } //And finally ask for the permission ActivityCompat.requestPermissions(this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE},REQUEST_WRITE_STORAGE); }
реализовать переопределение onRequestPermissionsResult метод для проверки является пользователь разрешить или запретить
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //Checking the request code of our request if(requestCode == REQUEST_WRITE_STORAGE){ //If permission is granted if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ //Displaying a toast Toast.makeText(this,"Permission granted now you can read the storage",Toast.LENGTH_LONG).show(); }else{ //Displaying another toast if permission is not granted Toast.makeText(this,"Oops you just denied the permission",Toast.LENGTH_LONG).show(); } }
это сработало для меня
boolean hasPermission = (ContextCompat.checkSelfPermission(AddContactActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED); if (!hasPermission) { ActivityCompat.requestPermissions(AddContactActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_WRITE_STORAGE: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //reload my activity with permission granted or use the features what required the permission } else { Toast.makeText(AddContactActivity.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show(); } } } }
Try this int permission = ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { Log.i("grant", "Permission to record denied"); if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(getString(R.string.permsg)) .setTitle(getString(R.string.permtitle)); builder.setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Log.i("grant", "Clicked"); makeRequest(); } }); AlertDialog dialog = builder.create(); dialog.show(); } else { //makeRequest1(); makeRequest(); } } protected void makeRequest() { ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 500); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case 500: { if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Log.i("1", "Permission has been denied by user"); } else { Log.i("1", "Permission has been granted by user"); } return; } } }
перед началом загрузки Проверьте свои разрешения во время выполнения и если у вас нет разрешения разрешения запроса, как этот метод
requestStoragePermission()
private void requestStoragePermission(){ if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)) { } ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_CODE); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(requestCode == STORAGE_PERMISSION_CODE){ if(grantResults.length >0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){ } else{ Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show(); } } }