You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android开发:相册选图复制到指定文件夹出现0字节问题求助

解决相册选图复制后文件0字节的问题

嗨,作为Android新手遇到这种问题很正常,别着急!我帮你分析下代码里的几个关键问题,以及怎么修复:

问题1:MediaStore.Images.Media.DATA字段已废弃(Android 10+)

从Android 10开始,系统限制了直接访问文件路径,MediaStore.Images.Media.DATA返回的路径可能无效或者没有权限,这会导致BitmapFactory.decodeFile(selectedImagePath)返回null,最终写入空文件。

问题2:setReducedImageSize方法误用

你调用setReducedImageSize()时,这个方法里用的是mImageFileLocation(也就是你刚创建的空文件路径),而不是选中图片的路径。这时候BitmapFactory.decodeFile(mImageFileLocation)根本读不到有效内容,等于白做了缩放操作,而且后续写入的bitmap如果是之前无效的,自然就是0字节。

问题3:不必要的Bitmap转换(可选优化)

把图片转成Bitmap再写入文件不仅会损耗质量,还可能因为内存问题导致失败,直接复制文件流更高效可靠。


修复后的代码示例

我帮你重新整理了相册选图的处理逻辑,同时兼容Android 10+:

1. 修改onActivityResult中的相册处理部分

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data); // 别忘加这句!
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case GALLERY_REQUEST_CODE:
                Uri selectedImage = data.getData();
                if (selectedImage == null) {
                    Log.e(TAG, "选中的图片Uri为空");
                    return;
                }
                try {
                    // 创建目标文件
                    File targetFile = createImageFile();
                    // 直接复制输入流到目标文件,避免Bitmap转换
                    copyStreamToFile(getContentResolver().openInputStream(selectedImage), targetFile);
                    // 如果需要缩放并显示图片,再处理Bitmap
                    Bitmap reducedBitmap = getReducedBitmapFromUri(selectedImage, mCapturedImageView.getWidth(), mCapturedImageView.getHeight());
                    mCapturedImageView.setImageBitmap(reducedBitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case CAMERA_REQUEST_CODE:
                setReducedImageSize();
                break;
        }
    }
}

2. 添加文件流复制方法

private void copyStreamToFile(InputStream inputStream, File outputFile) throws IOException {
    try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
        byte[] buffer = new byte[4096];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
    } finally {
        inputStream.close();
    }
}

3. 新增从Uri获取缩放Bitmap的方法(替代原来的setReducedImageSize

private Bitmap getReducedBitmapFromUri(Uri imageUri, int targetWidth, int targetHeight) throws IOException {
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;
    // 先读取图片尺寸,不加载Bitmap到内存
    InputStream inputStream = getContentResolver().openInputStream(imageUri);
    BitmapFactory.decodeStream(inputStream, null, bmOptions);
    inputStream.close();

    int imageWidth = bmOptions.outWidth;
    int imageHeight = bmOptions.outHeight;
    int scaleFactor = Math.min(imageWidth / targetWidth, imageHeight / targetHeight);
    scaleFactor = Math.max(scaleFactor, 1); // 确保缩放因子至少为1,避免放大图片

    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    // 加载并返回缩放后的Bitmap
    inputStream = getContentResolver().openInputStream(imageUri);
    Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, bmOptions);
    inputStream.close();
    return bitmap;
}

4. 保留原有的createImageFile方法(没问题)

private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "EMPL_" + timeStamp + "_";
    File image = File.createTempFile(imageFileName, ".jpg", mGalleryFolder);
    mImageFileLocation = image.getAbsolutePath();
    return image;
}

关键修复点说明

  • ContentResolver.openInputStream()直接读取选中图片的内容,避免依赖废弃的文件路径字段,兼容Android 10+的存储权限规则。
  • 直接复制文件流的方式更高效,不会出现Bitmap为空导致的0字节问题。
  • 重构了缩放逻辑,从Uri直接处理,不用依赖全局变量mImageFileLocation,避免逻辑混乱。

如果还有问题,比如权限申请(Android 13+需要READ_MEDIA_IMAGES权限),记得在Manifest里添加权限并动态申请哦!

内容的提问来源于stack exchange,提问作者Joris van Laar

火山引擎 最新活动