Search code examples
javaandroidandroid-contentproviderandroid-sdcardandroid-gallery

Get path to image chosen from gallery(on SD card)


I simply CANNOT get the path to an image chosen from the gallery thats on the SD card, but there is no problem with images stored on the device. There are dozens of similar or duplicate questions like this, but none of them are working.

The most recommended approach (by @Commonsware) is to use a ContentResolver and call openInputStream(), so I tried reading the bytes from openInputStream() then creating a temp file and using that path, no luck. My "bytes read: " System.err.println call shows 0 bytes read.

I also tried this, this, this, this, this, and this, none work. A lot of these answers lead to calling BitmapFactory#decodeStream(), problem is, I couldn't care less about displaying the image, I JUST NEED THE PATH!!.

Please Help!

Code so far:

 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(resultCode == Activity.RESULT_OK){

        switch(requestCode){

            case SELECT_FROM_GALLERY:
                fromGallery = true;
                path = getRealPathFromURI(data.getData());
                System.err.println("*******path: " + path + "*********");

                break;

        }

    }

}

public String getRealPathFromURI(Uri contentUri) {
    String thePath = null;
    String[] filePathColumn = {MediaStore.Images.Media.DATA};
    Cursor cursor = getContext().getContentResolver().query(contentUri, filePathColumn, null, null, null);
    if(cursor.moveToFirst()){
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        thePath = cursor.getString(columnIndex);
    }
    cursor.close();

    if(thePath == null){
        return getImagePathExternal(contentUri);
    }else {
        return thePath;
    }
}

public String getImagePathExternal(Uri uri){
    Cursor cursor = getContext().getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String document_id = cursor.getString(0);
    document_id = document_id.substring(document_id.lastIndexOf(":")+1);
    cursor.close();

    cursor = getContext().getContentResolver().query(
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();

    if(path == null){

        System.err.println("****************trying bytes route******************");
        try{

            InputStream in = getContext().getContentResolver().openInputStream(uri);

            byte[] resultBuff = new byte[0];
            byte[] buff = new byte[1024];
            int k ;
            while((k = in.read(buff, 0, buff.length)) > -1) {
                byte[] tbuff = new byte[resultBuff.length + k]; // temp buffer size = bytes already read + bytes last read
                System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); // copy previous bytes
                System.arraycopy(buff, 0, tbuff, resultBuff.length, k);  // copy current lot
                resultBuff = tbuff; // call the temp buffer as your result buff
            }

            System.err.println("****************bytes read: "+resultBuff.length+" ******************");

            File tem = new File(_tempImageDir, "temp.jpg");

            FileOutputStream out = new FileOutputStream(tem);

            out.write(resultBuff, 0, resultBuff.length);

            return tem.getAbsolutePath();

        }catch(Exception e){
            e.printStackTrace();
            return null;
        }

    }

    return path;
}

Logcat(this exception never changes, no matter which approach I use):

E/AndroidRuntime: FATAL EXCEPTION: main
                                                                  Process: com.venon.nakomangsp, PID: 20610
                                                                  java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=132074, result=-1, data=Intent { dat=content://media/external/images/media/4147 (has extras) }} to activity {com.venon.nakomangsp/com.venon.nakomangsp.SignUpActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
                                                                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4058)
                                                                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101)
                                                                      at android.app.ActivityThread.access$1400(ActivityThread.java:177)
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497)
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                      at android.os.Looper.loop(Looper.java:145)
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5942)
                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                      at java.lang.reflect.Method.invoke(Method.java:372)
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
                                                                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
                                                                      at id.zelory.compressor.ImageUtil.getScaledBitmap(ImageUtil.java:62)
                                                                      at id.zelory.compressor.ImageUtil.compressImage(ImageUtil.java:161)
                                                                      at id.zelory.compressor.Compressor.compressToFile(Compressor.java:48)
                                                                      at com.venon.nakomangsp.SignUpFragment.preparePicture(SignUpFragment.java:870)
                                                                      at com.venon.nakomangsp.SignUpFragment.onActivityResult(SignUpFragment.java:783)
                                                                      at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:165)
                                                                      at com.venon.nakomangsp.SignUpActivity.onActivityResult(SignUpActivity.java:37)
                                                                      at android.app.Activity.dispatchActivityResult(Activity.java:6549)
                                                                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4054)
                                                                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101) 
                                                                      at android.app.ActivityThread.access$1400(ActivityThread.java:177) 
                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497) 
                                                                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                      at android.os.Looper.loop(Looper.java:145) 
                                                                      at android.app.ActivityThread.main(ActivityThread.java:5942) 
                                                                      at java.lang.reflect.Method.invoke(Native Method) 
                                                                      at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

Solution

  • Apps do not have direct file access to any of the contents of the SD card. Therefore even if you could get a 'path' of some sort, your app would not have the ability to read anything from that location.

    The only way to reliably access the contents of these files is through ContentResolver.openInputStream() (or the other open methods if you need an AssetFileDescriptor, etc).

    You can most definitely copy the file to your own cache directory and then do whatever you want with the image.