棉花糖存储权限错误
在棒棒糖中,下载function在我的应用程序中工作正常,但当我升级到棉花糖,我的应用程序崩溃,并尝试从互联网下载到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" />
我清理和重build了这个项目,但仍然崩溃。
您应该检查用户是否已经使用以下方式授予了外部存储的权限:
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; } }
权限结果callback:
@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及更高版本的设备上运行时,将replace现有的安装时间权限模型
礼貌去运行时请求权限 。
例
声明这是全球
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; } }
FYI
onRequestPermissionsResult
该接口是用于接收许可请求结果的合同。
除非在外部存储器上有明确的写入要求,否则可以select将文件保存在应用程序目录中。 在我的情况下,我不得不保存文件,浪费了2到3天后,我发现如果我改变了存储path
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步:在活动checkPermissions()的onCreate;
你需要在棉花糖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
此video将为您提供有关UX的更好的概念,处理运行时权限https://www.youtube.com/watch?v=iZqDdvhTZj0
经过大量的search这段代码适合我:
检查权限已经有了:检查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(); } } } }
从棉花糖版本开发者需要向用户请求运行时权限。 让我给你提供运行时权限的整个过程。
我从这里使用的参考: 棉花糖运行时权限android 。
首先创build一个方法来检查是否给定所有的权限
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()
方法显示对话框
如果用户点击拒绝 ,并点击一个checkbox,说“再也不问” ,那么将使用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(); }
上面的代码片段一次要求四个权限。 您也可以根据您的要求在任何活动中要求任意数量的权限。
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; } } }