pez
pez

Reputation: 4235

Showing ImageView using BitmapFactory and file path, returns NullPointerException

UPDATE2: The problem has to do with onResume and onPause. It has nothing to do with the BitmapFactory.decodeFile(). The problem is that when I go to take the picture, onPause is called, but nothing is saved to SharedPreferences, since there is not yet anything to be saved. But once I return from taking the picture, onResume is called and attempts to set the image path to the custom object by taking the appropriate value from SharedPreferences. Since there is no corresponding value there, it applies the default value of null to imagePath.

UPDATE: The layout of my program is ActivityA hosts FragmentA which hosts this DialogFragment you see below. The user presses a button in FragmentA to take a picture, and once they have taken the picture, in onActivityResult I set the image path as a String variable in a custom object, and I verify it exists by calling Log.d(mObject.getImagePath(), ...).

They can then re-press the same picture button to view the image. This is where the NullPointerException occurs. Although I verify that the image path exists in onActivityResult, it returns null later when I try to access it. This is why the BitmapFactory.decodeFile() returns null- since imagePath is null in FragmentA, of course it will be null when I try to access it as an extra in DialogFragment.

Can anyone see why the image path is returning null, even when I verify it exists in onActivityResult and assign it to my object? I have no idea why this happens. I have a similar button where a user can input text, and then press the button again to view/edit that text in a dialog. I follow the same procedure of assigning the variable to my object in onActivityResult, and I have no problems.

NOTE: If you would like to see how the picture is taken and saved, please refer to this answer, or follow the linked question to the right.

imagePath:

/data/data/myPackageName/files/myInternalPicturesDir/IMG_20141011_152840.jpg.

FragmentA:

    //onCreateView
    mImageButton = (Button) v.findViewById(R.id.imageButton);
    mImageButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isImageButtonFirstClick)
            {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                imageUri = CameraUtils.getOutputMediaFileUri(CameraUtils.MEDIA_TYPE_IMAGE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intent, REQUEST_IMAGE);
            }
            else
            {
                try
                {
                    Log.d("mImageButton onClick", mMyObject.getImagePath());
                    //returns null...
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }

                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputImageFragment dialog = InputImageFragment.newInstance(mMyObject.getImagePath());
                dialog.show(fm, DIALOG_IMAGE);
            }
        }
    });

...

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (resultCode != Activity.RESULT_OK)
    {
        return;
    }
    ...
    else if (requestCode == REQUEST_IMAGE)
    {
        String pathToInternallyStoredImage = CameraUtils.saveToInternalStorage(getActivity(), imageUri);
        mMyObject.setImagePath(pathToInternallyStoredImage);

        //verify imagePath exists, both return correct path
        Log.d("onActivityResult pathToInternallyStoredImage", pathToInternallyStoredImage);
        Log.d("onActivityResult mMyObject.getImagePath", mMyObject.getImagePath());

        isImageButtonFirstClick = false;
        preferences.edit().putBoolean("isImageButtonFirstClick", isImageButtonFirstClick).commit();
    }

DialogFragment:

public static InputImageFragment newInstance(String imagePath)
{
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_IMAGEPATH, imagePath);

    InputImageFragment fragment = new InputImageFragment();
    fragment.setArguments(args);

    return fragment;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    String imagePath = (String) getArguments.getSerializable(EXTRA_IMAGEPATH);

    try
    {
        Log.d("onCreateDialog imagePath", imagePath);
        //returns null...
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_input_image, null);

    final ImageView imageView = (ImageView) v.findViewById(R.id.dialogInputImageView);
    Bitmap image = BitmapFactory.decodeFile(imagePath);
    imageView.setImageBitmap(image);

    return new AlertDialog.Builder(getActivity())
            .setView(v)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int whichButton)
                {
                    dialog.cancel();
                }
            })
            .create();
}

}

This returns a NullPointerException, and from my reading on BitmapFactory, it's either because the file name is null or cannot be decoded into a bitmap.

10-13 17:10:39.498 5330-5330/myPackageName E/BitmapFactory﹕ Unable to decode stream: java.lang.NullPointerException

The dialog is shown, but it is just an empty box with anOK button.

I've read of similar problems, where the issue was that the ImageView itself was null. I don't think this is the problem here, but below is the XML dialog_input_image. I've tried tinkering around with the XML, and I've had the ImageView as the child of a FrameLayout similar to other examples I've seen, but I get the same error.

<?xml version="1.0" encoding="utf-8"?>

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialogInputImageView"
    android:orientation="vertical"
    android:scaleType="centerInside"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
</ImageView>

I'm new to Android so I'm not sure where I'm going wrong. Any help appreciated, thanks!

Upvotes: 0

Views: 1262

Answers (3)

pez
pez

Reputation: 4235

The problem had nothing to do with BitmapFactory.decodeFile().

The problem was that when the user goes to take the picture, onPause is called. It checks if there is an existing image path, and if so, saves it to SharedPreferences. The first time the user opens the app, no image path will exist so nothing is saved. After the picture is taken, onResume is called and attempts to retreive an image path from SharedPreferences, but ended up assigning the default value of null since no image path existed. I had been using a boolean to keep track of when to retreive the information in onResume, but a much better solution was simply to check if the value was null before attempting to retrieve it.

    if (preferences.getString("imagePath", null) != null)
    {
        myObject.setImagePath(preferences.getString("imagePath", null));
    }

The original code would have worked, assuming an image path already existed. But it wouldn't have worked the first time.

I apologize for the confusion, and thank you to everyone who tried to help. Although the problem was something unrelated to your answers (and that was my fault), your answers were still helpful and I will implement them as I continue to learn.

Upvotes: 1

Avinash Kumar Pankaj
Avinash Kumar Pankaj

Reputation: 1720

Before changing your Uri to bitmap first get its path from code below and then set it

..........
Bitmap image = BitmapFactory.decodeFile(getRealPathFromURI(URI));
}

public String getRealPathFromURI(Uri contentURI) throws Exception {
    String result;
    Cursor cursor = context.getContentResolver().query(contentURI, null,
            null, null, null);
    if (cursor == null) { 
        result = contentURI.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor
                .getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

Upvotes: 0

ToYonos
ToYonos

Reputation: 16833

You'd better use the Context method getFilesDir() to read from your internal storage, like :

String image path = getFilesDir() .getAbsolutePath(); + "/myInternalPicturesDir/IMG_20141011_152840.jpg";
final ImageView imageView = (ImageView) v.findViewById(R.id.dialogInputImageView);
Bitmap image = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(image);

Upvotes: 0

Related Questions