0

I've fetched a user selected image from gallery and want to display it in a imageview

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

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            selectedImagePath = getPath(selectedImageUri);

            imageView.setImageBitmap(BitmapFactory
                        .decodeFile(selectedImagePath));

            Log.i("SELECTED IMAGE: ", selectedImagePath);
        }
    }
}

/**
 * helper to retrieve the path of an image URI
 */
public String getPath(Uri uri) {
    // just some safety built in
    if( uri == null ) {
        // TODO perform some logging or show user feedback
        return null;
    }
    // try to retrieve the image from the media store first
    // this will only work for images selected from gallery
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if( cursor != null ){
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    // for other file managers
    return uri.getPath();
}

There are some images with path as: /storage/sdcard0/WhatsApp/Media/WhatsApp Images/IMG-20150407-WA0013.jpg which get displayed properly

And there are some images which give path as a google download link. Example: https://lh3.googleusercontent.com/-9VYhxxxmZs/VdQnxxxo5I/AAAAxxxCpM/4B3s-xxoeI/I/2015-08-08.jpg (path changed in the post for privacy)

These images do not get displayed.

I one such case,

I'm getting Uri as content://com.sec.android.gallery3d.provider/picasa/item/5913341278276321746

and selectedImagePath as https://lh3.googleusercontent.com/-9VYhxxxmZs/VdQnxxxo5I/AAAAxxxCpM/4B3s-xxoeI/I/2015-08-08.jpg

How can I get selectedImagePath of such images as a path in the phone and not as a web location?

user5155835
  • 4,392
  • 4
  • 53
  • 97
  • Have you consider using third-party libraries such as Picasso (http://square.github.io/picasso/) or Glide (https://github.com/bumptech/glide)? – GuilhE Sep 29 '15 at 10:11
  • @GuilhE I thought it could be handled by android libraries itself – user5155835 Sep 29 '15 at 10:15
  • And you can but it would require more code. Use one of this libs (usually I use Picasso), it's pretty easy and fast to do so, and you have cache system implemented etc etc. Give it a try ;) – GuilhE Sep 29 '15 at 10:16
  • @GuilhE I would try that, but right now how can this be done in existing code? – user5155835 Sep 29 '15 at 10:21
  • @GuilhE what changes would be needed in existing code? – user5155835 Sep 29 '15 at 10:32
  • use third-party library for caching and reducing chances of `OutOfMemoryError` @user5155835 [Fresco](http://frescolib.org/docs/index.html#_) , [Glide](https://github.com/bumptech/glide) or [Picasso](http://square.github.io/picasso/) – Kaushik Sep 29 '15 at 10:58

3 Answers3

2

As I stated in the comments you should use libraries such as Picasso or Glide because in their implementation there are a lots of corners cases solved like cache systems, network failure handling, image effects and transformations, memory performance and so on.

If you want to this in a simpler way and "by hand" you should consider this:

private class NetworkImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
    @Override
    protected Void doInBackground(String... params) {
       try {
            InputStream in = new URL(params[0]).openStream();
            bitmap = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            return null;
        }
       return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
         if (result != null)
              mImageView.setImageBitmap(result);
         }
    }
}

Just call: new NetworkImageAsyncTask("url").execute();
You should use an AsyncTask because this "network methods" should not be done in the main thread.

NOTE: this solution does not include memory leaks safe code, it's just an example approach

EDIT (comments reply):
Try this instead:

Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/jpg");

...

String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
cursor.moveToFirst();
String path = cursor.getString(cursor.getColumnIndex(projection[0]));
cursor.close();
return path;
GuilhE
  • 11,591
  • 16
  • 75
  • 116
  • Google cloud photos (from Photos app) are displayed in the gallery and they're not in the phone. Check if your path is something like: "content://com.google.android...." – GuilhE Sep 29 '15 at 11:15
2

I solved it using:

Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");

startActivityForResult(Intent.createChooser(intent,
        "Share Photo"), SELECT_PICTURE);


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            String selectedImagePath = getPath(selectedImageUri);  

            selectedImageUri = selectedImageUri .replace("com.android.gallery3d","com.google.android.gallery3d");

            if (selectedImageUri .startsWith("content://com.google.android.gallery3d")
                || selectedImageUri .startsWith("content://com.sec.android.gallery3d.provider") ) {

                selectedImagePath = PicasaImage(selectedImageUri);
            }
            else
                selectedImagePath = getPath(selectedImageUri);
            }

            imageView.setImageBitmap(BitmapFactory
                            .decodeFile(selectedImagePath));

            Log.i("SELECTED IMAGE PATH: ", selectedImagePath);
    }
}

private String PicasaImage(Uri imageUri) {

    File cacheDir;
    // if the device has an SD card
    if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
        cacheDir = new File(android.os.Environment.getExternalStorageDirectory(),".OCFL311");
    } else {
        // it does not have an SD card
        cacheDir = getCacheDir();
    }

    if(!cacheDir.exists()) cacheDir.mkdirs();

    File f = new File(cacheDir, "tempPicasa");

    try {

        InputStream is = null;
        if (imageUri.toString().startsWith("content://com.google.android.gallery3d")
                || imageUri.toString().startsWith("content://com.sec.android.gallery3d.provider")) {

            is = getContentResolver().openInputStream(imageUri);
        } else {
            is = new URL(imageUri.toString()).openStream();
        }

        OutputStream os = new FileOutputStream(f);

        //Utils.InputToOutputStream(is, os);

        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }

        return f.getAbsolutePath();
    } catch (Exception ex) {
        Log.i(this.getClass().getName(), "Exception: " + ex.getMessage());
        // something went wrong
        ex.printStackTrace();
        return null;
    }
}

public String getPath(Uri uri) {
    // just some safety built in
    if( uri == null ) {
        // TODO perform some logging or show user feedback
        return null;
    }
    // try to retrieve the image from the media store first
    // this will only work for images selected from gallery
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if( cursor != null ){
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    // for other file managers
    return uri.getPath();
}
user5155835
  • 4,392
  • 4
  • 53
  • 97
0

Try this to download a bitmap:

URL url = new URL(sUrl);
HttpURLConnection connection  = (HttpURLConnection) url.openConnection();

InputStream is = connection.getInputStream();
Bitmap img = BitmapFactory.decodeStream(is);
Khawar Raza
  • 15,870
  • 24
  • 70
  • 127