Как получить реальный путь из Uri в Android 11

#java #android #android-studio #kotlin

#java #Android #android-studio #kotlin

Вопрос:

Как получить реальный путь из URI в Android 10 и Android 11. Получение Uri из данных намерения, т.е.

  private val startForResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult ->
            if (result.resultCode == Activity.RESULT_OK) {
                val uri = result.data?.data
              
            }
        }
  

и намерение получить файл pdf

  val mimeType = "application/pdf"
            val intent = Intent(Intent.ACTION_GET_CONTENT)
            intent.type = mimeType
            intent.addCategory(Intent.CATEGORY_OPENABLE)
 if (packageManager.resolveActivity(sIntent, 0) != null) {
            // it is device with Samsung file manager
            chooserIntent = Intent.createChooser(sIntent, "Select an PDF File")
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(intent))
        } else {
            chooserIntent = Intent.createChooser(intent, "Select an PDF File")
        }
        try {
            chooserIntent.resolveActivity(packageManager)?.let {
                //  startActivityForResult(Intent.createChooser(this,"Pick MHT file"),1)
                startForResult.launch(chooserIntent)
            }
        } catch (ex: ActivityNotFoundException) {
            Toast.makeText(
                applicationContext,
                "No suitable File Manager was found.",
                Toast.LENGTH_SHORT
            ).show()
        }
  

Комментарии:

1. С какой проблемой вы столкнулись?

2. Я не могу открыть PDF-файл в приложении из-за uri, получая uri, подобный этому содержимому://com.android.providers.downloads.documents/document/16, и когда я пытаюсь получить реальный путь, получаю путь, подобный этому /document/16

3. Вы пробовали использовать более низкую версию Android, такую как Android 8 или 9? Работает ли он в более низкой версии Android?

4. да, на уровне ниже 8 он работает нормально, но на Android 10 и Android 11 (уровень api 29 и 30) он не работает, на версии 8 и ниже 8 получение реального пути из URI с использованием этого кода gist.github.com/MeNiks/947b471b762f3b26178ef165a7f5558a и он работает нормально до версии 8, но он не работает на Android 10и Android 11

5. Не пытайтесь получить «реальный» путь из этого хорошего uri. То, что вы получили, тоже не является реальным путем, как вы видели. Используйте полученный uri непосредственно для открытия файла. Далее неясно, что вы пытаетесь сделать, если хотите открыть файл.

Ответ №1:

Мы не можем получить _data в ContentResolver.запрос (uri, …), поэтому нам нужно найти другой способ.

Это мой код, основанный на таблице MediaStore.Файлы:

Будьте осторожны, чтобы добавить

android.разрешение.MANAGE_EXTERNAL_STORAGE

     public static String Uri2Path(Context context, Uri uri) {
        if (uri == null) {
            return null;
        }

        if(ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
            return uri.getPath();
        }
        else if(ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            String authority = uri.getAuthority();

            if(authority.startsWith("com.android.externalstorage")) {
                return Environment.getExternalStorageDirectory()   "/"   uri.getPath().split(":")[1];
            }
            else {
                String idStr = "";
                if(authority.equals("media")) {
                    idStr = uri.toString().substring(uri.toString().lastIndexOf('/')   1);
                }
                else if(authority.startsWith("com.android.providers")) {
                    idStr = DocumentsContract.getDocumentId(uri).split(":")[1];
                }

                ContentResolver contentResolver = context.getContentResolver();
                Cursor cursor = contentResolver.query(MediaStore.Files.getContentUri("external"),
                        new String[] {MediaStore.Files.FileColumns.DATA},
                        "_id=?",
                        new String[]{idStr}, null);
                if (cursor != null) {
                    cursor.moveToFirst();
                    try {
                        int idx = cursor.getColumnIndex(MediaStore.Files.FileColumns.DATA);

                        return cursor.getString(idx);
                    } catch (Exception e) {
                    } finally {
                        cursor.close();
                    }
                }
            }
        }
        return null;
    }
  

Вы можете заменить таблицу в соответствии с вашими потребностями :

 MediaStore.Files.getContentUri("external")
MediaStore.Files.getContentUri("internal")
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
MediaStore.Video.Media.INTERNAL_CONTENT_URI
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
MediaStore.Images.Media.INTERNAL_CONTENT_URI
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
MediaStore.Audio.Media.INTERNAL_CONTENT_URI
MediaStore.Downloads.Media.EXTERNAL_CONTENT_URI
MediaStore.Downloads.Media.INTERNAL_CONTENT_URI
  

Ответ №2:

Вы можете сделать это, чтобы получить данные:

val inputStream = context.contentResolver.openInputStream(uri)

но я не уверен, что вы можете получить полезный путь к файлу из uri.