Android应用程序在使用相机意图捕获图像后崩溃。

huangapple go评论103阅读模式
英文:

Android App crashes after capturing image using camera intent

问题

该应用程序尝试使用设备的摄像头捕获图像并将其上传到 Firebase。然而,在捕获图像后,应用程序崩溃。

显示以下错误:java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法 'android.net.Uri android.content.Intent.getData()'

MainActivity 中的函数:

  1. private File createImageFile() throws IOException {
  2. String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
  3. String imageFileName = "JPEG_" + timeStamp + "_";
  4. File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
  5. File image = File.createTempFile(
  6. imageFileName, /* 前缀 */
  7. ".jpg", /* 后缀 */
  8. storageDir /* 目录 */
  9. );
  10. mCurrentPhotoPath = image.getAbsolutePath();
  11. return image;
  12. }
  13. private void dispatchTakePictureIntent() {
  14. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  15. if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  16. // 创建照片应保存的文件
  17. File photoFile = null;
  18. try {
  19. photoFile = createImageFile();
  20. } catch (IOException e) {
  21. Log.e("MainActivity", "创建文件时出错", e);
  22. }
  23. if (photoFile != null) {
  24. photoURI = FileProvider.getUriForFile(this,
  25. "com.example.android.fileprovider",
  26. photoFile);
  27. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
  28. startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
  29. }
  30. }
  31. }
  32. @Override
  33. protected void onCreate(Bundle savedInstanceState) {
  34. super.onCreate(savedInstanceState);
  35. setContentView(R.layout.activity_main);
  36. storage = FirebaseStorage.getInstance().getReference();
  37. take_pic = (Button) findViewById(R.id.take_pic);
  38. imageView = (ImageView) findViewById(R.id.pic_view);
  39. progressDialog = new ProgressDialog(this);
  40. take_pic.setOnClickListener(new View.OnClickListener() {
  41. @Override
  42. public void onClick(View view) {
  43. dispatchTakePictureIntent();
  44. }
  45. });
  46. }
  47. @Override
  48. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  49. super.onActivityResult(requestCode, resultCode, data);
  50. if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
  51. progressDialog.setMessage("上传中...");
  52. progressDialog.show();
  53. StorageReference filepath;
  54. Uri uri = data.getData();
  55. filepath = storage.child("Photos").child(uri.getLastPathSegment());
  56. filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
  57. @Override
  58. public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
  59. Toast.makeText(MainActivity.this, "上传成功!", Toast.LENGTH_SHORT).show();
  60. progressDialog.dismiss();
  61. }
  62. }).addOnFailureListener(new OnFailureListener() {
  63. @Override
  64. public void onFailure(@NonNull Exception e) {
  65. Toast.makeText(MainActivity.this, "上传失败!", Toast.LENGTH_SHORT).show();
  66. }
  67. });
  68. }
  69. }

如果您需要进一步的帮助或解释,请告诉我。

英文:

The application attempts to capture an image using the device's camera and upload it to FireBase. However, after an image is captured, the app crashes.

It shows the error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.net.Uri android.content.Intent.getData()' on a null object reference

Functions in MainActivity:

  1. private File createImageFile() throws IOException {
  2. String timeStamp = new SimpleDateFormat(&quot;yyyyMMdd_HHmmss&quot;).format(new Date());
  3. String imageFileName = &quot;JPEG_&quot; + timeStamp + &quot;_&quot;;
  4. File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
  5. File image = File.createTempFile(
  6. imageFileName, /* prefix */
  7. &quot;.jpg&quot;, /* suffix */
  8. storageDir /* directory */
  9. );
  10. mCurrentPhotoPath = image.getAbsolutePath();
  11. return image;
  12. }
  13. private void dispatchTakePictureIntent() {
  14. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  15. if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  16. // Create the File where the photo should go
  17. File photoFile = null;
  18. try {
  19. photoFile = createImageFile();
  20. } catch (IOException e) {
  21. Log.e(&quot;MainActivity&quot;, &quot;Error creating file&quot;, e);
  22. }
  23. if (photoFile != null) {
  24. photoURI = FileProvider.getUriForFile(this,
  25. &quot;com.example.android.fileprovider&quot;,
  26. photoFile);
  27. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
  28. startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
  29. }
  30. }
  31. }
  32. @Override
  33. protected void onCreate(Bundle savedInstanceState) {
  34. super.onCreate(savedInstanceState);
  35. setContentView(R.layout.activity_main);
  36. storage = FirebaseStorage.getInstance().getReference();
  37. take_pic = (Button) findViewById(R.id.take_pic);
  38. imageView = (ImageView) findViewById(R.id.pic_view);
  39. progressDialog = new ProgressDialog(this);
  40. take_pic.setOnClickListener(new View.OnClickListener() {
  41. @Override
  42. public void onClick(View view) {
  43. dispatchTakePictureIntent();
  44. }
  45. });
  46. }
  47. @Override
  48. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  49. super.onActivityResult(requestCode, resultCode, data);
  50. if (requestCode == CAMERA_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
  51. progressDialog.setMessage(&quot;Uploading...&quot;);
  52. progressDialog.show();
  53. StorageReference filepath;
  54. Uri uri = data.getData();
  55. filepath = storage.child(&quot;Photos&quot;).child(uri.getLastPathSegment());
  56. filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener&lt;UploadTask.TaskSnapshot&gt;() {
  57. @Override
  58. public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
  59. Toast.makeText(MainActivity.this, &quot;Upload Successful!&quot;, Toast.LENGTH_SHORT).show();
  60. progressDialog.dismiss();
  61. }
  62. }).addOnFailureListener(new OnFailureListener() {
  63. @Override
  64. public void onFailure(@NonNull Exception e) {
  65. Toast.makeText(MainActivity.this, &quot;Upload Failed!&quot;, Toast.LENGTH_SHORT).show();
  66. }
  67. });
  68. }
  69. }

答案1

得分: 1

由于您的意图数据为null,您会收到该错误。这也曾经发生在我身上,当使用拍照意图(take picture intent)时,您的onActivityResult始终将数据返回为null。作为一种解决方法,我将photoURI设置为活动的全局变量,并在onActivityResult中再次调用它。代码如下:

首先,您声明该变量:

  1. Uri myPhotoUri = null;

然后,在dispatchTakePictureIntent函数中初始化它:

  1. private void dispatchTakePictureIntent() {
  2. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  3. if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  4. // 创建照片应该保存的文件
  5. File photoFile = null;
  6. try {
  7. photoFile = createImageFile();
  8. } catch (IOException e) {
  9. Log.e("MainActivity", "Error creating file", e);
  10. }
  11. if (photoFile != null) {
  12. // 在这里初始化uri
  13. myPhotoUri = FileProvider.getUriForFile(this,
  14. "com.example.android.fileprovider",
  15. photoFile);
  16. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, myPhotoUri);
  17. startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
  18. }
  19. }
  20. }

在您的onActivityResult中,您使用该uri来调用您的Firebase函数。它现在将具有上传所需的信息:

  1. @Override
  2. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  3. super.onActivityResult(requestCode, resultCode, data);
  4. if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
  5. progressDialog.setMessage("Uploading...");
  6. progressDialog.show();
  7. StorageReference filepath;
  8. // 不再需要 Uri uri = data.getData();
  9. filepath = storage.child("Photos").child(myPhotoUri.getLastPathSegment());
  10. // 在这里调用它
  11. filepath.putFile(myPhotoUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
  12. @Override
  13. public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
  14. Toast.makeText(MainActivity.this, "Upload Successful!", Toast.LENGTH_SHORT).show();
  15. progressDialog.dismiss();
  16. }
  17. }).addOnFailureListener(new OnFailureListener() {
  18. @Override
  19. public void onFailure(@NonNull Exception e) {
  20. Toast.makeText(MainActivity.this, "Upload Failed!", Toast.LENGTH_SHORT).show();
  21. }
  22. });
  23. }
  24. }

希望这对您有所帮助!

英文:

You are getting that errror because your intent.getData is null. It happened to me too, your onActivityResult when using the take picture intent always brings the data as null. As a workaround I made the photoURI a global variable in the activity and onActivityResult called it again. It would be something like this:

First you declare the variable

  1. Uri myPhotoUri = null;

Then, you initiate it in your dispatchTakePictureIntent function:

  1. private void dispatchTakePictureIntent() {
  2. Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  3. if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
  4. // Create the File where the photo should go
  5. File photoFile = null;
  6. try {
  7. photoFile = createImageFile();
  8. } catch (IOException e) {
  9. Log.e(&quot;MainActivity&quot;, &quot;Error creating file&quot;, e);
  10. }
  11. if (photoFile != null) {
  12. //you are adding initializing the uri
  13. myPhotoUri = FileProvider.getUriForFile(this,
  14. &quot;com.example.android.fileprovider&quot;,
  15. photoFile);
  16. takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
  17. startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
  18. }
  19. }
  20. }

And on your onActivityResult, you use that uri to call to your firebase function. It will now have the information necessary to upload it:

  1. @Override
  2. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  3. super.onActivityResult(requestCode, resultCode, data);
  4. if (requestCode == CAMERA_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
  5. progressDialog.setMessage(&quot;Uploading...&quot;);
  6. progressDialog.show();
  7. StorageReference filepath;
  8. //you delete the Uri uri = data.getData();
  9. filepath = storage.child(&quot;Photos&quot;).child(uri.getLastPathSegment());
  10. //here you call it
  11. filepath.putFile(myPhotoUri).addOnSuccessListener(new OnSuccessListener&lt;UploadTask.TaskSnapshot&gt;() {
  12. @Override
  13. public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
  14. Toast.makeText(MainActivity.this, &quot;Upload Successful!&quot;, Toast.LENGTH_SHORT).show();
  15. progressDialog.dismiss();
  16. }
  17. }).addOnFailureListener(new OnFailureListener() {
  18. @Override
  19. public void onFailure(@NonNull Exception e) {
  20. Toast.makeText(MainActivity.this, &quot;Upload Failed!&quot;, Toast.LENGTH_SHORT).show();
  21. }
  22. });
  23. }
  24. }

答案2

得分: 0

首先检查是否具有使用相机的权限,然后

  1. Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  2. startActivityForResult(cameraIntent, CAMERA_REQ);

然后在onActivityResult中

  1. @Override
  2. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  3. super.onActivityResult(requestCode, resultCode, data);
  4. if (requestCode == CAMERA_REQ && resultCode == Activity.RESULT_OK) {
  5. bitmap = (Bitmap) data.getExtras().get("data");
  6. Bitmap.createScaledBitmap(bitmap, 150, 150, true);
  7. }
  8. }

然后从位图转换为字节数组

  1. public static byte[] getByteArrayFromBitmap(Bitmap bitmap) {
  2. if(bitmap == null) return null;
  3. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  4. bitmap.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);
  5. return byteArrayOutputStream.toByteArray();
  6. }

现在你可以使用位图或字节数组做任何你想做的事情。

英文:

First check that you have permission for using the camera, then

  1. Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
  2. startActivityForResult(cameraIntent, CAMERA_REQ);

Then onActivityResult

  1. @Override
  2. public void onActivityResult(int requestCode, int resultCode, Intent data) {
  3. super.onActivityResult(requestCode, resultCode, data);
  4. if (requestCode == CAMERA_REQ &amp;&amp; resultCode == Activity.RESULT_OK) {
  5. bitmap = (Bitmap) data.getExtras().get(&quot;data&quot;);
  6. Bitmap.createScaledBitmap(bitmap, 150, 150, true);
  7. }
  8. }

then from bitmap to byte[]

  1. public static byte[] getByteArrayFromBitmap(Bitmap bitmap) {
  2. if(bitmap == null) return null;
  3. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  4. bitmap.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);
  5. return byteArrayOutputStream.toByteArray();
  6. }

You can now do whatever you want with the bitmap or byte[]

huangapple
  • 本文由 发表于 2020年8月5日 21:39:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63266464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定