由 java.lang.NullPointerException 引起:尝试在空对象引用上调用虚拟方法 'int android.graphics.Bitmap.getWidth()'
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference
我有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);
}
}
}
在这个class中有:
createScaledBitmap()
...其中 returns 缩放位图图像。
在另一个class中,我有这个方法:
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.access00(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.access00(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 之前的设备中也会崩溃。
您正在使用:Bitmap decodeFile (String pathName)
如果文件解码失败,此方法可能 return null。
我认为这可能与某些设备上的权限问题或不支持的图像格式有关。
如果您使用的是 GIF,请尝试 https://developer.android.com/reference/android/graphics/Movie.html
有一些原因可能会导致错误。
- AndroidManifest.xml 中缺少权限。读取或写入权限。
- 文件不存在或您正在尝试访问无法解码为位图的文件。
从你的代码中post,我找不到任何逻辑error.Here是我的建议:
换一张图片试试
尝试使用 Glide 或 Fresco 等 ImageLoader 库并进行测试。
您面临的问题是您正试图在 createScaledBitmap
函数中 unscaledBitmap
上 getWidth()
。显然,您的 unscaledBitmap
有时是 null
;并且调用 getWidth()
导致空指针异常。
根本原因是 decodeResource
出于某种原因向您返回 null。
原因可能包括 -
- 没有读取权限
- 图像文件已损坏
- 没有足够的内存来解码文件
- 资源不存在
- 选项变量中指定的选项无效。
我建议您修改您的代码以包括对解码位图的空检查,记录它并从那里在您看到错误发生的特定设备上进行调试。
也可能是您重复使用的选项变量在第二次调用 decodeResource
时被不同地解释。您可以尝试在那里传递 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;
}
}
如果您使用创建不当的库 jar,并且在 gradle 上将 minifyEnabled 设置为 true,也可能导致此错误。
简单回答:
按照以下步骤..
- 长按已安装的APP图标
- 转到“应用程序信息”部分。
- 现在点击应用权限部分
- 启用存储权限
现在可以正常工作了
好吧,我反复遇到这个错误,我解决这个问题的方法是确保使用 .png 图像作为位图图像并将其保存在 drawable 文件夹中。以前我将它用作矢量资产。
这对我来说很好。
对于 Android 10 ,将此行添加到清单中:
android:requestLegacyExternalStorage="true"
请注意,您还必须添加所需的权限:
READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE
我有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);
}
}
}
在这个class中有:
createScaledBitmap()
...其中 returns 缩放位图图像。
在另一个class中,我有这个方法:
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.access00(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.access00(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 之前的设备中也会崩溃。
您正在使用:Bitmap decodeFile (String pathName)
如果文件解码失败,此方法可能 return null。
我认为这可能与某些设备上的权限问题或不支持的图像格式有关。
如果您使用的是 GIF,请尝试 https://developer.android.com/reference/android/graphics/Movie.html
有一些原因可能会导致错误。
- AndroidManifest.xml 中缺少权限。读取或写入权限。
- 文件不存在或您正在尝试访问无法解码为位图的文件。
从你的代码中post,我找不到任何逻辑error.Here是我的建议:
换一张图片试试
尝试使用 Glide 或 Fresco 等 ImageLoader 库并进行测试。
您面临的问题是您正试图在 createScaledBitmap
函数中 unscaledBitmap
上 getWidth()
。显然,您的 unscaledBitmap
有时是 null
;并且调用 getWidth()
导致空指针异常。
根本原因是 decodeResource
出于某种原因向您返回 null。
原因可能包括 -
- 没有读取权限
- 图像文件已损坏
- 没有足够的内存来解码文件
- 资源不存在
- 选项变量中指定的选项无效。
我建议您修改您的代码以包括对解码位图的空检查,记录它并从那里在您看到错误发生的特定设备上进行调试。
也可能是您重复使用的选项变量在第二次调用 decodeResource
时被不同地解释。您可以尝试在那里传递 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;
}
}
如果您使用创建不当的库 jar,并且在 gradle 上将 minifyEnabled 设置为 true,也可能导致此错误。
简单回答: 按照以下步骤..
- 长按已安装的APP图标
- 转到“应用程序信息”部分。
- 现在点击应用权限部分
- 启用存储权限
现在可以正常工作了
好吧,我反复遇到这个错误,我解决这个问题的方法是确保使用 .png 图像作为位图图像并将其保存在 drawable 文件夹中。以前我将它用作矢量资产。 这对我来说很好。
对于 Android 10 ,将此行添加到清单中:
android:requestLegacyExternalStorage="true"
请注意,您还必须添加所需的权限:
READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE