Android相机拍照返回低质量图片,如何获取高清原图?
解决拍照获取高清原图的方案
这个问题我之前踩过坑!用data.getExtras().get("data")确实只能拿到缩略图——系统为了性能优化,默认只会返回小尺寸预览图,想要高清原图,核心是让相机直接把原图保存到你指定的路径,而不是依赖Intent返回的缩略图。下面是适配大部分Android版本的完整解决方案:
1. 先准备原图的存储路径
首先要创建一个安全的文件路径来存放拍照后的原图,推荐用公共图片目录或应用私有目录,这里以公共目录为例(注意权限适配):
// 获取系统公共图片目录 File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); // 创建自定义子目录,方便区分你的App图片 File appCameraDir = new File(storageDir, "MyCameraAlbum"); if (!appCameraDir.exists()) { appCameraDir.mkdirs(); } // 生成唯一文件名,避免重复 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; // 创建临时文件 File imageFile = null; try { imageFile = File.createTempFile(imageFileName, ".jpg", appCameraDir); } catch (IOException e) { e.printStackTrace(); } // 保存文件路径和Uri,后续要用到(建议把这两个变量设为Fragment的成员变量) String photoAbsolutePath = imageFile.getAbsolutePath(); // Android7.0及以上必须用FileProvider获取Uri,避免FileUriExposedException Uri photoUri = FileProvider.getUriForFile(getContext(), "com.your.package.name.fileprovider", imageFile);
注意:Android7.0+需要配置
FileProvider,步骤见文末注意事项。
2. 修改拍照Intent,指定原图保存位置
把原来的拍照Intent修改为指定MediaStore.EXTRA_OUTPUT,告诉相机把原图直接存到我们刚才创建的Uri:
img22a1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 先检查有没有相机App能处理这个Intent if (takePhotoIntent.resolveActivity(getContext().getPackageManager()) != null) { // 传入我们准备好的Uri,让相机把原图存在这里 takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri); startActivityForResult(takePhotoIntent, CAMERA_01); } } });
3. 在onActivityResult中读取原图
现在data.getExtras()不会返回图片数据了,我们直接从之前保存的文件路径读取高清原图:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == CAMERA_01) { if (resultCode == Activity.RESULT_OK) { // 从指定路径读取原图Bitmap Bitmap originalBitmap = BitmapFactory.decodeFile(photoAbsolutePath); // 这里继续你原来的Base64转换和全局变量存储逻辑 ByteArrayOutputStream output = new ByteArrayOutputStream(); originalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output); byte[] byte_arr = output.toByteArray(); ((SiteProgress) getActivity().getApplication()).seti22a1(Base64.encodeToString(byte_arr, Base64.DEFAULT)); // 更新ImageView显示原图 BitmapDrawable ob = new BitmapDrawable(getResources(), originalBitmap); img22a1.setBackgroundDrawable(ob); } else if (resultCode == Activity.RESULT_CANCELED) { // 用户取消拍照的处理逻辑 } } }
4. 优化保存到相册的代码
原来的保存方式在高版本Android可能出现权限问题,推荐用MediaStore插入图片,确保系统相册能正确识别:
// 假设你已经有decodedString(Base64解码后的字节数组)和namefile(文件名数组) for(int i=0; i < namefile.length; i++){ Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString[i], 0, decodedString[i].length); // 用MediaStore插入图片到系统相册 ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DISPLAY_NAME, namefile[i].getName()); values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); // Android10及以上需要设置RELATIVE_PATH,无需WRITE_EXTERNAL_STORAGE权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyCameraAlbum"); } else { values.put(MediaStore.Images.Media.DATA, namefile[i].getAbsolutePath()); } ContentResolver resolver = getActivity().getContentResolver(); Uri insertUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); if (insertUri != null) { try (OutputStream outputStream = resolver.openOutputStream(insertUri)) { bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); } catch (IOException e) { e.printStackTrace(); } } }
关键注意事项
- 权限处理:
- Android6.0+需要动态申请
CAMERA权限;Android10以下还需要WRITE_EXTERNAL_STORAGE权限。 - Android10及以上使用
MediaStore插入图片无需WRITE_EXTERNAL_STORAGE权限。
- Android6.0+需要动态申请
- FileProvider配置:
在AndroidManifest.xml中添加Provider配置:
然后在<provider android:name="androidx.core.content.FileProvider" android:authorities="com.your.package.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>res/xml目录下创建file_paths.xml:<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="public_images" path="Pictures" /> </paths> - 避免内存溢出:如果原图尺寸很大,直接解码可能导致OOM,建议用
BitmapFactory.Options做采样压缩:BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; // 宽高都缩为原来的1/2,根据需求调整 Bitmap compressedBitmap = BitmapFactory.decodeFile(photoAbsolutePath, options);
这样修改后,你就能获取到高清的原图,保存到相册的图片质量也会恢复正常啦!
内容的提问来源于stack exchange,提问作者BrenDonie
相关产品推荐
相关产品推荐

