Obter conteúdo uri do caminho do arquivo no android

271

Eu sei o caminho absoluto de uma imagem (por exemplo, /sdcard/cats.jpg). Existe alguma maneira de obter a interface do usuário para este arquivo?

Na verdade, no meu código, faço o download de uma imagem e a salvo em um local específico. Para definir a imagem em uma instância do ImageView, atualmente abro o arquivo usando o caminho, obtenho os bytes e crie um bitmap e, em seguida, defina o bitmap na instância do ImageView. Este é um processo muito lento. Se eu pudesse obter o conteúdo da interface do usuário, poderia usar o método com muita facilidade. imageView.setImageUri(uri)

pankajagarwal
fonte
23
Uri uri = Uri.parse ("arquivo: ///sdcard/img.png");
Anand Tiwari
13
+1 ao comentário, apenas Uri.parse ("file: //" + filePath) deve resolver o problema
Latorre alemão 20/14
URI.parse é depreciado e "a ser adicionado"
pollaris
O @pollaris Uri.parse foi adicionado na API 1 e não está marcado para descontinuação.
JP de la Torre
Uri.parse ("alguma coisa"); não está trabalhando em mim, eu não consigo encontrar a razão pela qual ...
Bay

Respostas:

480

Tente com:

ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));

Ou com:

ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));
Francesco Laurita
fonte
3
obrigado! segundo método funciona bem em 1.6, 2.1 e 2.2, mas primeiro apenas em 2.2
Mishkin
28
nenhum desses métodos resolve um caminho de arquivo para um URI de conteúdo. Eu entendo que resolveu o problema imediato.
precisa saber é o seguinte
38
Não codifique "/ sdcard /"; utilização Environment.getExternalStorageDirectory () getPath () em vez disso.
ekatz
8
É isso que as duas soluções acima retornam: 1. file: ///storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 2. /storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 Mas o que eu estava procurando pois é algo diferente. Preciso do conteúdo: // formato URI. A resposta de Jinal parece perfeito trabalho
Ajith Memana
5
hey Uri.fromFilenão vai trabalhar no android 26+, você deve usar provedor de arquivo
vuhung3990
85

ATUALIZAR

Aqui supõe-se que sua mídia (imagem / vídeo) já tenha sido adicionada ao provedor de mídia de conteúdo. Caso contrário, não será possível obter o URL do conteúdo exatamente como você deseja. Em vez disso, haverá arquivo Uri.

Eu tive a mesma pergunta para minha atividade do explorador de arquivos. Você deve saber que o conteúdo do arquivo suporta apenas dados do mediastore, como imagem, áudio e vídeo. Estou fornecendo o código para obter o conteúdo da imagem uri ao selecionar uma imagem do sdcard. Experimente este código, talvez ele funcione para você ...

public static Uri getImageContentUri(Context context, File imageFile) {
  String filePath = imageFile.getAbsolutePath();
  Cursor cursor = context.getContentResolver().query(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.Media._ID },
      MediaStore.Images.Media.DATA + "=? ",
      new String[] { filePath }, null);
  if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
  } else {
    if (imageFile.exists()) {
      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA, filePath);
      return context.getContentResolver().insert(
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    } else {
      return null;
    }
  }
}
Jinal Jogiyani
fonte
Eu estava procurando por um método para encontrar o conteúdo: // URI do meu arquivo de vídeo gravado e o código acima parece funcionar perfeitamente no Nexus 4 (Android 4.3). Seria bom se você pudesse explicar o código.
Ajith Memana
Eu tentei isso para obter o URL do conteúdo para um arquivo com o caminho absoluto "/ sdcard / Image Depo / picture.png". Como não funcionou, depurei o caminho do código e descobri que o Cursor está vazio e, quando a entrada está sendo adicionada ao ContentProvider, ele é nulo como o Content Uri. Por favor ajude.
Sri Krishna
1
Eu tenho o caminho do arquivo - file: ///storage/emulated/0/Android/data/com.packagename/files/out.mp4, mas ficando nulo quando tento obter contentUri. Eu também tentei mudar MediaStore.Images.Mediapara MediaStore.Video.Media, mas ainda sem sorte.
Narendra Singh
1
Isso não está funcionando no Android Pie api 28. O cursor retorna nulo
Ibrahim Gharyali 15/18
1
Você pode atualizar esse método para o Android 10, pois a coluna DATA não está acessível no Android 10?
Khushbu Shah
16

// Este código funciona para imagens no 2.2, não tenho certeza se existem outros tipos de mídia

   //Your file path - Example here is "/sdcard/cats.jpg"
   final String filePathThis = imagePaths.get(position).toString();

   MediaScannerConnectionClient mediaScannerClient = new
   MediaScannerConnectionClient() {
    private MediaScannerConnection msc = null;
    {
        msc = new MediaScannerConnection(getApplicationContext(), this);
        msc.connect();
    }

    public void onMediaScannerConnected(){
        msc.scanFile(filePathThis, null);
    }


    public void onScanCompleted(String path, Uri uri) {
        //This is where you get your content uri
            Log.d(TAG, uri.toString());
        msc.disconnect();
    }
   };
AndroidDebaser
fonte
1
ótimo, me ajudou a compartilhar no Google+, pois esse aplicativo requer um fluxo de mídia com um conteúdo Uri - o caminho absoluto não funciona.
Ridcully
1
Excelente! Posso confirmar que isso também funciona com os tipos de mídia de áudio.
Matt M
16

A solução aceita é provavelmente a melhor aposta para seus propósitos, mas para realmente responder à pergunta na linha de assunto:

No meu aplicativo, eu tenho que obter o caminho dos URIs e obter o URI dos caminhos. O antigo:

/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

O último (que eu faço para vídeos, mas também pode ser usado para Áudio ou Arquivos ou outros tipos de conteúdo armazenado, substituindo MediaStore.Audio (etc) por MediaStore.Video):

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {


    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

Basicamente, a DATAcoluna MediaStore(ou qualquer subseção que você está consultando) armazena o caminho do arquivo, para que você use essas informações para procurá-lo.

Jon O
fonte
Nem sempre é o caso, há duas colunas semi-garantidas retornadas, ou seja, OpenableColumns.DISPLAY_NAME & OpenableColumns.SIZEse o aplicativo de envio ainda segue as "regras". Descobri que alguns aplicativos principais retornam apenas esses dois campos e nem sempre o _datacampo. No caso em que você não possui o campo de dados que normalmente contém um caminho direto para o conteúdo, você deve primeiro ler o conteúdo e gravá-lo em um arquivo ou na memória e, em seguida, ter seu próprio caminho.
28419 Pierre
7

Você pode usar essas duas maneiras com base no uso

Uri uri = Uri.parse("String file location");

ou

Uri uri = Uri.fromFile(new File("string file location"));

Eu tentei nos dois sentidos e nos dois trabalhos.

Abhishek Meharia
fonte
5

A maneira mais fácil e robusta de criar o Content Uri a content://partir de um arquivo é usar o FileProvider . O Uri fornecido pelo FileProvider também pode ser usado, fornecendo o Uri para o compartilhamento de arquivos com outros aplicativos. Para obter o File Uri a partir de um caminho absoluto, Filevocê pode usar DocumentFile.fromFile (novo arquivo (caminho, nome)), ele é adicionado na Api 22 e retorna nulo para as versões abaixo.

File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
Trácia
fonte
2

Obtendo o ID do arquivo sem escrever nenhum código, apenas com os comandos da CLI adb shell:

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"
BogdanBiv
fonte
O Google "adb obtém o caminho real do conteúdo da interface do usuário" e esta pergunta é a principal 1, com o conteúdo da sua resposta com 0 voto no resumo do resultado da pesquisa. Então deixe-me ser o primeiro a votar. OBRIGADO mano!
Fim de semana
Isso é legal. Mas parece que você receberá:, a Permission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLYmenos que esteja enraizado.
Not2qubit # 418
então isso precisa de acesso root do telefone?
Samintha Kaveesh
1

É melhor usar uma validação para suportar versões anteriores ao Android N, por exemplo:

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     imageUri = Uri.parse(filepath);
  } else{
     imageUri = Uri.fromFile(new File(filepath));
  }

  if (Build.VERSION.SDK_INT >=  Build.VERSION_CODES.N) {
     ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));         
  } else{
     ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));
  }

https://es.stackoverflow.com/questions/71443/reporte-crash-android-os-fileuriexposedexception-en-android-n

Jorgesys
fonte
0

Você pode tentar o trecho de código abaixo

    public Uri getUri(ContentResolver cr, String path){
    Uri mediaUri = MediaStore.Files.getContentUri(VOLUME_NAME);
    Cursor ca = cr.query(mediaUri, new String[] { MediaStore.MediaColumns._ID }, MediaStore.MediaColumns.DATA + "=?", new String[] {path}, null);
    if (ca != null && ca.moveToFirst()) {
        int id = ca.getInt(ca.getColumnIndex(MediaStore.MediaColumns._ID));
        ca.close();
        return  MediaStore.Files.getContentUri(VOLUME_NAME,id);
    }
    if(ca != null) {
        ca.close();
    }
    return null;
}
caopeng
fonte
1
O que é VOLUME_NAME?
Evgenii Vorobei
É "externo" ou "interno"
caopeng 12/07/19