Android所有版本的存储权限适配

第一步:在Manifest文件添加如下权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" tools:ignore="ScopedStorage"/>

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

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

android:requestLegacyExternalStorage="true"

第二步:定义以下常量

private static final int REQUEST_CODE_FOR_READ_MEDIA_IMAGES_PERMISSION_FROM_ANDROID_13 = 0x00000003;

private static final int REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12 = 0x00000005;

private static final int REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_ANDROID_6_TO_ANDROID_9 = 0x00000006;

第三步:在需要写入文件的地方编写以下代码

java.io.OutputStream outputStream = null;

java.lang.String errorMessage = "";

java.lang.String fileName = "test_导出资料_" + java.lang.System.currentTimeMillis() + ".xls";

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

android.util.Log.d("debug", "设备系统的版本号是大于等于安卓6.0以上的版本,需要检查运行时的危险权限");

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {

android.util.Log.d("debug", "设备系统的版本号是大于等于安卓10.0以上的版本,说明是只能用媒介存储写入文件和读取文件");

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {

android.util.Log.d("debug", "设备系统的版本号是大于等于安卓13.0以上的版本,换成检查Media声音和Media视频和Media图片的权限");

int checkSelfPermissionResultForReadMediaImages = checkSelfPermission(android.Manifest.permission.READ_MEDIA_IMAGES);

android.util.Log.d("debug", "checkSelfPermissionResultForReadMediaImages->" + checkSelfPermissionResultForReadMediaImages);

if (checkSelfPermissionResultForReadMediaImages == android.content.pm.PackageManager.PERMISSION_GRANTED) {

android.util.Log.d("debug", "已经授予媒介图片的读取权限");

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

} else {

errorMessage = "需要授予权限";

android.util.Log.d("debug", "没有授予媒介图片的读取权限");

android.util.Log.d("debug", "现在执行请求读取媒介图片的权限");

java.lang.String[] permission = new java.lang.String[1];

permission[0] = android.Manifest.permission.READ_MEDIA_IMAGES;

requestPermissions(permission, REQUEST_CODE_FOR_READ_MEDIA_IMAGES_PERMISSION_FROM_ANDROID_13);

}

int checkSelfPermissionResultForReadExternalStorage = checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE);

int checkSelfPermissionResultForWriteExternalStorage = checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

android.util.Log.d("debug", "检测完读取媒介图片权限之后再检测外部存储读取权限看看->" + checkSelfPermissionResultForReadExternalStorage);

android.util.Log.d("debug", "检测完读取媒介图片权限之后再检测外部存储写入权限看看->" + checkSelfPermissionResultForWriteExternalStorage);

} else {

android.util.Log.d("debug", "设备系统的版本号时介于10.0到12.0之间的,通过android.provider.MediaStore获取外部存储目录");

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {

android.util.Log.d("debug", "安卓11或者安卓12通过Environment的isExternalStorageManager方法检查是否有权限");

if (android.os.Environment.isExternalStorageManager()) {

android.util.Log.d("debug", "在安卓11或者安卓12中有读写文件的权限");

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

} else {

errorMessage = "需要授予权限";

android.util.Log.d("debug", "安卓11或者安卓12的逻辑请求权限");

try {

Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);

intent.addCategory("android.intent.category.DEFAULT");

intent.setData(android.net.Uri.parse(String.format("package:%s",getApplicationContext().getPackageName())));

startActivityForResult(intent, REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12);

} catch (Exception e) {

e.printStackTrace();

Intent intent = new Intent();

intent.setAction(android.provider.Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);

startActivityForResult(intent, REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12);

}

}

} else {

android.util.Log.d("debug", "在安卓10版本中沿用之前的检查方法");

int checkSelfPermissionResultForReadExternalStorage = androidx.core.app.ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);

//int checkSelfPermissionResultForWriteExternalStorage = androidx.core.app.ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

android.util.Log.d("debug", "checkSelfPermissionResultForReadExternalStorage->" + checkSelfPermissionResultForReadExternalStorage);

//android.util.Log.d("debug", "checkSelfPermissionResultForWriteExternalStorage->" + checkSelfPermissionResultForWriteExternalStorage);

//boolean isHavePermission = checkSelfPermissionResultForReadExternalStorage == android.content.pm.PackageManager.PERMISSION_GRANTED && checkSelfPermissionResultForWriteExternalStorage == android.content.pm.PackageManager.PERMISSION_GRANTED;

if (checkSelfPermissionResultForReadExternalStorage == android.content.pm.PackageManager.PERMISSION_GRANTED) {

android.util.Log.d("debug", "已经授予外部存储写入权限");

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

} else {

errorMessage = "需要授予权限";

android.util.Log.d("debug", "没有授予外部存储写入权限");

android.util.Log.d("debug", "现在执行请求外部存储写入的权限");

android.util.Log.d("debug", "安卓10的逻辑请求权限");

java.lang.String[] permission = new java.lang.String[2];

permission[0] = android.Manifest.permission.READ_EXTERNAL_STORAGE;

permission[1] = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

requestPermissions(permission, REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12);

}

}

}

} else {

android.util.Log.d("debug", "设备系统的版本号是介于6.0到9.0之间,仍然是可以从Environment类的getExternalStorageDirectory方法获取外部存储目录的,但是前提是要检查运行时权限");

int checkSelfPermissionResultForWriteExternalStorage = checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

if (checkSelfPermissionResultForWriteExternalStorage == android.content.pm.PackageManager.PERMISSION_GRANTED) {

java.io.File externalStorageDirectory = android.os.Environment.getExternalStorageDirectory();

android.util.Log.d("debug", "安卓系统是在6.0到9.0之间的,通过Environment类获取到外部存储目录->" + externalStorageDirectory.getPath());

try {

outputStream = new java.io.FileOutputStream(externalStorageDirectory.getPath() + java.io.File.separator + fileName);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

} else {

errorMessage = "需要授予权限";

java.lang.String[] permission = new java.lang.String[1];

permission[0] = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

requestPermissions(permission, REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_ANDROID_6_TO_ANDROID_9);

}

}

} else {

android.util.Log.d("debug", "设备系统的版本号小于6.0以下的版本,不需要检查运行时权限");

java.io.File externalStorageDirectory = android.os.Environment.getExternalStorageDirectory();

android.util.Log.d("debug", "直接通过Environment类的getExternalStorageDirectory()即可获取外部存储目录->" + externalStorageDirectory.getPath());

try {

outputStream = new java.io.FileOutputStream(externalStorageDirectory.getPath() + java.io.File.separator + fileName);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

}

if (outputStream != null) {

//file write

} else {

android.widget.Toast.makeText(this, errorMessage, android.widget.Toast.LENGTH_LONG).show();

}

第四步:权限请求回调函数

@Override

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

if (requestCode == REQUEST_CODE_FOR_READ_MEDIA_IMAGES_PERMISSION_FROM_ANDROID_13) {

if (grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED) {

if (permissions.length > 0) {

android.util.Log.d("debug", "打印授予的权限->" + permissions[0]);

}

java.lang.String fileName = "buyup_导出资料_" + java.lang.System.currentTimeMillis() + ".xls";

java.lang.String errorMessage = "";

java.io.OutputStream outputStream = null;

android.util.Log.d("debug", "设备系统的版本号是大于等于安卓10.0以上的版本,说明是只能用媒介存储写入文件和读取文件");

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

if (outputStream != null) {

//file write

} else {

android.widget.Toast.makeText(this, errorMessage, android.widget.Toast.LENGTH_LONG).show();

}

} else {

if (permissions.length > 0) {

java.lang.String permission0 = permissions[0];

android.util.Log.d("debug", "打印请求的权限->" + permission0);

}

android.util.Log.d("debug", "权限授予失败");

android.widget.Toast.makeText(this, "权限授予失败", android.widget.Toast.LENGTH_LONG).show();

}

} else if (requestCode == REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FOR_ANDROID_6_TO_ANDROID_9) {

if (grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED) {

if (permissions.length > 0) {

android.util.Log.d("debug", "来自安卓6.0到安卓9.9之间的请求权限,打印授予的权限->" + permissions[0]);

}

java.lang.String fileName = "buyup_导出资料_" + java.lang.System.currentTimeMillis() + ".xls";

java.lang.String errorMessage = "";

java.io.OutputStream outputStream = null;

android.util.Log.d("debug", "设备系统的版本号是大于等于安卓6.0到安卓9.0之间的,通过用android.os.Environment类获取外部存储");

java.io.File externalStorageDirectory = android.os.Environment.getExternalStorageDirectory();

try {

outputStream = new java.io.FileOutputStream(externalStorageDirectory.getPath() + java.io.File.separator + fileName);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

if (outputStream != null) {

//file write

} else {

android.widget.Toast.makeText(this, errorMessage, android.widget.Toast.LENGTH_LONG).show();

}

} else {

if (permissions.length > 0) {

android.util.Log.d("debug", "来自安卓6.0到安卓9.9之间的请求权限,打印拒绝的权限->" + permissions[0]);

}

android.util.Log.d("debug", "来自安卓6.0到安卓9.9之间的请求权限,权限授予失败");

android.widget.Toast.makeText(this, "权限授予失败", android.widget.Toast.LENGTH_LONG).show();

}

} else if (requestCode == REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12) {

if (grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED) {

if (permissions.length > 0) {

android.util.Log.d("debug", "来自安卓10.0的版本,打印授予的权限->" + permissions[0]);

android.util.Log.d("debug", "来自安卓10.0的版本,打印授予的权限->" + permissions[1]);

}

java.lang.String fileName = "buyup_导出资料_" + java.lang.System.currentTimeMillis() + ".xls";

java.lang.String errorMessage = "";

java.io.OutputStream outputStream = null;

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

if (outputStream != null) {

//file write

} else {

android.widget.Toast.makeText(this, errorMessage, android.widget.Toast.LENGTH_LONG).show();

}

} else {

if (permissions.length > 0) {

android.util.Log.d("debug", "来自安卓10.0的版本,打印拒绝的权限->" + permissions[0]);

android.util.Log.d("debug", "来自安卓10.0的版本,打印拒绝的权限->" + permissions[1]);

}

android.widget.Toast.makeText(this, "权限授予失败", android.widget.Toast.LENGTH_LONG).show();

}

}

}

第五步:针对安卓11或者安卓12版本的请求权限方法

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (requestCode == REQUEST_CODE_FOR_WRITE_EXTERNAL_STORAGE_PERMISSION_FROM_ANDROID_10_TO_ANDROID_12) {

android.util.Log.d("debug", "在安卓11或者安卓12系统中引导到系统设置界面开启权限回来");

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {

if (android.os.Environment.isExternalStorageManager()) {

android.util.Log.d("debug", "已经授予外部存储写入权限");

java.io.OutputStream outputStream = null;

java.lang.String errorMessage = "";

java.lang.String fileName = "buyup_导出资料_" + java.lang.System.currentTimeMillis() + ".xls";

android.util.Log.d("debug", "设备系统的版本号时介于10.0到12.0之间的,通过android.provider.MediaStore获取外部存储目录");

android.net.Uri uri = android.provider.MediaStore.Files.getContentUri("external");

android.content.ContentValues contentValues = new android.content.ContentValues();

contentValues.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, fileName);

contentValues.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, "application/x-xls");

android.content.ContentResolver contentResolver = getContentResolver();

android.net.Uri uriForInsertResult = contentResolver.insert(uri, contentValues);

try {

outputStream = contentResolver.openOutputStream(uriForInsertResult);

} catch (java.io.IOException ioException) {

ioException.printStackTrace();

errorMessage = ioException.getMessage();

}

if (outputStream != null) {

//file write

} else {

android.widget.Toast.makeText(this, errorMessage, android.widget.Toast.LENGTH_LONG).show();

}

} else {

android.widget.Toast.makeText(this, "需要授予权限才能导出文件!", android.widget.Toast.LENGTH_SHORT).show();

}

}

}

}

相关推荐
清水白石0087 分钟前
《从零到进阶:Pydantic v1 与 v2 的核心差异与零成本校验实现原理》
数据库·python
leo__5209 分钟前
基于菲涅耳衍射积分的空心高斯光束传输数值模拟(MATLAB实现)
开发语言·matlab
昵称已被吞噬~‘(*@﹏@*)’~10 分钟前
【RL+空战】学习记录03:基于JSBSim构造简易空空导弹模型,并结合python接口调用测试
开发语言·人工智能·python·学习·深度强化学习·jsbsim·空战
短剑重铸之日19 分钟前
《SpringBoot4.0初识》第一篇:前瞻与思想
java·开发语言·后端·spring·springboot4.0
2501_9418779826 分钟前
从配置热更新到运行时自适应的互联网工程语法演进与多语言实践随笔分享
开发语言·前端·python
lsx20240630 分钟前
Python 运算符详解
开发语言
酩酊仙人34 分钟前
fastmcp构建mcp server和client
python·ai·mcp
程序炼丹师1 小时前
CMakeLists中 get_filename_component详解
开发语言
꧁Q༒ོγ꧂1 小时前
C++ 入门完全指南(四)--函数与模块化编程
开发语言·c++
且去填词1 小时前
DeepSeek API 深度解析:从流式输出、Function Calling 到构建拥有“手脚”的 AI 应用
人工智能·python·语言模型·llm·agent·deepseek