胡说叔叔
在下面链接的我的Android项目中,您可以找到允许在Android 5中的ExtSDCard上编写的工作代码。它假设用户可以访问整个SD卡,然后允许您在这张卡上随时随地写东西。(如果您只想访问单个文件,事情就会变得更容易。)主代码片段触发存储访问框架:@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void triggerStorageAccessFramework() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_STORAGE_ACCESS);}处理来自存储访问框架的响应:@TargetApi(Build.VERSION_CODES.LOLLIPOP)@Overridepublic final void onActivityResult(final int requestCode,
final int resultCode, final Intent resultData) {
if (requestCode == SettingsFragment.REQUEST_CODE_STORAGE_ACCESS) {
Uri treeUri = null;
if (resultCode == Activity.RESULT_OK) {
// Get Uri from Storage Access Framework.
treeUri = resultData.getData();
// Persist URI in shared preference so that you can use it later.
// Use your own framework here instead of PreferenceUtil.
PreferenceUtil.setSharedPreferenceUri(R.string.key_internal_uri_extsdcard, treeUri);
// Persist access permissions.
final int takeFlags = resultData.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getActivity().getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
}
}}通过存储访问框架获取文件的输出流(使用存储的URL,假设这是外部SD卡根文件夹的URL)DocumentFile targetDocument = getDocumentFile(file, false);OutputStream outStream = Application.getAppContext().
getContentResolver().openOutputStream(targetDocument.getUri());它使用以下帮助方法:public static DocumentFile getDocumentFile(final File file, final boolean isDirectory) {
String baseFolder = getExtSdCardFolder(file);
if (baseFolder == null) {
return null;
}
String relativePath = null;
try {
String fullPath = file.getCanonicalPath();
relativePath = fullPath.substring(baseFolder.length() + 1);
}
catch (IOException e) {
return null;
}
Uri treeUri = PreferenceUtil.getSharedPreferenceUri(R.string.key_internal_uri_extsdcard);
if (treeUri == null) {
return null;
}
// start with root of SD card and then parse through document tree.
DocumentFile document = DocumentFile.fromTreeUri(Application.getAppContext(), treeUri);
String[] parts = relativePath.split("\\/");
for (int i = 0; i
DocumentFile nextDocument = document.findFile(parts[i]);
if (nextDocument == null) {
if ((i
nextDocument = document.createDirectory(parts[i]);
}
else {
nextDocument = document.createFile("image", parts[i]);
}
}
document = nextDocument;
}
return document;}public static String getExtSdCardFolder(final File file) {
String[] extSdPaths = getExtSdCardPaths();
try {
for (int i = 0; i
if (file.getCanonicalPath().startsWith(extSdPaths[i])) {
return extSdPaths[i];
}
}
}
catch (IOException e) {
return null;
}
return null;}/**
* Get a list of external SD card paths. (Kitkat or higher.)
*
* @return A list of external SD card paths.
*/@TargetApi(Build.VERSION_CODES.KITKAT)private static String[] getExtSdCardPaths() {
List paths = new ArrayList<>();
for (File file : Application.getAppContext().getExternalFilesDirs("external")) {
if (file != null && !file.equals(Application.getAppContext().getExternalFilesDir("external"))) {
int index = file.getAbsolutePath().lastIndexOf("/Android/data");
if (index
Log.w(Application.TAG, "Unexpected external file dir: " + file.getAbsolutePath());
}
else {
String path = file.getAbsolutePath().substring(0, index);
try {
path = new File(path).getCanonicalPath();
}
catch (IOException e) {
// Keep non-canonical path.
}
paths.add(path);
}
}
}
return paths.toArray(new String[paths.size()]);}
/**
* Retrieve the application context.
*
* @return The (statically stored) application context
*/public static Context getAppContext() {
return Application.mApplication.getApplicationContext();}引用完整代码https:/github.com/jeisfeld/Augensis/blob/master/AugenDiagseIdea/augenDiagseLib/src/main/java/de/jeisfeld/augenDiagselib/片段/SettingsFragment.java#L 521和https:/github.com/jeisfeld/Augensis/blob/master/AugenDiagseIdea/augenDiagseLib/src/main/java/de/jeisfeld/augenDiagselib/util/Imagefile/FileUtil.java