Reputation: 4235
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
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
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
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