简书链接:anroid存储权限的最佳适配针对android11也就是api29问题解决EPERMoperationnotpermitted
文章字数:540,阅读全文大约需要2分钟
昨天本来想写一个demo,然后放到手机上用神之手hook,然后用我的hookui测试批量修改集合内模型数据,没想到这么简单的问题都搞不定了。。

权限申请了,清单文件也定义了,也手动进入设置给了存储权限,然后今天动态调用了权限申请了,
还是提示EPERM operation not permitted
网络上说的的在application节点

1
2

进入清单文件选择
1
2
3
4
5
6


*WRITE_EXTERNAL_STORAGE no longer provides write access when targeting Android 11+, even when using requestLegacyExternalStorage*
于是根据这个关键词搜索才找到解决方案,

解决方法如下:
/> <application android:requestLegacyExternalStorage="true"
1
2

java层对于android 11的代码

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && false == Environment.isExternalStorageManager()) {
Uri uri = Uri.parse(“package:” + BuildConfig.APPLICATION_ID);
startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri));
}else{
callPermissionLogic(this, 0);
}

1
2

我写的完整代码,不用任何框架
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && false == Environment.isExternalStorageManager()) {
        Uri uri = Uri.parse("package:" + BuildConfig.APPLICATION_ID);
        startActivity(new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, uri));
    }else{
    callPermissionLogic(this, 0);
    }

}

private static final int REQUEST_CODE_SELECT_PLUGIN = 1;
private boolean mChanage;


private int _CurrentPermissionIndex;

List<String> waitRequestPermissionList = new ArrayList<>();

{
    waitRequestPermissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);

    waitRequestPermissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}

private int callPermissionLogic(Activity activity, final int from) {
    int breakFlag = -1;
    for (int i = from; i < waitRequestPermissionList.size(); i++) {
        final String currentPermission = waitRequestPermissionList.get(i);
        _CurrentPermissionIndex = i;
        final int finalI = i;
        if (PermissionUtil.checkSelfPermission(this, currentPermission) != PackageManager.PERMISSION_GRANTED) {
            breakFlag = i;
            if (PermissionUtil.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {


                Log.w("PermissionRequest", "shouldShowRequestPermissionRationale call");
                Toast.makeText(activity, "权限被拒绝" + currentPermission + ",你可以再次申请", Toast.LENGTH_SHORT).show();


                callPermissionLogic(activity, from + 1);

            } else {
                PermissionUtil.requestPermissions(this, new String[]{currentPermission}, i);
                if (BuildConfig.DEBUG) {

                    Log.w("PermissionRequest", "第一次或者最后一次权限申请 " + currentPermission);
                }

            }
        } else {
            if (BuildConfig.DEBUG) {
                Log.w("PermissionRequest", "权限" + currentPermission + "已拥有...");

            }
        }

    }
    return breakFlag;
}


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

//onRequestPermissionsResult requestCode:1,permission:[android.permission.FOREGROUND_SERVICE],grantResult:[-1]
if (BuildConfig.DEBUG) {
Log.w(“PermissionRequest”, “onRequestPermissionsResult requestCode:” + requestCode + “,permission:” + Arrays.toString(permissions) + “,grantResult:” + Arrays.toString(grantResults));
}
_CurrentPermissionIndex++;
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && permissions[0].equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

    } else {


    }

    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
1
在上面代码可以找到如下行

Toast.makeText(activity, “权限被拒绝” + currentPermission + “,你可以再次申请”, Toast.LENGTH_SHORT).show();

1
2

可以替换成下面的再次调用

Log.w(“PermissionRequest”, “shouldShowRequestPermissionRationale call”);
DialogUtils.showConfirmDialog(this, “年轻人,权限不用轻易拒绝啊,再给你一次机会,我需要申请” + currentPermission + “权限,这个权限有利于机器人程序得问题哈!”, new INotify() {
@Override
public void onNotify(Void param) {
PermissionUtil.requestPermissions(activity, new String[]{currentPermission}, finalI);
}
}, new INotify() {
@Override
public void onNotify(Void param) {
callPermissionLogic(activity,from + 1);
}
});

1
2
3
4
5


关于android11的问题看看大神们怎么讨论的。

https://stackoverflow.com/questions/64221188/write-external-storage-when-targeting-android-10

package cn.qssq666.robot.utils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.annotation.NonNull;
import android.util.Log;
import android.view.WindowManager;

import java.util.Arrays;

/**

*/
public class PermissionUtil {

private static final String TAG = "PermissionUtil";
public static boolean debug=true;

public static void onRequestPermissionsResult(Activity activity, int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {




    Log.w(TAG, "onRequestPermissionsResult:" + " requestCode ,result:" + getPermissionsResultMsg(permissions, grantResults)+",grantResultslength:"+grantResults.length);


}

private static String getPermissionsResultMsg(String[] permissions, int[] grantResults) {


    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < permissions.length; i++) {


        stringBuilder.append(printPermission(permissions[i]) + ":" + getResultMsg(grantResults[i]) + "\n");
    }


    return stringBuilder.toString();
}

public static void requestPermissions(Activity activity, String[] permissions, int requestCode) {


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        activity.requestPermissions(permissions,requestCode);
    Log.w(TAG, "requestPermissions:" + printPermissions(permissions) + " requestCode" + requestCode);
    }else{

    }

}

public static int checkSelfPermission(Context activity, String permission) {
    if(debug){
        Log.w(TAG,"=========================================");
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        int i = activity.checkSelfPermission(permission);

        if (debug) {
            Log.w(TAG, "checkSelfPermission:" + printPermission(permission) + ":" + getResultMsg(i));
        }

        return i;
    }
    if (debug) {
        Log.w(TAG, "Build.VERSION.SDK_INT <23 checkSelfPermission:" + printPermission(permission) + ":" + getResultMsg(PackageManager.PERMISSION_GRANTED));


    }
    return PackageManager.PERMISSION_GRANTED;
}

public static String printPermission(String permission) {
    return permission;

}

public static String printPermissions(String[] permission) {
    return Arrays.toString(permission);

}

/*
是否应该显示 请求权限信息
 */
public static boolean shouldShowRequestPermissionRationale(Activity activity, String permissionRationale) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        boolean result = activity.shouldShowRequestPermissionRationale(permissionRationale);
        if (debug) {
            Log.w(TAG, "shouldShowRequestPermissionRationale:" + printPermission(permissionRationale) + " result" + getRationaleResultMsg(result));
        }
    } else {
            Log.w(TAG, "shouldShowRequestPermissionRationale <23 false" );

    }

    return false;
}

private static String getRationaleResultMsg(boolean result) {
    return result ? "应该显示权限说明" : "不应该显示权限说明";
}

public static String getResultMsg(int permissionCode) {
    if (permissionCode == PackageManager.PERMISSION_GRANTED) {
        return "获得/成功";
    } else {
        return "未获得/拒绝";

    }
}

public static void showSystemDialog(Activity mainActivity) {

    if(debug){
        Log.w(TAG,"弹出系统对话框开始");
        AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);

        builder.setMessage("我是系统对话框");
        Dialog dialog= builder.create();
        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);

// dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

        dialog.show();
        Log.w(TAG,"弹出系统对话框结束");
    }
}

}