尽管获得许可,但写入外部存储器的权限仍被拒绝

时间:2017-06-09 10:50:29

标签: android android-permissions

我有一个Android 7.0测试设备和我的APK目标=“targetSdkVersion 22”,其中包含:

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

使用:

final File f = new 
File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + File.separator + "DressUpBaby" + photonumber + ".png");
f.createNewFile();

此时我收到警告:

W/System.err: java.io.IOException: Permission denied

如何保存文件?当我在Eclipse上创建它时,这是有效的,但是现在我已经更新并转移到Android Studio,它似乎已经破坏了一些东西。

7 个答案:

答案 0 :(得分:10)

如果您定位到 SDK 29 ,并且在成功请求WRITE_EXTERNAL_STORAGE权限后仍然出现“拒绝权限”错误,则应添加

android:requestLegacyExternalStorage="true"

转到AndroidManifest.xml中的应用程序定义。

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting
       Android 10 or higher. -->
    <application android:requestLegacyExternalStorage="true" ... >
      ...
    </application>
</manifest>

请参阅https://developer.android.com/training/data-storage/compatibility

答案 1 :(得分:8)

如果您在API级别23或更高级别上运行应用程序,则必须在运行时请求权限。

请求权限:

String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions, WRITE_REQUEST_CODE);

然后处理结果:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
       case WRITE_REQUEST_CODE:
         if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
           //Granted.


         }
       else{
           //Denied.
         }
        break;
    }
}

有关详细信息,请访问Requesting Permissions at Run Time - Android Doc

答案 2 :(得分:5)

Android N引入了一种新的权限模型,该模式仅在应用程序真正需要时才会请求权限,而不是像以前那样在安装期间。

使用以下代码询问权限

注意 - 还要在清单文件中添加所需的权限

如果您没有要求主要活动的权限传递对上下文/活动的引用

以下示例显示了要求写入外部存储的权限的示例,可以同时重新安排多个permisisons(谷歌不推荐)。

public class MainActivity extends AppCompatActivity {
/**
 * Variables for requiesting permissions, API 25+
 */
private int requestCode;
private int grantResults[];


/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {if(ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED ){
        //if you dont have required permissions ask for it (only required for API 23+)
        ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);


        onRequestPermissionsResult(requestCode,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},grantResults);
    }

    @Override // android recommended class to handle permissions
    public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
        switch (requestCode) {
            case 1: {

            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                Log.d("permission","granted");
            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.uujm
                Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();

                //app cannot function without this permission for now so close it...
                onDestroy();
            }
            return;
        }

        // other 'case' line to check fosr other
        // permissions this app might request
    }
}

答案 3 :(得分:1)

如果即使授予了权限并且您已经实施了权限检查,您也会得到拒绝权限错误,

确保您未定位到api级别29:

targetSdkVersion compilesdkversion 29 更改为 28 或其他任何较低级别。

答案 4 :(得分:1)

与答案“确保您未针对api级别29 ...”有关,我发现了这一点。

https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory

。。。。。。。。

“ getExternalStoragePublicDirectory”

此方法已在API级别29中弃用。

为了提高用户隐私,不建议直接访问共享/外部存储设备。当应用程序定位到Build.VERSION_CODES.Q时,此方法返回的路径不再可供应用程序直接访问。通过迁移到Context#getExternalFilesDir(String),MediaStore或Intent#ACTION_OPEN_DOCUMENT之类的替代方案,应用程序可以继续访问共享/外部存储中存储的内容。

。。。。。。。。

因此,在这种情况下,您必须用其他方法替换“ getExternalStoragePublicDirectory”。

答案 5 :(得分:0)

这是我在类似情况下所做的:

步骤1:为清单文件添加权限

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

步骤2:创建权限检查功能

void checkForPermissions()
{
    // Here, thisActivity is the current activity
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        // Permission is not granted
        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
            // This part I didn't implement,because for my case it isn't needed
            Log.i(TAG,"Unexpected flow");
        } else {
            // No explanation needed; request the permission
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE);

            // MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE is an
            // app-defined int constant. The callback method gets the
            // result of the request.
        }
    } else {
        // Permission is already granted, call the function that does what you need

        onFileWritePermissionGranted();
    }
}

步骤3:实现onRequestPermissionsResult

 @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted, yay! 
                    // call the function that does what you need
                    onFileWritePermissionGranted();
                } else {
                    Log.e(TAG, "Write permissions has to be granted tp ATMS, otherwise it cannot operate properly.\n Exiting the program...\n");
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request.
        }
    }

第4步:使用权限:)

void onFileWritePermissionGranted()
{
   // Write to some file
}

答案 6 :(得分:0)

在最新版本的android中,请求权限有点不同,例如, 如果您想先访问存储权限 您需要从 Manifest.xml 请求访问权限

喜欢:

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

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

最重要的是不要忘记从 Manifets.xml 的应用程序标签中允许这一点,

`android:requestLegacyExternalStorage="true"'

//并从您的活动中创建方法以请求运行权限 从任何需要的活动中调用此函数。

private boolean requestPermission(){
        boolean request=true;
        String[] permissions={Manifest.permission.CAMERA,
                                Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.READ_EXTERNAL_STORAGE,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.ACCESS_COARSE_LOCATION,
                                Manifest.permission.ACCESS_FINE_LOCATION};
        if (permissions.length!=0){
            ActivityCompat.requestPermissions(this,permissions,102);
            request= true;
        }

        else{
            toastMsg("Permissions Denied");
            println("Permissions not allowed by User...");
            request=false;
        }

        return request;

    }