android Uri.getPath()で実際のパスを取得


107

ギャラリーから画像を取得しようとしています。

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );

このアクティビティから戻った後、ウリを含むデータがあります。それは次のようになります:

content://media/external/images/1

このパスを実際のパスに変換するにはどうすればよい/sdcard/image.pngですか(「」のように)?

ありがとう


1
これは明らかに非常に遅いコメントですが、startActivityForResultCodeメソッドは、結果コードではなくリクエストコードを引数として受け取ることを指摘したいと思います。
Tianxiang Xiong 2015

uri.getPath()あなたに本当の道を与えませんでしたか?
ダーパン

#Try Thisそれでも、実際のパスを取得するために問題が発生している場合は、私の答えを試すことができます。上記の答えは私を助けませんでした。説明:-このメソッドは、URIを取得してから、AndroidデバイスのAPIレベルをチェックします。その後、APIレベルに従って、実際のパスを生成します。実際のパスを生成するコードは、APIレベルによって異なります。 ここに私の答えは
スニル

回答:


56

物理的なパスを取得することが本当に必要ですか?
たとえば、ImageView.setImageURI()そしてContentResolver.openInputStream()あなたがその実際のパスを知らなくても、ファイルの内容にアクセスすることを可能にします。


それはまさに私が探したものですが、見つかりませんでした。ありがとう。
davs

6
申し訳ありませんが、この画像をファイルに変換したい場合は、実際のパスを取得せずにどうすればよいですか?
クレブタ2014年

6
物理パスは、ファイル名と拡張子へのアクセスを提供します。ファイルのアップロードの場合。
クロッカー、2015

195

これが私がすることです:

Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));

そして:

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else { 
        cursor.moveToFirst(); 
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

注:managedQuery()メソッドは非推奨であるため、使用していません。

最終編集:改善。カーソルを閉じます!!


1
stackoverflow.com/a/7265235/375093これは別のオプションですが、上記よりも優れていると推奨されています。これもチェックしてください
Sundeep 2013

6
こんにちは@ m3n0Rさん、Moto GではMediaStore.Images.ImageColumns.DATA列がまったく存在しません。この列なしで画像を取得するにはどうすればよいですか?
seema

16
エラー データにアクセスする前に、カーソルが正しく初期化されていることを確認してください
。API19で

1
@ReneJuuse:優れたリソース。そのおかげで、ようやくこの問題を解決することができました。Androidの登場以来、多くの変更があったことに気づきませんでした。私はAPI 21を実行していましたが、リンクしたサイトに表示されているAPI 19の実装を使用すると、ようやく機能しました。
ミロスイワノビッチ2015年

2
CursorWindowから行0、列-1を読み取れませんでした。カーソルからデータにアクセスする前に、カーソルが正しく初期化されていることを確認してください。
Mavenのツ

18

@Rene Juuse-上記のコメント...このリンクをありがとう!

。実際のパスを取得するコードはSDKごとに少し異なるため、以下に異なるSDKを処理する3つのメソッドがあります。

getRealPathFromURI_API19():API 19(またはそれ以上ですがテストされていません)の実際のパスを返します。getRealPathFromURI_API11to18():API 11の実際のパスをAPI 18に返します。

public class RealPathUtil {

@SuppressLint("NewApi")
public static String getRealPathFromURI_API19(Context context, Uri uri){
    String filePath = "";
    String wholeID = DocumentsContract.getDocumentId(uri);

     // Split at colon, use second item in the array
     String id = wholeID.split(":")[1];

     String[] column = { MediaStore.Images.Media.DATA };     

     // where id is equal to             
     String sel = MediaStore.Images.Media._ID + "=?";

     Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                               column, sel, new String[]{ id }, null);

     int columnIndex = cursor.getColumnIndex(column[0]);

     if (cursor.moveToFirst()) {
         filePath = cursor.getString(columnIndex);
     }   
     cursor.close();
     return filePath;
}


@SuppressLint("NewApi")
public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
      String[] proj = { MediaStore.Images.Media.DATA };
      String result = null;

      CursorLoader cursorLoader = new CursorLoader(
              context, 
        contentUri, proj, null, null, null);        
      Cursor cursor = cursorLoader.loadInBackground();

      if(cursor != null){
       int column_index = 
         cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
       cursor.moveToFirst();
       result = cursor.getString(column_index);
      }
      return result;  
}

public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri){
           String[] proj = { MediaStore.Images.Media.DATA };
           Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
           int column_index
      = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
           cursor.moveToFirst();
           return cursor.getString(column_index);
}

フォント: http //hmkcode.com/android-display-selected-image-and-its-real-path/


2016年3月更新

画像のパスに関するすべての問題を解決するには、カスタムギャラリーをFacebookや他のアプリとして作成してみます。これは、ローカルファイル(仮想ファイルや一時ファイルではなく、実際のファイル)のみを使用できるためです。このライブラリのすべての問題を解決します。

https://github.com/nohana/Laevatein (このライブラリは、カメラから写真を撮るか、ギャラリーから選択します。ギャラリーから選択した場合、彼はアルバム付きの引き出しを持っており、ローカルファイルのみを表示します)


サムスンS4の@Clockerも
Ricardo

私は本当にアンドロイドですべてのタイプのソース画像を管理するのが難しいです。アップロードするか、ギャラリーから選択する場合、最善の解決策はFacebookからギャラリーとして作成することです。デバイス内の実際の画像のみを含むカスタムギャラリーであり、仮想または一時的なものではありません。このライブラリを使用して、アプリのすべての問題を修正します。github.com/nohana/Laevatein 本当に良いライブラリです。カスタマイズは簡単ではありませんが、コードを開いて変更を加えることができます。これがお役に立てば幸いです。
luizfelipetx 2016年

私のサムスンS2で4.4.1が壊れています
Oliver Dixon

PDFやDOCなどのファイルを取得する必要があります。パスを取得できません。手伝ってくれませんか?
Anish Kumar 2016

1
驚くばかり!最後に、本当にうまくいくもの。長い間これを探していました。ありがとう。
Javatar 2016年

14

これは@ user3516549の回答の改善であり、Android 6.0.1
を搭載したMoto G3で確認しています。この問題があるため、@ user3516549の回答を試しましたが、場合によっては正しく機能しませんでした。Android 6.0以降では、ギャラリー画像選択インテントを開始すると、最近の画像を表示する画面が開き、ユーザーがこのリストから画像を選択すると、URIが次のように表示されます。

content://com.android.providers.media.documents/document/image%3A52530

一方、ユーザーが最近ではなくスライド式の引き出しからギャラリーを選択すると、URIは次のようになります。

content://media/external/images/media/52530

だから私はそれを取り扱っています getRealPathFromURI_API19()

public static String getRealPathFromURI_API19(Context context, Uri uri) {
        String filePath = "";
        if (uri.getHost().contains("com.android.providers.media")) {
            // Image pick from recent 
            String wholeID = DocumentsContract.getDocumentId(uri);

            // Split at colon, use second item in the array
            String id = wholeID.split(":")[1];

            String[] column = {MediaStore.Images.Media.DATA};

            // where id is equal to
            String sel = MediaStore.Images.Media._ID + "=?";

            Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, new String[]{id}, null);

            int columnIndex = cursor.getColumnIndex(column[0]);

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();
            return filePath;
        } else {
            // image pick from gallery 
           return  getRealPathFromURI_BelowAPI11(context,uri)
        }

    }

編集:上位バージョンの外部SDカードにあるファイルの画像パスを取得しようとしている場合は、私の質問を確認しください


こんにちは友人、そうです。しかし、これは起こっているのは、Googleがすべての写真を携帯電話からGoogleドキュメントにアップロードするデフォルトのフォーマットを持っているためです。そしてちょうどあなたの携帯電話に親指を保存します。GoogleドキュメントからこのURIを取得した場合は、これを使用する前に写真をダウンロードする必要があります。これは一般的に良くありません。したがって、ここですべての問題を修正するには、このライブラリを使用しています。(このライブラリはローカルファイルを使用するだけで、このソリューションで問題は解決されます)または、ライブラリからコードを抽出して、問題に対処するために自分自身を改善できます。github.com/nohana/Laevateinこれがあなたのお役に立てば幸いです。
luizfelipetx 2016年

1+、その仕事は私にぴったりです。@JaiprakasSoniが彼の回答で言ったように、Moto G4プレイでアプリを実行すると同じ問題に直面しましたが、上記のコードを使用するとうまく動作します。ありがとうございます。あなたは私の時間を節約します
Shailesh 2017年

6

編集: ここでこのソリューションを使用してください:https//stackoverflow.com/a/20559175/2033223 完璧に動作します!

まず、あなたのソリューションに感謝します@luizfelipetx

私はあなたの解決策を少し変えました。これは私にとってはうまくいきます:

public static String getRealPathFromDocumentUri(Context context, Uri uri){
    String filePath = "";

    Pattern p = Pattern.compile("(\\d+)$");
    Matcher m = p.matcher(uri.toString());
    if (!m.find()) {
        Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString());
        return filePath;
    }
    String imgId = m.group();

    String[] column = { MediaStore.Images.Media.DATA };
    String sel = MediaStore.Images.Media._ID + "=?";

    Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            column, sel, new String[]{ imgId }, null);

    int columnIndex = cursor.getColumnIndex(column[0]);

    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }
    cursor.close();

    return filePath;
}

注:したがって、画像が「最近」、「ギャラリー」、または何からのものかによって、ドキュメントと画像を取得しました。だから私はそれを調べる前にまず画像IDを抽出します。


1

Hiiは、カメラまたはギャラリーから画像を取得するための完全なコードです

//私の変数宣言

protected static final int CAMERA_REQUEST = 0;
    protected static final int GALLERY_REQUEST = 1;
    Bitmap bitmap;
    Uri uri;
    Intent picIntent = null;

// Onclick

if (v.getId()==R.id.image_id){
            startDilog();
        }

//メソッド本体

private void startDilog() {
    AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this);
    myAlertDilog.setTitle("Upload picture option..");
    myAlertDilog.setMessage("Where to upload picture????");
    myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
            picIntent.setType("image/*");
            picIntent.putExtra("return_data",true);
            startActivityForResult(picIntent,GALLERY_REQUEST);
        }
    });
    myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(picIntent,CAMERA_REQUEST);
        }
    });
    myAlertDilog.show();
}

//そして残りのこと

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode==GALLERY_REQUEST){
        if (resultCode==RESULT_OK){
            if (data!=null) {
                uri = data.getData();
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                try {
                    BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    options.inSampleSize = calculateInSampleSize(options, 100, 100);
                    options.inJustDecodeBounds = false;
                    Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    imageofpic.setImageBitmap(image);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }else {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        }else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }else if (requestCode == CAMERA_REQUEST) {
        if (resultCode == RESULT_OK) {
            if (data.hasExtra("data")) {
                bitmap = (Bitmap) data.getExtras().get("data");
                uri = getImageUri(YourActivity.this,bitmap);
                File finalFile = new File(getRealPathFromUri(uri));
                imageofpic.setImageBitmap(bitmap);
            } else if (data.getExtras() == null) {

                Toast.makeText(getApplicationContext(),
                        "No extras to retrieve!", Toast.LENGTH_SHORT)
                        .show();

                BitmapDrawable thumbnail = new BitmapDrawable(
                        getResources(), data.getData().getPath());
                pet_pic.setImageDrawable(thumbnail);

            }

        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

private String getRealPathFromUri(Uri tempUri) {
    Cursor cursor = null;
    try {
        String[] proj = { MediaStore.Images.Media.DATA };
        cursor = this.getContentResolver().query(tempUri,  proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
    String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
    return Uri.parse(path);
}

この行は100であることがわかります options.inSampleSize = calculateInSampleSize(options, 100, 100);
John Joe

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