Android拍照后FilePathUri为空,求Firebase上传整合示例代码
解决Android拍照后FilePathUri为null并上传Firebase的完整方案
首先,你的核心问题在于没有提前为拍摄的图片创建一个实际的存储路径并赋值给FilePathUri,而且当使用MediaStore.ACTION_IMAGE_CAPTURE并通过EXTRA_OUTPUT指定保存路径时,onActivityResult的data参数不会返回图片Uri——图片已经直接保存到你指定的Uri中了,所以data.getData()会返回null。
下面是整合了权限处理、正确拍照路径配置和Firebase上传的完整代码:
1. 权限配置(AndroidManifest.xml)
首先在清单文件中添加必要权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" android:required="true" />
2. Activity完整代码
import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ProgressDialog; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.storage.FirebaseStorage; import com.google.firebase.storage.StorageReference; import com.google.firebase.storage.UploadTask; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class PhotoActivity extends AppCompatActivity { private static final int REQUEST_IMAGE_CAPTURE = 1; private static final int REQUEST_CAMERA_PERMISSION = 200; private String currentPhotoPath; private Uri FilePathUri; private Button ChooseButton, UploadButton; private EditText ImageName; private ImageView SelectImage; private ProgressDialog progressDialog; private StorageReference storageReference; private DatabaseReference databaseReference; private static final String Storage_Path = "All_Images/"; private static final String Database_Path = "All_Images_Database"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_takephoto); // 初始化Firebase实例 storageReference = FirebaseStorage.getInstance().getReference(); databaseReference = FirebaseDatabase.getInstance().getReference(Database_Path); // 绑定视图 ChooseButton = findViewById(R.id.ButtonChooseImage); UploadButton = findViewById(R.id.ButtonUploadImage); ImageName = findViewById(R.id.ImageNameEditText); SelectImage = findViewById(R.id.ShowImageView); progressDialog = new ProgressDialog(PhotoActivity.this); // 拍照按钮点击事件 ChooseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 检查相机权限 if (ContextCompat.checkSelfPermission(PhotoActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(PhotoActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } else { dispatchTakePictureIntent(); } } }); // 上传按钮点击事件 UploadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { UploadImageFileToFirebaseStorage(); } }); } // 创建拍照意图并指定图片保存路径 private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // 确保有相机应用可以处理这个意图 if (takePictureIntent.resolveActivity(getPackageManager()) != null) { // 创建保存图片的文件 File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { // 处理文件创建失败的情况 Toast.makeText(this, "创建图片文件失败", Toast.LENGTH_SHORT).show(); } // 如果文件创建成功,继续 if (photoFile != null) { FilePathUri = FileProvider.getUriForFile(this, "com.yourpackage.name.fileprovider", // 替换成你的FileProvider授权 photoFile); takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, FilePathUri); startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); } } } // 创建存储图片的文件 private File createImageFile() throws IOException { // 创建以时间戳命名的图片文件 String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File image = File.createTempFile( imageFileName, /* 前缀 */ ".jpg", /* 后缀 */ storageDir /* 存储目录 */ ); // 保存文件路径用于后续操作 currentPhotoPath = image.getAbsolutePath(); return image; } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) { // 图片已经保存到FilePathUri指定的路径,直接加载到ImageView Bitmap bitmap = BitmapFactory.decodeFile(currentPhotoPath); SelectImage.setImageBitmap(bitmap); ChooseButton.setText("图片已选择"); } } // 处理权限请求结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CAMERA_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限通过,启动拍照 dispatchTakePictureIntent(); } else { Toast.makeText(this, "需要相机权限才能拍照", Toast.LENGTH_SHORT).show(); } } } // 上传图片到Firebase Storage public void UploadImageFileToFirebaseStorage() { // 检查FilePathUri是否为空 if (FilePathUri != null && !ImageName.getText().toString().trim().isEmpty()) { progressDialog.setTitle("图片上传中..."); progressDialog.show(); // 创建存储引用,用时间戳作为文件名避免重复 StorageReference storageReference2nd = storageReference.child(Storage_Path + System.currentTimeMillis() + ".jpg"); storageReference2nd.putFile(FilePathUri) .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { progressDialog.dismiss(); Toast.makeText(getApplicationContext(), "图片上传成功", Toast.LENGTH_LONG).show(); // 获取下载URL(适配新版本Firebase API) storageReference2nd.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() { @Override public void onSuccess(Uri uri) { String imageName = ImageName.getText().toString().trim(); ImageUploadInfo imageUploadInfo = new ImageUploadInfo(imageName, uri.toString()); // 生成唯一ID并保存到数据库 String imageUploadId = databaseReference.push().getKey(); databaseReference.child(imageUploadId).setValue(imageUploadInfo); } }); } }) .addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { progressDialog.dismiss(); Toast.makeText(PhotoActivity.this, exception.getMessage(), Toast.LENGTH_LONG).show(); } }) .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() { @Override public void onProgress(UploadTask.TaskSnapshot taskSnapshot) { progressDialog.setTitle("图片上传中..."); } }); } else { Toast.makeText(PhotoActivity.this, "请选择图片并填写图片名称", Toast.LENGTH_LONG).show(); } } // 图片上传信息实体类 public static class ImageUploadInfo { public String imageName; public String imageURL; public ImageUploadInfo() { // Firebase需要空构造函数 } public ImageUploadInfo(String imageName, String imageURL) { this.imageName = imageName; this.imageURL = imageURL; } } }
3. 关键补充配置(FileProvider)
Android 7.0+禁止直接使用File Uri,需要配置FileProvider:
- 在
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="my_images" path="Pictures" /> </paths>
- 在
AndroidManifest.xml的<application>标签内注册FileProvider:
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourpackage.name.fileprovider" <!-- 和代码中的授权一致 --> android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
记得把com.yourpackage.name替换成你自己的应用包名。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

