androïde obtenir vrai chemin par Uri.getPath()
j'essaie d'obtenir une image de la galerie.
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );
après mon retour de cette activité, j'ai une donnée, qui contient Uri. On dirait:
content://media/external/images/1
comment convertir ce chemin en chemin réel (comme /sdcard/image.png
')?
Merci
9 réponses
Est-il vraiment nécessaire pour vous d'obtenir un chemin d'accès physique?
Par exemple, ImageView.setImageURI()
et ContentResolver.openInputStream()
vous permettent d'accéder au contenu d'un fichier sans en connaître le véritable chemin.
C'est ce que je fais:
Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));
et:
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;
}
NOTE: managedQuery()
méthode est dépréciée, donc je ne l'utilise pas.
dernière édition: amélioration. On devrait fermer le curseur!!
@Rene Juuse-ci-dessus dans les commentaires... Merci pour ce lien!!!
. le code pour obtenir le chemin réel est un peu différent d'un SDK à l'autre donc ci-dessous nous avons trois méthodes qui traitent avec différents SDK.
getRealPathFromURI_API19 (): renvoie le chemin réel pour API 19 (ou plus haut mais non testé)) getRealPathFromURI_API11to18 (): renvoie real path pour API 11 à API 18 getRealPathFromURI_below11 (): renvoie le chemin réel pour API below 11
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);
}
font: http://hmkcode.com/android-display-selected-image-and-its-real-path /
mise à jour 2016 mars
pour corriger tous les problèmes avec le chemin des images, j'essaie de créer une galerie personnalisée comme facebook et d'autres applications. C'est parce que vous pouvez utiliser juste des fichiers locaux ( fichiers réels, pas virtuels ou temporaires) , Je résous tous les problèmes avec cette bibliothèque.
https://github.com/nohana/Laevatein (cette bibliothèque est de prendre des photos de l'appareil photo ou de choisir de la galerie , si vous choisissez dans la galerie il a un tiroir avec des albums et juste montrer des dossiers locaux)
Note c'est une amélioration dans @user3516549 réponse et je l'ai vérifier sur Moto G3 avec Android 6.0.1
J'ai ce problème j'ai donc essayé de réponse de @user3516549 mais dans certains cas, il ne fonctionnait pas correctement.
J'ai trouvé que dans Android 6.0 (ou au-dessus) quand nous commençons Galerie image pick intention puis un écran s'ouvrira qui montre les images récentes lorsque l'utilisateur sélectionne l'image de cette liste, nous obtiendrons uri comme
content://com.android.providers.media.documents/document/image%3A52530
alors que si l'utilisateur sélectionne galerie à partir de tiroir coulissant au lieu de récent, nous obtiendrons uri comme
content://media/external/images/media/52530
donc je dois gérer en 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)
}
}
EDIT : si vous essayez d'obtenir le chemin de l'image de fichier dans la carte sd externe en plus de la version puis cochez la case ma question
il n'y a pas de véritable chemin .
Un Uri
avec un content
système est opaque poignée à certains contenus. Si ce Uri
représente un contenu ouvert, vous pouvez utiliser ContentResolver
et openInputStream()
pour obtenir un InputStream
sur ce contenu. De même, un Uri
avec un schéma http
ou https
ne représente pas un fichier local, et vous devrez utiliser une API client HTTP pour y accéder.
seul un Uri
avec un schéma file
identifie un fichier (sauf dans les cas où le fichier a été déplacé ou supprimé après la création du Uri
).
ce que les gens stupides font est d'essayer de dériver un chemin du système de fichiers en essayant de décoder le contenu du Uri
, peut-être couplé avec des sorts de lancer pour invoquer $EVIL_DEITY
. Au mieux, cela ne sera pas fiable, pour trois raisons:
-
les règles pour le décodage des valeurs
Uri
peut changer au fil du temps, comme avec les versions Android, comme la structure duUri
représente un détail de mise en œuvre, pas une interface -
même si vous obtenez un chemin du système de fichiers, vous ne pouvez pas avoir le droit d'accéder au fichier
-
pas toutes les valeurs
Uri
peuvent être décodées via des algorithmes fixes, car de nombreuses applications ont leurs propres fournisseurs, et ceux-ci peut-point à l'actif deBLOB
colonnes de données qui doit être transmis à partir de l'Internet
si vous avez une API limitée qui nécessite un fichier, utilisez le InputStream
de openInputStream()
pour faire une copie de ce contenu. Qu'il s'agisse d'une copie transitoire (par exemple, utilisée pour une opération de téléchargement de fichier, puis supprimée) ou d'une copie durable (par exemple, pour une fonction "Importer" de votre application) dépend de vous.
EDIT: Utilisez cette Solution ici: https://stackoverflow.com/a/20559175/2033223 Fonctionne parfaitement!
tout D'abord, merci pour votre solution @luizfelipetx
j'ai un peu changé votre solution. Cela me convient:
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;
}
Note: Nous avons donc des documents et des images, selon que l'image provient de 'récents', 'galerie' ou quoi que ce soit. Donc j'extrait d'abord L'ID de l'image avant de regarder.
hii voici mon code complet pour prendre des images de la caméra ou de la galerie
/ / ma déclaration de variable
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();
}
//corps de la méthode
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();
}
//Et le reste des choses
@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);
}
cela m'a aidé à obtenir uri de la galerie et convertir en un fichier pour le téléchargement Multipart
File file = FileUtils.getFile(this, fileUri);
Essayez Cette
encore, si vous obtenez le problème pour obtenir le vrai chemin, vous pouvez essayer mes réponses. Les réponses ci-dessus ne m'ont pas aidé.
explication : - cette méthode obtient L'URI et puis vérifier le niveau API de votre appareil Android après que selon le niveau API, il va générer le chemin réel. Le Code pour générer le chemin réel est différent selon les niveaux de L'API.