AndroidのファイルパスからコンテンツURIを取得する


271

画像の絶対パスを知っています(たとえば、/ sdcard / cats.jpg)。このファイルのコンテンツURIを取得する方法はありますか?

実際、私のコードでは、画像をダウンロードして特定の場所に保存しています。ImageViewインスタンスに画像を設定するには、現在パスを使用してファイルを開き、バイトを取得してビットマップを作成してから、ImageViewインスタンスにビットマップを設定します。これは非常に遅いプロセスですが、コンテンツuriを取得できれば、メソッドを非常に簡単に使用できます。 imageView.setImageUri(uri)


23
Uri uri = Uri.parse( "file:///sdcard/img.png");
アナンドティワリ2009

13
コメントに+1して、Uri.parse( "file://" + filePath)だけでうまくいくはずです
ドイツ語Latorre

Uri.Parseが非推奨になり、「追加される」
pollaris

@pollaris Uri.parseはAPI 1で追加され、非推奨としてマークされていません。
JP de la Torre

Uri.parse( "何か"); は私に取り組んでいません、理由がわかりません...
Bay

回答:


480

試してみてください:

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

または:

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

3
ありがとう!2番目の方法は
1.6、2.1

28
これらのメソッドはいずれも、コンテンツURIへのファイルパスを解決しません。私はそれが当面の問題を解決したことを理解しています。
Jeffrey Blattman、2011

38
「/ sdcard /」をハードコードしないでください。代わりにEnvironment.getExternalStorageDirectory()。getPath()を使用してください
ekatz

8
これは、上記の両方のソリューションが返すものです。1. file:///storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4 2. /storage/emulated/0/DCIM/Camera/VID_20140312_171146.mp4しかし、私が探していたもの何か違うのです。content://形式のURIが必要です。ジナルからの回答は完璧に機能するようです
Ajith Memana

5
hey Uri.fromFileはandroid 26以降では機能しません。ファイルプロバイダーを使用する必要があります
vuhung3990

85

更新

ここでは、メディア(画像/ビデオ)がコンテンツメディアプロバイダーに既に追加されていると想定しています。そうしないと、コンテンツURLを正確に取得できなくなります。代わりに、ファイルUriがあります。

ファイルエクスプローラのアクティビティについても同じ質問がありました。ファイルのcontenturiは、画像、オーディオ、ビデオなどのメディアストアデータのみをサポートすることを知っておく必要があります。SDカードから画像を選択して画像コンテンツURIを取得するためのコードを提供します。このコードを試してください、多分それはあなたのために働くでしょう...

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;
    }
  }
}

録画したビデオファイルのcontent:// URIを見つける方法を探していましたが、上記のコードはNexus 4(Android 4.3)で完全に動作するようです。コードを説明していただければ幸いです。
Ajith Memana 2014年

私はこれを試し、絶対パスが "/ sdcard / Image Depo / picture.png"のファイルのコンテンツURIを取得しました。機能しなかったため、コードパスをデバッグしたところ、Cursorが空であることがわかりました。また、エントリがContentProviderに追加されると、コンテンツURIとしてnullが返されます。助けてください。
スリクリシュナ

1
ファイルパスがあります-file:///storage/emulated/0/Android/data/com.packagename/files/out.mp4ですが、contentUriを取得しようとするとnullになります。私もに変更MediaStore.Images.MediaしてみましたMediaStore.Video.Mediaが、まだうまくいきませんでした。
Narendra Singh

1
これはAndroid Pie api 28では機能しません。カーソルがnullを返します
Ibrahim Gharyali '15年

1
Android 10ではDATA列にアクセスできないため、このメソッドをAndroid 10用に更新できますか?
Khushbu Shah

16

//このコードは2.2の画像で機能しますが、他のメディアタイプかどうかはわかりません

   //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();
    }
   };

1
素晴らしい、Google +への共有に役立ちました。そのアプリにはコンテンツUriを含むメディアストリームが必要なので、絶対パスは機能しません。
Ridcully 2012年

1
優れた!これがオーディオメディアタイプでも機能することを確認できます。
Matt M

16

受け入れられた解決策はおそらくあなたの目的にとって最善の策ですが、実際に件名の質問に答えるには:

私のアプリでは、URIからパスを取得し、パスからURIを取得する必要があります。前者:

/**
 * 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;
}

後者(ビデオの場合はこれを行いますが、MediaStore.VideoをMediaStore.Audio(など)に置き換えることにより、オーディオやファイル、またはその他の種類の保存されたコンテンツにも使用できます):

/**
 * 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;
}

基本的に、のDATAMediaStore(または照会するサブセクション)にはファイルパスが格納されるため、その情報を使用して検索します。


常にそうとは限りませんが、2つの半保証列が返されます。これはOpenableColumns.DISPLAY_NAME & OpenableColumns.SIZE、送信アプリが「ルール」に従う場合でも同様です。一部の主要なアプリはこれら2つのフィールドのみを返し、常にフィールドを返すわけではないことがわかりました_data。通常はコンテンツへの直接パスが含まれるデータフィールドがない場合は、まずコンテンツを読み取り、それをファイルまたはメモリに書き込んでから、独自のパスを作成する必要があります。
ピエール

7

使用に基づいてこれらの2つの方法を使用できます

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

または

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

私は両方の方法を試し、両方とも機能しました。


5

content://ファイルからコンテンツURIを作成する最も簡単で確実な方法は、FileProviderを使用することです。FileProviderが提供するUriは、他のアプリとファイルを共有するためのUriも提供します。FileDocumentFile.fromFile(new File(path、name))を使用できる絶対パスからファイルURIを取得するには、API 22で追加され、以下のバージョンではnullを返します。

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


2

コードを記述せずに、adbシェルCLIコマンドでファイルIDを取得します。

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"

Googleは「adb get content URI from content uri」であり、この質問はトップ1で、0票回答のコンテンツが検索結果の要約に表示されます。だから私は最初に投票しましょう。ありがとうございます!
週末

これはカッコいい。:しかし、あなたが得るように見えるPermission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY、あなたが根ざしている場合を除き。
not2qubit 2018年

これには電話のルートアクセスが必要ですか?
Samintha Kaveesh

1

検証を使用してAndroid Nより前のバージョンをサポートすることをお勧めします。例:

  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


0

以下のコードスニペットを試すことができます

    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;
}

1
VOLUME_NAMEとは何ですか?
Evgenii Vorobei

「外部」または「内部」
caopeng
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.