0

下面的代码工作正常的棉花糖前的设备,但不是在棉花糖。没有这样的文件或目录只在Android 6.0

这些都是在清单

<uses-permission android:name="android.permission.INTERNET" /> 
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 

这里的权限是代码

public void saveImageToSDCard(Bitmap bitmap) { 
    File myDir = new File(
      Environment 
        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), 
      pref.getGalleryName()); 

    myDir.mkdirs(); 
    Random generator = new Random(); 
    int n = 10000; 
    n = generator.nextInt(n); 
    String fname = "Wallpaper-" + n + ".jpg"; 
    File file = new File(myDir, fname); 
    if (file.exists()) 
     file.delete(); 
    try { 
     FileOutputStream out = new FileOutputStream(file); 
     bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); 
     out.flush(); 
     out.close(); 
     Uri uri = getImageContentUri(_context,file); 

     Log.d(TAG, "Wallpaper saved to: " + file.getAbsolutePath()); 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

而同样的代码工作时,我手动允许存储许可

下面是解由Nitesh Pareek提供。

private boolean hasPermissions(Context context, String[] permissions) { 
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) { 
     for (String permission : permissions) { 
      if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { 
       return false; 
      } 
     } 
    } 
    return true; 
} 
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}; 

    if (!hasPermissions(this, PERMISSIONS)) { 
     ActivityCompat.requestPermissions(this, PERMISSIONS, 11); 
     return; 
    } 
+1

使用'运行时间为Permission' *在Android 6.0 *这里指https://developer.android.com/training/permissions/requesting.html使用。 –

回答

1

给运行时读取棉花糖或较新版本的写入权限。 做象下面这样: -

String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE}; 

if (!hasPermissions(this, PERMISSIONS)) { 
      ActivityCompat.requestPermissions(this, PERMISSIONS, 11); 
      return; 
     } 

private boolean hasPermissions(Context context, String... permissions) { 
     if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) { 
      for (String permission : permissions) { 
       if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { 
        return false; 
       } 
      } 
     } 
     return true; 
    } 
+0

谢谢,按预期工作。 –

1

你需要安装/更新的惯例

时的Android 6.0(API级别23)开始采取应用程序的权限在运行时,而不是采取,用户授予权限 应用正在运行,而不是在安装应用时。这 方法简化了应用程序的安装过程,因为用户没有 需要在安装时授予权限或更新应用

如需更多帮助:Requesting Permissions at Run Time

通过专注于文档和后做一些谷歌搜索,最后我编译了下面的代码来有效地处理运行时权限

要使其工作,您需要按照以下说明操作:

调用此方法检查用户是否授予存储权限? 如果没有,那么你需要请求它

public static boolean isStoragePermissionGranted(Activity activity) { 
    boolean flag = false; 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     flag = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED; 
    } 
    return flag; 
} 

调用此方法来请求存储许可

public static void requestStoragePermission(Activity activity) { 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     if (isStoragePermissionGranted(activity)) { 
      return; 
     } 

     // Fire off an async request to actually get the permission 
     // This will show the standard permission request dialog UI 
     activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
       REQUEST_CODE_STORAGE_PERMISSION); 
    } 
} 

实现您的活动这种方法来处理权限回调的响应

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults); 

    switch (requestCode) { 
     case REQUEST_CODE_STORAGE_PERMISSION: 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
       if (grantResults.length > 0) { 
        if (grantResults[0] == PackageManager.PERMISSION_DENIED) { 
         boolean shouldShowRationale = shouldShowRequestPermissionRationale(permissions[0]); 
         if (!shouldShowRationale) { 
          // user denied flagging NEVER ASK AGAIN, you can either enable some fall back, 
          // disable features of your app or open another dialog explaining again the permission and directing to 
          // the app setting 
          dialogReasonStoragePermissionToSettings(this); 
         } else if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0])) { 
          // user denied WITHOUT never ask again, this is a good place to explain the user 
          // why you need the permission and ask if he want to accept it (the rationale) 
          dialogReasonStoragePermission(this); 
         } 
        } /*else { 
         // Do on permission granted work here 
        }*/ 
       } 
      } 

      break; 
    } 
} 

public static void dialogReasonStoragePermission(final Activity activity) { 
    AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
    builder.setMessage(activity.getString(R.string.reason_storage_permission)); 
    builder.setCancelable(false); 
    builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      requestStoragePermission(activity); 
     } 
    }); 
    builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      dialog.dismiss(); 
     } 
    }); 

    AlertDialog dialog = builder.create(); 
    dialog.show(); 
} 

public static void dialogReasonStoragePermissionToSettings(final Activity activity) { 
    AlertDialog.Builder builder = new AlertDialog.Builder(activity); 
    builder.setMessage(activity.getString(R.string.reason_storage_permission)); 
    builder.setCancelable(false); 
    builder.setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      goToAppDetailsForPermissionSettings(activity); 
     } 
    }); 
    builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      dialog.dismiss(); 
     } 
    }); 

    AlertDialog dialog = builder.create(); 
    dialog.show(); 
} 

private static final int REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING = 3995; 
private static void goToAppDetailsForPermissionSettings(Activity activity) { 
    Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 
    Uri uri = Uri.fromParts("package", activity.getPackageName(), null); 
    intent.setData(uri); 
    activity.startActivityForResult(intent, REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING); 
} 
2

从Android 6.0(API级别23)开始,用户在应用程序运行时为应用程序授予权限,而不是在安装应用程序时授予应用程序权限。

这就是为什么它的工作原理在-棒棒糖前期版本,并且不会对API的权限23.在Android清单单单是不够的,你需要将它们在运行时添加为好。请参阅here for more details.

+0

感谢您的回答。但将targetSdkVersion更改为22解决了我的问题。这是错的吗? –

+0

是的,没有。你总是可以回归到一个更低的API并且它可以工作,但是它不是更好的做到这一点,所以它使用更新的SDK(API 23)构建,它也可以使用它吗?通过选择较低的目标SDK来忽略问题并不是一个好习惯,最好跟上最新的东西。 :) – Vucko

0

我不是为您提供直接的代码,这一点,但这里是有原因的API级别23引入一个新的许可结构,下面更安全的东西短,但赤身描述,在文档here

开始在Android 6.0(API级别23)中,用户在应用程序运行时向应用程序授予权限,而不是在安装应用程序时授予应用程序权限。此方法简化了应用程序安装过程,因为用户在安装或更新应用程序时无需授予权限。它还使用户可以更好地控制应用程序的功能;例如,用户可以选择给相机应用程序访问相机,但不能访问设备位置。用户可以随时撤销权限,只需转到应用的“设置”屏幕即可。

代码是好的,只需要添加一些东西,那就是运行时权限存储。

阅读this blog了解深处的一切约运行时权限给了我一个清晰的图片,希望它也可以帮助你。

感谢

相关问题