DMS
DMS

Reputation: 3

NullPointerException when getting image from internal storage in Android

I am developing a student registration app on Android following a tutorial. I need to create a new student getting a photo saved on the phone.

The problem is I can`t load the image from the URI retrieved.

My "Script" log prints:

Img uri: content://com.android.providers.media.documents/document/image%3A30

But my imgString is null.

I am using genymotion emulator by the way.

Here is the code for calling the gallery...

public void loadImage(View view){
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    startActivityForResult(intent, IMG_SDCARD_ACTIVITY);
}

And this is the onActivityResult for handling the answer from gallery...

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        File file;
        String pass = null;
        Log.i("Script", "RequestCode: "+requestCode+" ResultCode: "+resultCode);
        if(requestCode == IMG_SDCARD_ACTIVITY && resultCode == Activity.RESULT_OK){
            try{
                Uri img = data.getData();
                Log.i("Script", "Img uri: "+img.toString());
                String[] cols = {MediaStore.Images.Media.DATA};
                Cursor cursor = getContentResolver().query(img, cols, null, null, null);
                cursor.moveToFirst();

                int indexCol = cursor.getColumnIndex(cols[0]);
                String imgString = cursor.getString(indexCol);
                cursor.close();

                file = new File(imgString); //this is the line 108 where the problem is...
                ivImg.setImageBitmap(ImageUtil.setPic(Uri.fromFile(file), 100, 100));
                ivImg.setContentDescription(file.getPath());
                pass = "passou";
            }
            catch (NullPointerException e){e.printStackTrace();}
            catch (Exception e){e.printStackTrace();}
            finally {
                if(pass==null){
                    ivImg.setImageResource(R.drawable.person);
                    Toast.makeText(SalvarAlunoActivity.this, "Fail! Try again.", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

And this is the ImageUtil class...

public class ImageUtil {
    public static Bitmap setPic(Uri uriFile, int width, int height){
        //Get the dimensions of the view
        int targetW = width;
        int targetH = height;

        //Get the dimensions of the Bitmap
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;

        //Determine how much to scale down the image
        int scaleFactor = Math.min(photoW/targetW, photoH/targetH);

        //Decode the image file into a Bitmap sized to fill the View
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        Bitmap bitmap = BitmapFactory.decodeFile(uriFile.getPath(), bmOptions);
        return(bitmap);
}

}

The log prints also this error...

10-28 08:19:45.602  10874-10874/? W/System.err﹕ java.lang.NullPointerException
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at java.io.File.fixSlashes(File.java:185)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at java.io.File.<init>(File.java:134)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at com.XXXX.contentProvider.SalvarAlunoActivity.onActivityResult(SalvarAlunoActivity.java:108)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.Activity.dispatchActivityResult(Activity.java:5423)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.ActivityThread.access$1300(ActivityThread.java:135)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.os.Looper.loop(Looper.java:136)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5001)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:515)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-28 08:19:45.606  10874-10874/? W/System.err﹕ at dalvik.system.NativeStart.main(Native Method)

It`s my first time here. Let me know if I need to put more information.

Thanks in advance.

Upvotes: 0

Views: 1269

Answers (3)

CharlieTap
CharlieTap

Reputation: 136

I think the answer above covers the error your experiencing pretty well however as a rule of thumb you should never assume cursor.moveToFirst() will work, rather wrap it in an if as it returns a boolean.

if(cursor.moveToFirst())
{
    //Do something here
}

Upvotes: 0

Zubair Ahmed
Zubair Ahmed

Reputation: 2897

Your file path is null. While selecting picture from Gallery you can directly get Bitmap from uri. So in your onActivityResult method do something like:

Uri fileUri = data.getData();
Bitmap b = decodeUri(fileUri);
your_image_view.setImageBitmap(b); 


// here decodeUri method will directly return you Bitmap which can be set to imageview

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException 
    {
        BitmapFactory.Options o = new BitmapFactory.Options();

        o.inJustDecodeBounds = true;

        BitmapFactory.decodeStream(getContentResolver()
                .openInputStream(selectedImage), null, o);

        final int REQUIRED_SIZE = 72;

        int width_tmp = o.outWidth, height_tmp = o.outHeight;

        int scale = 1;

        while (true) 
        {
            if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) 
            {
                break;
            }
            width_tmp /= 2;

            height_tmp /= 2;

            scale *= 2;
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();

        o2.inSampleSize = scale;

        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver()
                .openInputStream(selectedImage), null, o2);

        return bitmap;
    }

EDIT:

For Uri explanation see @CommonsWare answer. Also he mentioned about Picasso which is very usefull library for android to load images efficiently in android.

Upvotes: 1

CommonsWare
CommonsWare

Reputation: 1006539

A Uri is not a file. The Uri you get back from your ACTION_GET_CONTENT request does not have to point to a file, let alone a file that you can access yourself on the filesystem. Also, the Uri that you get back from your ACTION_GET_CONTENT request does not have to be one from the MediaStore, and the MediaStore does not have to return a DATA value in any case.

I have no idea what ImageUtil.setPic() does, but if it takes a Uri as input, pass in the actual Uri that you get back in onActivityResult(). setPic() hopefully uses a ContentResolver and openInputStream() under the covers.

Even better is to use an image-loading library, like Picasso or Universal Image Loader, so all that disk I/O and bitmap decoding can be done on a background thread.

Upvotes: 1

Related Questions