好吧,我进行了搜索和搜索,没有人有我的确切答案,或者我错过了.我让我的用户通过以下方式选择目录:
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); startActivityForResult(intent,READ_REQUEST_CODE);
在我的活动中,我想捕捉实际路径,这似乎是不可能的.
protected void onActivityResult(int requestCode,int resultCode,Intent intent){
super.onActivityResult(requestCode,resultCode,intent);
if (resultCode == RESULT_OK) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
//Marshmallow
} else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
//Set directory as default in preferences
Uri treeUri = intent.getData();
//grant write permissions
getContentResolver().takePersistableuriPermission(treeUri,Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
//File myFile = new File(uri.getPath());
DocumentFile pickedDir = DocumentFile.fromTreeUri(this,treeUri);
我选择的文件夹位于:
Device storage/test/
我已经尝试了以下所有方法来获得确切的路径名称,但无济于事.
File myFile = new File (uri.getPath()); //returns: /tree/1AF6-3708:test treeUri.getPath(); //returns: /tree/1AF6-3708:test/ pickedDir.getName() //returns: test pickedDir.getParentFile() //returns: null
基本上我需要将/ tree / 1AF6-3708:转换为/ storage / emulated / 0 /或者每个设备调用它的存储位置.所有其他可用选项返回/ tree / 1AF6-37u08:也.
我想这样做有两个原因.
1)在我的应用程序中,我将文件位置存储为共享首选项,因为它是特定于用户的.我有相当多的数据将被下载和存储,我希望用户能够将它放在他们想要的地方,特别是如果他们有一个额外的存储位置.我确实设置了默认值,但我想要多功能性,而不是专用位置:
Device storage/Android/data/com.app.name/
2)在5.0中我想让用户获得该文件夹的读/写权限,这似乎是唯一的方法.如果我可以从解决此问题的字符串获得读/写权限.
我能找到的所有解决方案都与Mediastore有关,这对我没有帮助.我必须在某处丢失某些东西,否则我必须对它进行釉面处理.任何帮助,将不胜感激.谢谢.
解决方法
这将为您提供所选文件夹的实际路径(假设所选文件夹位于外部存储或外部SD卡中)
Uri treeUri = data.getData(); String path = FileUtil.getFullPathFromTreeUri(treeUri,this);
其中FileUtil是以下类
public final class FileUtil {
static String TAG="TAG";
private static final String PRIMARY_VOLUME_NAME = "primary";
@Nullable
public static String getFullPathFromTreeUri(@Nullable final Uri treeUri,Context con) {
if (treeUri == null) return null;
String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri),con);
if (volumePath == null) return File.separator;
if (volumePath.endsWith(File.separator))
volumePath = volumePath.substring(0,volumePath.length() - 1);
String documentPath = getDocumentPathFromTreeUri(treeUri);
if (documentPath.endsWith(File.separator))
documentPath = documentPath.substring(0,documentPath.length() - 1);
if (documentPath.length() > 0) {
if (documentPath.startsWith(File.separator))
return volumePath + documentPath;
else
return volumePath + File.separator + documentPath;
}
else return volumePath;
}
@SuppressLint("ObsoleteSdkInt")
private static String getVolumePath(final String volumeId,Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return null;
try {
StorageManager mStorageManager =
(StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getmethod("getVolumeList");
Method getUuid = storageVolumeClazz.getmethod("getUuid");
Method getPath = storageVolumeClazz.getmethod("getPath");
Method isPrimary = storageVolumeClazz.getmethod("isPrimary");
Object result = getVolumeList.invoke(mStorageManager);
final int length = Array.getLength(result);
for (int i = 0; i < length; i++) {
Object storageVolumeElement = Array.get(result,i);
String uuid = (String) getUuid.invoke(storageVolumeElement);
Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement);
// primary volume?
if (primary && PRIMARY_VOLUME_NAME.equals(volumeId))
return (String) getPath.invoke(storageVolumeElement);
// other volumes?
if (uuid != null && uuid.equals(volumeId))
return (String) getPath.invoke(storageVolumeElement);
}
// not found.
return null;
} catch (Exception ex) {
return null;
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getVolumeIdFromTreeUri(final Uri treeUri) {
final String docId = DocumentsContract.getTreeDocumentId(treeUri);
final String[] split = docId.split(":");
if (split.length > 0) return split[0];
else return null;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getDocumentPathFromTreeUri(final Uri treeUri) {
final String docId = DocumentsContract.getTreeDocumentId(treeUri);
final String[] split = docId.split(":");
if ((split.length >= 2) && (split[1] != null)) return split[1];
else return File.separator;
}
}