如何从相机操作初始化代码中获取图片URI并将Bitmap转换为URI存入Firebase
安卓相机/图库选图并适配Firebase存储解决方案
一、现有代码问题说明
你当前的相机调用逻辑只能获取低分辨率的缩略图Bitmap,无法拿到原图URI,不满足后续上传Firebase Storage的清晰度要求,需要调整相机调用逻辑。
二、正确获取相机拍照原图URI
2.1 提前配置FileProvider(适配Android7.0+文件权限)
- 在
res/xml目录下创建file_paths.xml配置文件:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="pictures" path="Pictures/" /> <files-path name="internal_files" path="." /> </paths>
- 在
AndroidManifest.xml的<application>标签内添加provider声明:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
2.2 定义全局拍照URI变量
// 全局保存拍照输出的原图URI private Uri cameraImageUri;
2.3 生成拍照输出路径的URI工具方法
private Uri getCameraOutputUri() { File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File imageFile = new File(storageDir, "profile_" + System.currentTimeMillis() + ".jpg"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", imageFile); } else { return Uri.fromFile(imageFile); } }
2.4 启动相机逻辑
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); cameraImageUri = getCameraOutputUri(); // 指定拍照结果输出到预先定义的URI takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri); // 给目标应用授予URI临时访问权限 takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); activityResultLauncher1.launch(takePictureIntent);
2.5 接收相机返回结果
activityResultLauncher1 = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == RESULT_OK) { // 直接使用预存的cameraImageUri即可,无需从返回数据中解析 profilePic.setImageURI(cameraImageUri); // 可直接用该URI上传Firebase Storage } });
三、Bitmap转URI方案(仅针对必须转换的场景)
如果你的业务场景只有Bitmap对象需要转成URI,使用以下方法:
private Uri bitmapToUri(Bitmap bitmap) { File tempFile = new File(getApplicationContext().getFilesDir(), "temp_img_" + System.currentTimeMillis() + ".png"); try { OutputStream outputStream = new FileOutputStream(tempFile); bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); return null; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".fileprovider", tempFile); } else { return Uri.fromFile(tempFile); } }
四、Firebase Storage上传实现
拿到图片URI后直接上传即可,上传成功后将下载链接存入数据库:
// 替换为你自己的存储路径 StorageReference storageRef = FirebaseStorage.getInstance().getReference() .child("profile_images/" + UUID.randomUUID().toString()); storageRef.putFile(imageUri) .addOnSuccessListener(taskSnapshot -> { // 获取文件下载链接 storageRef.getDownloadUrl().addOnSuccessListener(downloadUri -> { String downloadUrl = downloadUri.toString(); // 在此处将downloadUrl写入Firebase Realtime Database/Firestore即可 }); }) .addOnFailureListener(e -> { // 处理上传失败逻辑 });
五、图库选图补充逻辑
如果需要支持从图库选图,单独注册对应启动器即可:
ActivityResultLauncher<String> galleryLauncher = registerForActivityResult( new ActivityResultContracts.GetContent(), uri -> { if (uri != null) { profilePic.setImageURI(uri); // 直接用返回的uri上传Firebase即可 } } ); // 启动图库时调用 galleryLauncher.launch("image/*");
内容的提问来源于stack exchange,提问作者Terminator
相关产品推荐
相关产品推荐

