web-dev-qa-db-ja.com

Java.lang.NullPointerExceptionが原因:nullオブジェクト参照で仮想メソッド「int Android.graphics.Bitmap.getWidth()」を呼び出そうとしました

私はBitmapScalingHelper.Javaを持っています:

public class BitmapScalingHelper
{
    public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight)
    {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        options.inJustDecodeBounds = false;

        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                dstHeight);

        Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);

        return unscaledBitmap;
    }

    public static Bitmap decodeFile(String filePath, int dstWidth, int dstHeight)
    {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        options.inJustDecodeBounds = false;
        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                dstHeight);

        Bitmap unscaledBitmap = BitmapFactory.decodeFile(filePath, options);

        return unscaledBitmap;
    }


    public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight)
    {
        final float srcAspect = (float)srcWidth / (float)srcHeight;
        final float dstAspect = (float)dstWidth / (float)dstHeight;

        if (srcAspect > dstAspect)
        {
            return srcWidth / dstWidth;
        }
        else
        {
            return srcHeight / dstHeight;
        }
    }

    public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight)
    {
        Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight());

        Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
                dstWidth, dstHeight);

        Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
                Config.ARGB_8888);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));

        return scaledBitmap;
    }

    public static Rect calculateSrcRect(int srcWidth, int srcHeight)
    {
        System.out.print("Scr" + srcWidth + " " + srcHeight);
        return new Rect(0, 0, srcWidth, srcHeight);
    }

    public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight)
    {
        final float srcAspect = (float)srcWidth / (float)srcHeight;
        final float dstAspect = (float)dstWidth / (float)dstHeight;

        if (srcAspect > dstAspect)
        {
            return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
        }
        else
        {
            return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
        }
    }
}

このクラスには次のものがあります。

createScaledBitmap()

...これは、スケーリングされたビットマップ画像を返します。

別のクラスには、このメソッドがあります:

public Bitmap readSelectedBitmapFromFile(Context context, String fileName)
    {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getMetrics(metrics);

        Bitmap scaledBitmap = getDefaultBitmap(context);

        try {
            File themeParentDir = context.getDir(THEME_DIRECTORY_NAME, Context.MODE_PRIVATE); //Creating an internal dir;
            File themeSubDir = new File(themeParentDir, THEME_SUB_DIRECTORY_NAME + getThemeBasedDirectoryNumber(m_SelectedTheme));
            themeSubDir.mkdir();

            File themeFileWithinDir = new File(themeSubDir, fileName); //Getting a file within the dir.

            if(themeFileWithinDir.exists())
            {
                // Part 1: Decode image
                Bitmap unscaledBitmap = BitmapScalingHelper.decodeFile(themeFileWithinDir.getPath(), metrics.widthPixels, metrics.heightPixels);

                // Part 2: Scale image
                scaledBitmap = BitmapScalingHelper.createScaledBitmap(unscaledBitmap, metrics.widthPixels, metrics.heightPixels);
                unscaledBitmap.recycle();
            }

            m_SelectedBitmap = scaledBitmap;

        }
        catch (Error e) {
            e.printStackTrace();
        }

        return scaledBitmap;
    }

このコードは、多くのデバイスで正常に機能していました。しかし、一部のデバイスではクラッシュしていました。誰でも助けてくれますか?

私はこのようなログを取得しています:

Fatal Exception: Java.lang.RuntimeException: Unable to start activity ComponentInfo: Java.lang.NullPointerException: Attempt to invoke virtual method 'int Android.graphics.Bitmap.getWidth()' on a null object reference
       at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:3254)
       at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:3350)
       at Android.app.ActivityThread.access$1100(ActivityThread.Java:222)
       at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1795)
       at Android.os.Handler.dispatchMessage(Handler.Java:102)
       at Android.os.Looper.loop(Looper.Java:158)
       at Android.app.ActivityThread.main(ActivityThread.Java:7229)
       at Java.lang.reflect.Method.invoke(Method.Java)
       at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1230)
       at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1120)
Caused by Java.lang.NullPointerException: Attempt to invoke virtual method 'int Android.graphics.Bitmap.getWidth()' on a null object reference
       at in.plackal.lovecyclesfree.util.BitmapScalingHelper.createScaledBitmap(SourceFile:62)
       at in.plackal.lovecyclesfree.general.ThemeManager.readSelectedBitmapFromFile(SourceFile:202)
       at in.plackal.lovecyclesfree.activity.SplashActivity.onCreate(SourceFile:70)
       at Android.app.Activity.performCreate(Activity.Java:6876)
       at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1135)
       at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:3207)
       at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:3350)
       at Android.app.ActivityThread.access$1100(ActivityThread.Java:222)
       at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1795)
       at Android.os.Handler.dispatchMessage(Handler.Java:102)
       at Android.os.Looper.loop(Looper.Java:158)
       at Android.app.ActivityThread.main(ActivityThread.Java:7229)
       at Java.lang.reflect.Method.invoke(Method.Java)
       at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1230)
       at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:1120)

権限の問題である場合、Android-Mバージョン以下でクラッシュすることはありませんが、一部のAndroid-M以前のデバイスでもクラッシュします。

16
Pavan Bilagi

あなたが直面している問題は、unscaledBitmap関数のcreateScaledBitmapgetWidth()しようとしていることです。明らかに、あなたのunscaledBitmapは時々nullです; getWidth()を呼び出すと、Null Pointer例外が発生します。

根本的な原因は、decodeResourceが何らかの理由でnullを返していることです。

理由には次のものがあります-

  1. 読み取り許可なし
  2. 画像ファイルが破損しています
  3. ファイルをデコードするのに十分なメモリがありません
  4. リソースが存在しません
  5. Options変数に無効なオプションが指定されています。

デコードされたビットマップにヌルチェックを含めるようにコードを変更し、ログに記録して、エラーが発生した特定のデバイスでデバッグすることをお勧めします。

再使用しているオプション変数は、decodeResourceの2回目の呼び出しで異なる解釈をされている可能性もあります。そこでnullを渡してみてください。

変更されたコードは次のようになります-

public class BitmapScalingHelper
{
    public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight)
    {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        options.inJustDecodeBounds = false;

        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                dstHeight);

        options = new Options(); 
        //May use null here as well. The funciton may interpret the pre-used options variable in ways hard to tell.
        Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);

        if(unscaledBitmap == null)
        {
            Log.e("ERR","Failed to decode resource - " + resId + " " + res.toString());
            return null;
        }

        return unscaledBitmap;
    }
}
10
neur0tic

使用している:Bitmap decodeFile (String pathName)このメソッドは、ファイルのデコードが失敗した場合にnullを返すことがあります。何らかのデバイスでの許可の問題、またはサポートされていない画像形式に関係していると思います。 GIFを使用している場合は、 https://developer.Android.com/reference/Android/graphics/Movie.html を試してください。

0
Anis BEN NSIR

エラーの原因にはいくつかの理由があります。

  1. AndroidManifest.xmlの許可の欠如。読み取りまたは書き込み許可。
  2. ファイルが存在しないか、ビットマップとしてデコードできないファイルにアクセスしようとしています。

あなたが投稿したコードから、私は論理エラーを見つけることができません。ここに私の提案があります:

  1. 別の画像を変更してテストします。

  2. GlideやFrescoなどのImageLoaderライブラリを使用してテストしてください。

0
orzangleli