ギャラリーから画像を取得しようとしています。
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );
このアクティビティから戻った後、Uriを含むデータがあります。次のようになります。
content://media/external/images/1
このパスを実際のパス(「/sdcard/image.png
」のように)に変換するにはどうすればよいですか?
ありがとう
物理的なパスを取得することは本当に必要ですか?
たとえば、ImageView.setImageURI()
およびContentResolver.openInputStream()
を使用すると、実際のパスを知らなくてもファイルの内容にアクセスできます。
これが私がすることです:
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()
メソッドは推奨されないため、使用していません。
最終編集:改善。カーソルを閉じる必要があります!!
@Rene Juuse-上記のコメント...このリンクをありがとう!
。実際のパスを取得するコードはSDKごとに少し異なるため、以下に異なるSDKを扱う3つのメソッドがあります。
getRealPathFromURI_API19():API 19の実際のパスを返します(またはテスト済みではありません)getRealPathFromURI_API11to18():API 11からAPI 18の実際のパスを返しますgetRealPathFromURI_below11(): 11未満のAPIの実際のパスを返します
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 (このライブラリは、カメラから写真を撮るか、ギャラリーから選択します。ギャラリーから選択すると、アルバムの引き出しがあり、ローカルファイルを表示します)
注これは @ user3516549 answer の改善であり、Androidを使用してMoto G3で確認しました。 6.0.1
この問題があるので、@ user3516549の回答を試みましたが、場合によっては正しく機能していませんでした。 Android 6.0(またはそれ以上)でギャラリー画像ピックインテントを開始すると、ユーザーがこのリストから画像を選択すると最近の画像を表示する画面が開くことがわかりました
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カードのファイルの画像パスを取得しようとしている場合は、 私の質問 を確認してください
実際のパスはありません。
Uri
スキームを持つcontent
は、一部のコンテンツに対する不透明なハンドルです。そのUri
がオープン可能なコンテンツを表す場合、ContentResolver
およびopenInputStream()
を使用して、そのコンテンツのInputStream
を取得できます。同様に、Uri
またはhttp
スキームを持つhttps
はローカルファイルを表さないため、HTTPクライアントAPIを使用してアクセスする必要があります。
Uri
スキームを持つfile
のみがファイルを識別します(Uri
の作成後にファイルが移動または削除された場合を除く)。
愚かな人々は、Uri
の内容をデコードすることでファイルシステムパスを導き出そうとします。おそらく、$EVIL_DEITY
を呼び出すために呪文を唱えることと組み合わせてください。せいぜい、これは3つの理由で信頼できないでしょう:
Uri
の構造はインターフェースではなく実装の詳細を表すため、Androidバージョンリリースなど、Uri
値をデコードするためのルールは時間とともに変化する可能性があります
ファイルシステムのパスを取得しても、ファイルにアクセスする権限がない場合があります
多くのアプリには独自のプロバイダーがあるため、すべてのUri
値を固定アルゴリズムでデコードできるわけではなく、それらはアセットからBLOB
列、インターネットからストリーミングする必要のあるデータまですべてを指すことができます
ファイルを必要とするAPIが限られている場合は、openInputStream()
のInputStream
を使用して、そのコンテンツのコピーを作成します。それが一時的なコピー(たとえば、ファイルのアップロード操作に使用され、その後削除される)か、永続的なコピー(たとえば、アプリの「インポート」機能用)かはユーザー次第です。
EDIT:ここでこのソリューションを使用してください: https://stackoverflow.com/a/20559175/203322 完璧に動作します!
まず、あなたのソリューションに感謝します@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を抽出します。
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);
}
それでも、実際のパスを取得するために問題が発生している場合は、私の答えを試すことができます。上記の答えは私を助けませんでした。
説明:-このメソッドはURIを取得し、AndroidデバイスのAPIレベルを確認し、その後APIレベルに従って実際のパスを生成します。 実際のパスを生成するためのコードは、APIレベルによって異なります。
これにより、ギャラリーからURIを取得し、マルチパートアップロード用のファイルに変換できました
File file = FileUtils.getFile(this, fileUri);