Firebase Crashlytics 中 MediaStore insertImage 函数中的 NullPointerException
NullPointerException in MediaStore insertImage function in Firebase Crashlytics
我有一个生产应用 运行 在 1000 多台设备上使用。其中一项功能是获取图像视图的位图并通过所有可共享的应用程序共享它。为了实现这一点,我创建了位图并通过 Media Store 将其插入,然后获取 URI 并将其传递到 Share intent。
private void createAndShareImage() {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
String shareMgText;
shareMgText = "Read this post";
shareIntent.putExtra(Intent.EXTRA_TEXT, shareMgText);
String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), ImageUtil.getBitmapFromView(postImageView), "", "");
if (url != null && !url.isEmpty()) {
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else
Toast.makeText(context, "Failed to create shareable image", Toast.LENGTH_LONG).show();
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
}
public static Bitmap getBitmapFromView(View v) {
Bitmap bitmap = null;
try {
if (v.getMeasuredHeight() < IntegerConstants.SCREEN_HEIGHT)
bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
else
bitmap = Bitmap.createBitmap(v.getWidth(), v.getWidth(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
return bitmap;
} catch (Exception e) {
Log.e("ImageUtil", e.getMessage());
}
return bitmap;
}
此代码长期以来一直运行良好,我没有更改此代码。但是突然间,我开始从 Android 10 台设备中崩溃。 Firebase crashlytic 日志说:
Fatal Exception: java.lang.NullPointerException: url
at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:133)
at android.content.ContentResolver.delete(ContentResolver.java:1951)
at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:1794)
at com.xxxx.yyy.dialogs.SharePostDialog.createAndShareImage(SharePostDialog.java:121)
at com.xxxx.yyy.dialogs.SharePostDialog.onClick(SharePostDialog.java:99)
这发生在 RedMi Note Android 10 台设备中(至少在我的测试设备 Android 8 和 Android 11 中,这是不可重现的)。我无法理解问题的任何可能原因。它是什么以及如何变得 null ?以及如何修复它?
看看 documentation:
This method was deprecated in API level 29.
inserting of images should be performed using MediaColumns#IS_PENDING, which offers richer control over lifecycle.
对于29>你必须使用ContentValues
和ContentResolver
,如下图:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
String shareMgText = "Read this post";
shareIntent.putExtra(Intent.EXTRA_TEXT,
shareMgText);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
ContentValues valuesimage = new ContentValues();
valuesimage.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/");
valuesimage.put(MediaStore.Images.Media.TITLE, fileName);
valuesimage.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
valuesimage.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
valuesimage.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
valuesimage.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
valuesimage.put(MediaStore.Images.Media.IS_PENDING, 1);
ContentResolver resolver = getContentResolver();
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
Bitmap savedBitmap = ImageUtil.getBitmapFromView(postImageView).compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
valuesimage.clear();
valuesimage.put(MediaStore.Audio.Media.IS_PENDING, 0);
resolver.update(imageUri, valuesimage, null, null);
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
} else {
String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), ImageUtil.getBitmapFromView(postImageView), "", "");
if (url != null && !url.isEmpty()) {
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
} else {
Toast.makeText(context, "Failed to create shareable image", Toast.LENGTH_LONG).show();
}
}
我有一个生产应用 运行 在 1000 多台设备上使用。其中一项功能是获取图像视图的位图并通过所有可共享的应用程序共享它。为了实现这一点,我创建了位图并通过 Media Store 将其插入,然后获取 URI 并将其传递到 Share intent。
private void createAndShareImage() {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
String shareMgText;
shareMgText = "Read this post";
shareIntent.putExtra(Intent.EXTRA_TEXT, shareMgText);
String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), ImageUtil.getBitmapFromView(postImageView), "", "");
if (url != null && !url.isEmpty()) {
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else
Toast.makeText(context, "Failed to create shareable image", Toast.LENGTH_LONG).show();
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
}
public static Bitmap getBitmapFromView(View v) {
Bitmap bitmap = null;
try {
if (v.getMeasuredHeight() < IntegerConstants.SCREEN_HEIGHT)
bitmap = Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
else
bitmap = Bitmap.createBitmap(v.getWidth(), v.getWidth(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
v.draw(canvas);
return bitmap;
} catch (Exception e) {
Log.e("ImageUtil", e.getMessage());
}
return bitmap;
}
此代码长期以来一直运行良好,我没有更改此代码。但是突然间,我开始从 Android 10 台设备中崩溃。 Firebase crashlytic 日志说:
Fatal Exception: java.lang.NullPointerException: url at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:133) at android.content.ContentResolver.delete(ContentResolver.java:1951) at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:1794) at com.xxxx.yyy.dialogs.SharePostDialog.createAndShareImage(SharePostDialog.java:121) at com.xxxx.yyy.dialogs.SharePostDialog.onClick(SharePostDialog.java:99)
这发生在 RedMi Note Android 10 台设备中(至少在我的测试设备 Android 8 和 Android 11 中,这是不可重现的)。我无法理解问题的任何可能原因。它是什么以及如何变得 null ?以及如何修复它?
看看 documentation:
This method was deprecated in API level 29. inserting of images should be performed using MediaColumns#IS_PENDING, which offers richer control over lifecycle.
对于29>你必须使用ContentValues
和ContentResolver
,如下图:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
String shareMgText = "Read this post";
shareIntent.putExtra(Intent.EXTRA_TEXT,
shareMgText);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
ContentValues valuesimage = new ContentValues();
valuesimage.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/");
valuesimage.put(MediaStore.Images.Media.TITLE, fileName);
valuesimage.put(MediaStore.Images.Media.DISPLAY_NAME, fileName);
valuesimage.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
valuesimage.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
valuesimage.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
valuesimage.put(MediaStore.Images.Media.IS_PENDING, 1);
ContentResolver resolver = getContentResolver();
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OutputStream fos = resolver.openOutputStream(imageUri);
Bitmap savedBitmap = ImageUtil.getBitmapFromView(postImageView).compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
valuesimage.clear();
valuesimage.put(MediaStore.Audio.Media.IS_PENDING, 0);
resolver.update(imageUri, valuesimage, null, null);
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
} else {
String url = MediaStore.Images.Media.insertImage(context.getContentResolver(), ImageUtil.getBitmapFromView(postImageView), "", "");
if (url != null && !url.isEmpty()) {
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(url));
shareIntent.setType("image/*");
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(shareIntent, "Select the app"));
} else {
Toast.makeText(context, "Failed to create shareable image", Toast.LENGTH_LONG).show();
}
}