Android写入外置sd卡
参照https://blog.csdn.net/qq_36467463/article/details/88691726 自己整理了下
1. 获取外置sd卡根目录
sd卡根目录是类似/storage/0000-0000 这样的路径,
而用runtime.exec("mount"), 或者是用StorageManager.getStorageVolumes()再用反射path获取的路径是/mnt/media_rw/0000-0000 不可用,需要用下面的方式获取:
public String getExternalDir(Context context) {String root = null;File[] dirs = context.getExternalFilesDirs(null);for (File f : dirs) {String path = f.getAbsolutePath();if (!path.contains(Environment.getExternalStorageDirectory().getAbsolutePath())) {int index = path.indexOf("/Android/data");if (index != -1) {root = path.substring(0, index);break;}}}return root;}
2. 外置sd卡写入权限检查
外置sd卡用File.canWrite()检查返回均为false,因此无法用来检查是否可写。
可用
boolean hasPermission = false;String uriStr = EdoPreference.getExternalUri();//fetch value in sharedpreferencesif (uriStr != null) {DocumentFile documentFile = DocumentFile.fromTreeUri(context, Uri.parse(uriStr));if (documentFile != null) {hasPermission = documentFile.canWrite();}}
3. 申请外置sd卡写入权限
如果>=7.0, 需要用StorageVolume.createAccessIntent()来创建intent,否则intent需设置action: Intent.ACTION_OPEN_DOCUMENT_TREE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {StorageManager storageManager = EmailApplication.getContext().getSystemService(StorageManager.class);StorageVolume volume = storageManager.getStorageVolume(new File(externalDir));if (volume != null) {Intent accessIntent = volume.createAccessIntent(null);if (accessIntent != null) {extFragment.startActivityForResult(accessIntent, ExtSdFragment.REQ_CODE_EXT);}}} else {Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);extFragment.startActivityForResult(intent, ExtSdFragment.REQ_CODE_EXT);}
其中externalDir是sd卡的任意路径, 在onActivityResult回调中保存Uri的string,以备后用
4. 写入外置sd卡
直接用FileOutputStream写入外置sd卡会失败,原因是对应file的canWrite()返回false, 用户授权后仍然是false(这里太坑了!!!),需要用DocumentFile获取Uri,然后用Uri打开OutputStream:
DocumentFile file = getExtDocumentFile(to.substring(externalDir.length() + 1));if (file == null) {return false;}try (FileInputStream is = new FileInputStream(from); OutputStream os = EmailApplication.getContext().getContentResolver().openOutputStream(file.getUri())) {byte[] b = new byte[is.available()];is.read(b);os.write(b);return true;} catch (IOException e) {e.printStackTrace();return false;}
根据文件路径获取DocumentFile,需要一层层去找
private DocumentFile getExtDocumentFile(String path,Context context) {String extSDUri = EdoPreference.getExternalUri();//获取保存的Uri stringif (extSDUri == null) {return null;}DocumentFile file = DocumentFile.fromTreeUri(context, Uri.parse(extSDUri));if (file == null) {return null;}if (path.contains("/")) {String[] split = path.split("/");for (int i = 0; i < split.length; i++) {DocumentFile df = file.findFile(split[i]);if (df == null) {if (i == split.length - 1) {df = file.createFile("*/*", split[i]);} else {df = file.createDirectory(split[i]);}}file = df;}} else {file = file.createFile("*/*", path);}return file;}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
