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

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

Android App crashes after capturing image using camera intent

问题

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

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

MainActivity 中的函数:

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      /* 目录 */
    );

    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // 创建照片应保存的文件
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException e) {
            Log.e("MainActivity", "创建文件时出错", e);
        }
        if (photoFile != null) {
            photoURI = FileProvider.getUriForFile(this,
                    "com.example.android.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
            startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
        }
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    storage = FirebaseStorage.getInstance().getReference();
    take_pic = (Button) findViewById(R.id.take_pic);
    imageView = (ImageView) findViewById(R.id.pic_view);

    progressDialog = new ProgressDialog(this);

    take_pic.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dispatchTakePictureIntent();
        }
    });
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
        progressDialog.setMessage("上传中...");
        progressDialog.show();
        StorageReference filepath;

        Uri uri = data.getData();

        filepath = storage.child("Photos").child(uri.getLastPathSegment());

        filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                Toast.makeText(MainActivity.this, "上传成功!", Toast.LENGTH_SHORT).show();
                progressDialog.dismiss();
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(MainActivity.this, "上传失败!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

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

英文:

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:

 private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat(&quot;yyyyMMdd_HHmmss&quot;).format(new Date());
String imageFileName = &quot;JPEG_&quot; + timeStamp + &quot;_&quot;;
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName,  /* prefix */
&quot;.jpg&quot;,         /* suffix */
storageDir      /* directory */
);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
Log.e(&quot;MainActivity&quot;, &quot;Error creating file&quot;, e);
}
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
&quot;com.example.android.fileprovider&quot;,
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
storage = FirebaseStorage.getInstance().getReference();
take_pic = (Button) findViewById(R.id.take_pic);
imageView = (ImageView) findViewById(R.id.pic_view);
progressDialog = new ProgressDialog(this);
take_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dispatchTakePictureIntent();
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
progressDialog.setMessage(&quot;Uploading...&quot;);
progressDialog.show();
StorageReference filepath;
Uri uri = data.getData();
filepath = storage.child(&quot;Photos&quot;).child(uri.getLastPathSegment());
filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener&lt;UploadTask.TaskSnapshot&gt;() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, &quot;Upload Successful!&quot;, Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MainActivity.this, &quot;Upload Failed!&quot;, Toast.LENGTH_SHORT).show();
}
});
}
}

答案1

得分: 1

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

首先,您声明该变量:

Uri myPhotoUri = null;

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

private void dispatchTakePictureIntent() {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

    if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        // 创建照片应该保存的文件
        File photoFile = null;
        try {
            photoFile = createImageFile();
        } catch (IOException e) {
            Log.e("MainActivity", "Error creating file", e);
        }
        if (photoFile != null) {

            // 在这里初始化uri
            myPhotoUri = FileProvider.getUriForFile(this,
                    "com.example.android.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, myPhotoUri);
            startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
        }
    }
}

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

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
        progressDialog.setMessage("Uploading...");
        progressDialog.show();
        StorageReference filepath;

        // 不再需要 Uri uri = data.getData();
        filepath = storage.child("Photos").child(myPhotoUri.getLastPathSegment());

        // 在这里调用它
        filepath.putFile(myPhotoUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                Toast.makeText(MainActivity.this, "Upload Successful!", Toast.LENGTH_SHORT).show();
                progressDialog.dismiss();
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(MainActivity.this, "Upload Failed!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

希望这对您有所帮助!

英文:

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

Uri myPhotoUri = null;

Then, you initiate it in your dispatchTakePictureIntent function:

private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
Log.e(&quot;MainActivity&quot;, &quot;Error creating file&quot;, e);
}
if (photoFile != null) {
//you are adding initializing the uri
myPhotoUri = FileProvider.getUriForFile(this,
&quot;com.example.android.fileprovider&quot;,
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}

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

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
progressDialog.setMessage(&quot;Uploading...&quot;);
progressDialog.show();
StorageReference filepath;
//you delete the Uri uri = data.getData();
filepath = storage.child(&quot;Photos&quot;).child(uri.getLastPathSegment());
//here you call it
filepath.putFile(myPhotoUri).addOnSuccessListener(new OnSuccessListener&lt;UploadTask.TaskSnapshot&gt;() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, &quot;Upload Successful!&quot;, Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Toast.makeText(MainActivity.this, &quot;Upload Failed!&quot;, Toast.LENGTH_SHORT).show();
}
});
}
}

答案2

得分: 0

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

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

然后在onActivityResult中

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

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

public static byte[] getByteArrayFromBitmap(Bitmap bitmap) {
    if(bitmap == null) return null;

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);

    return byteArrayOutputStream.toByteArray();
}

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

英文:

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

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

Then onActivityResult

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

then from bitmap to byte[]

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

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:

确定