Получить путь от Ури
Я делаю так, чтобы Пользователь выбирал внутреннее или внешнее хранилище (SD-карту), используя документ Storage Access Framework.
После того, как пользователь выберет каталог, я хочу проверить, относится ли выбранный пользователем каталог к корневой папке определенного хранилища (внутреннего или внешнего хранилища).
Это то, как я пытаюсь достичь этого, и это то, чего я достиг до сих пор.
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == 42) {
Uri treeUri = data.getData();
if (!wrong_directory_selected(treeUri, Context)) {
// Permission granted for the Directory as required by me
} else {
// Permission not granted for the Directory as required by me
}
}
}
}
public boolean wrong_directory_selected(Uri uri, Context con)
{
final File uri_path=new File(FileUtil.getFullPathFromTreeUri(uri,con.getApplicationContext()));
if(uri_path!=null)
{
if(uri_path.getName().toLowerCase().equals(new File(PathForWhichPermissionNeeded).getName().toLowerCase()))
{
return false;
}
}
return true;
}
А это мой FileUtil
учебный класс-
public final class FileUtil {
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);
Log.e("DocumentPath",documentPath);
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;
}
}
private static String getVolumePath(final String volumeId, Context con)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
return null;
}
try {
StorageManager mStorageManager =
(StorageManager) con.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)
{
if (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;
}
}
}
Так в основном onActivityResult
Я проверяю, если treeuri
выбранного пути к каталогу равен или не указан по пути, указанному мной.
Это treeuri
для выбранного каталога content://com.android.externalstorage.documents/tree/primary%3A
Это путь, который возвращается из выше treeuri
/storage/sdcard0
Путь, который ожидается вернуть /storage/sdcard1
,
Таким образом, даже после выбора правильного каталога возвращается неправильный путь.
Может ли кто-нибудь помочь мне найти точный путь treeuri
или может кто-нибудь помочь мне проверить, если treeuri
принадлежит к внутренней памяти или внешней памяти (SD-карта).
2 ответа
Я хочу проверить, находится ли выбранный пользователем каталог в корневой папке определенного хранилища (внутреннего или внешнего хранилища).
Вы можете использовать getParentFile()
на DocumentFile
и посмотрите, что он возвращает для вершины дерева документа. Они не документируют, что именно происходит здесь, но должны либо вернуться null
или бросить какое-то исключение. Затем вы можете использовать это, чтобы определить, является ли возвращенное дерево документа корнем чего-либо.
Однако не требуется, чтобы "что-то" было внешним хранилищем или съемным хранилищем. Пользователь может выбрать дерево документов на Google Диске, файловом сервере Windows или любом другом источнике данных. Не требуется, чтобы вы могли определить, откуда исходит источник данных.
И это мой класс FileUtil
Большая часть кода в этом классе делает неверные предположения. Остальные используют рефлексию, и вполне возможно, что в следующей версии Android будет запрещен доступ к скрытым API с помощью рефлексии.
Может ли кто-нибудь помочь мне найти точный путь Treeuri
Там нет "точного пути Treeuri".
Может ли кто-нибудь помочь мне проверить, принадлежит ли treeuri к внутренней памяти или внешней памяти (SD-карта)
Это невозможно вообще.
Я хочу проверить, находится ли выбранный пользователем каталог в корневой папке определенного хранилища
Это очень просто. Если схема контента заканчивается %3A
чем это.
Так проверь data.getData().toString()
для этого.