使用BitmapFactory和文件路径显示ImageView,返回NullPointerException

时间:2014-10-11 22:51:12

标签: android bitmap imageview bitmapfactory

更新2:问题与onResumeonPause有关。它与BitmapFactory.decodeFile()无关。问题是,当我去拍照时,onPause被调用,但没有任何内容保存到SharedPreferences,因为还没有任何东西可以保存。但是一旦我从拍照中返回,就会调用onResume并尝试通过从SharedPreferences获取适当的值来将图像路径设置为自定义对象。由于那里没有相应的值,因此它将默认值null应用于imagePath

更新:我的计划的布局是ActivityA个主机FragmentA,其中包含您在下面看到的DialogFragment。用户按下FragmentA中的按钮拍照,一旦他们拍照,在onActivityResult中我将图像路径设置为自定义对象中的字符串变量,并通过以下方式验证它是否存在致电Log.d(mObject.getImagePath(), ...)

然后他们可以重新按相同的图片按钮来查看图像。这是NullPointerException发生的地方。虽然我验证了onActivityResult中的图像路径,但是当我尝试访问它时它会返回null。这就是BitmapFactory.decodeFile()返回null的原因 - imagePath中的FragmentA为空,当我尝试在DialogFragment中将其作为额外访问时,它将为null。

任何人都可以看到为什么图像路径返回null,即使我在onActivityResult中验证它并将其分配给我的对象?我不知道为什么会这样。我有一个类似的按钮,用户可以在其中输入文本,然后再次按下按钮以在对话框中查看/编辑该文本。我遵循将变量分配给onActivityResult中的对象的相同过程,我没有问题。

注意:如果您想了解如何拍摄和保存照片,请参阅this答案,或按照右侧的链接问题进行操作。

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();
}

}

这将返回NullPointerException,并且从我在BitmapFactory上的读数中,它或者是因为文件名为null或者无法解码为位图。

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

显示对话框,但它只是一个带有OK按钮的空框。

我读过类似的问题,问题是ImageView本身是空的。我认为这不是问题,但下面是XML dialog_input_image。我已经尝试过修改XML了,我已经ImageView作为FrameLayout的孩子,类似于我见过的其他例子,但我得到了同样的错误。

<?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>

我是Android的新手,所以我不确定我哪里出错了。感谢任何帮助,谢谢!

3 个答案:

答案 0 :(得分:1)

问题与BitmapFactory.decodeFile()无关。

问题在于,当用户去拍照时,会调用onPause。它会检查是否存在现有图像路径,如果存在,则将其保存到SharedPreferences。用户第一次打开应用程序时,不会存在任何图像路径,因此不会保存任何内容。拍摄照片后,系统会调用onResume并尝试从SharedPreferences检索图像路径,但最终会分配默认值null,因为不存在图像路径。我一直使用boolean来跟踪何时检索onResume中的信息,但更好的解决方案是在尝试检索之前检查值是否为null

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

假设已经存在图像路径,原始代码将起作用。但它不会第一次运作。

我为这种困惑道歉,并感谢所有试图提供帮助的人。虽然这个问题与你的答案无关(这是我的错),但你的答案仍然有用,我会继续学习它们。

答案 1 :(得分:0)

您最好使用Context方法getFilesDir()从内部存储中读取内容,例如:

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);

答案 2 :(得分:0)

在将Uri更改为位图之前,首先从下面的代码中获取其路径,然后将其设置为

..........
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;
}