【问题标题】:NullPointerException in MediaStore insertImage function in Firebase CrashlyticsFirebase Crashlytics 中 MediaStore insertImage 函数中的 NullPointerException
【发布时间】:2020-11-30 05:08:38
【问题描述】:

我有一个在 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 日志说:

致命异常:java.lang.NullPointerException:url 在 com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:133) 在 android.content.ContentResolver.delete(ContentResolver.java:1951) 在 android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:1794) 在 com.xxxx.yyy.dialogs.SharePostDialog.createAndShareImage(SharePostDialog.java:121) 在 com.xxxx.yyy.dialogs.SharePostDialog.onClick(SharePostDialog.java:99)

这发生在 RedMi Note Android 10 设备中(至少在我的测试设备 Android 8 和 Android 11 中这是不可重现的)。我无法理解问题的任何可能原因。什么以及它如何变得 null ?以及如何解决?

【问题讨论】:

    标签: android firebase mediastore


    【解决方案1】:

    看看documentation

    此方法在 API 级别 29 中已弃用。 应使用 MediaColumns#IS_PENDING 插入图像,它可以更丰富地控制生命周期。

    对于29>你必须使用ContentValuesContentResolver,如下图:

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

    【讨论】:

    • 感谢您的回复。我想您指的是 resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, valuesvideos);我已经尝试过此代码,但仅在此行中出现以下错误... java.lang.IllegalArgumentException: Primary directory Images not allowed for content://media/external/images/media;允许的目录是 [DCIM, Pictures]
    • 所以我尝试将相对路径设置为“图片/”,它正在插入图像。但我现在有一个新问题。共享时我无法访问此图像。它给出了一个错误“原因:java.lang.IllegalStateException:只有所有者才能与待处理的项目内容交互:​​//media/external/images/media/36”
    • 谢谢,它在 1 台设备上工作。让我在更多设备上进行测试,然后再更新。
    猜你喜欢
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    • 2019-03-27
    相关资源
    最近更新 更多