【问题标题】:BitmapFactory.decodeFile returning null on certain devicesBitmapFactory.decodeFile 在某些设备上返回 null
【发布时间】:2017-02-11 11:29:14
【问题描述】:

我一直在尝试捕获图像并调整其大小(以显示它)并存储其 base64 值。

private String setImageAndReturnBase64String(ImageView imageView) {

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
    bitmap = Bitmap.createScaledBitmap(bitmap, 400, 400, false);
    imageView.setImageBitmap(bitmap);

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 40, byteArrayOutputStream);
    byte[] byteArray = byteArrayOutputStream.toByteArray();

    return Base64.encodeToString(byteArray, Base64.DEFAULT);
}

mCurrentPhotoPath 在哪里

String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPG_" + timeStamp + "_";
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    mCurrentPhotoPath = image.getAbsolutePath();

storageDir

File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    if (!(storageDir != null && storageDir.exists())) {
        if (storageDir != null) {
            storageDir.mkdir();
        }
    }

具有所有必要的权限和清单中的文件提供程序。

但在某些设备中,BitmapFactory.decodeFile(mCurrentPhotoPath); 返回 null 会导致运行时异常。

来自 FireBase 的堆栈跟踪:

android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618)
arrow_drop_down
Caused by java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=null} to activity {com.app.in/com.app.activities.JobCard}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
android.app.ActivityThread.deliverResults (ActivityThread.java:3720)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:3107)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618)
arrow_drop_down
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
android.graphics.Bitmap.createScaledBitmap (Bitmap.java:636))
android.app.Activity.dispatchActivityResult (Activity.java:6442)
android.app.ActivityThread.deliverResults (ActivityThread.java:3716)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:3107)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618) 

如何防止此运行时异常在某些设备上发生?

编辑:实施 cmets 中建议的方法后,这就是我一直面临的问题。

Exception java.lang.RuntimeException: Unable to resume activity {com.app.in/com.app.activities.Detailed}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:0, request=0, result=-1, data=null} to activity {com.app.in/com.app.activities.Detailed}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
android.app.ActivityThread.performResumeActivity (ActivityThread.java:3121)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618)

Caused by java.lang.RuntimeException: Failure delivering result ResultInfo{who=android:fragment:0, request=0, result=-1, data=null} to activity {com.app.in/com.app.activities.Detailed}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
android.app.ActivityThread.deliverResults (ActivityThread.java:3720)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:3107)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618)

Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
com.app.fragments.ModeDetailsFragment.setImageAndReturnBase64String (ModeDetailsFragment.java:224)
com.app.fragments.ModeDetailsFragment.onActivityResult (ModeDetailsFragment.java:198)
android.app.Activity.dispatchActivityResult (Activity.java:6466)
android.app.ActivityThread.deliverResults (ActivityThread.java:3716)
android.app.ActivityThread.performResumeActivity (ActivityThread.java:3107)
android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3152)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2495)
android.app.ActivityThread.-wrap11 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1354)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5443)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:728)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:618) 

修改方法

private String setImageAndReturnBase64String(ImageView imageView) {

    Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath);
    if(bitmap == null) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, 400, 400);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, options);
    } else {
        bitmap = Bitmap.createScaledBitmap(bitmap, 400, 400, false);
    }
    imageView.setImageBitmap(bitmap);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 40, byteArrayOutputStream);
    byte[] byteArray = byteArrayOutputStream.toByteArray();

    return Base64.encodeToString(byteArray, Base64.DEFAULT);
}

private int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
            inSampleSize *= 2;
        }
    }

    return inSampleSize;
}

【问题讨论】:

  • 我的猜测是你的堆空间用完了。与其读取完整图像,然后将其缩小,不如使用BitmapFactory.OptionsinSampleSize 读取缩小的图像,并使用更少的内存。
  • 免费虚拟机:7.21MB 虚拟机总数:19.58MB 最大虚拟机:96MB 电池电量:71% 制造商:LGE 型号:LG-K420 主板:Msm8916 Android API:22 Android OS:5.1.1 品牌: Lge RAM:1.86GB 这是崩溃期间的设备数据。
  • @CommonsWare 你能调查一下这个问题吗?

标签: android nullpointerexception android-bitmap bitmapfactory


【解决方案1】:

是的 BitmapFactory.decodeFile() 将返回 null 如果 Bitmap 对于可用内存来说太大了。您可以每周在此网站上阅读此“功能”。

尝试使用较小的图像。

【讨论】:

    猜你喜欢
    • 2018-05-03
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    相关资源
    最近更新 更多