问题
After searching a lot in all the related issues at Stack Overflow and finding nothing, please try to help me.
I created an intent for capture a picture. Then I saw different behavior at onActivityResult()
: if I don't put any extra in the Intent (for small pics) the Intent in onActivityResult is ok, but when I put extras in the intent for writing the pic to a file, the intent in onActivityResult is null
!
The Intent creation:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// without the following line the intent is ok
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(takePictureIntent, actionCode);
Why is it null, and how can I solve it?
回答1:
It happens the same to me, if you are providing MediaStore.EXTRA_OUTPUT
, then the intent is null, but you will have the photo in the file you provided (Uri.fromFile(f)
).
If you don't specify MediaStore.EXTRA_OUTPUT
then you will have an intent which contains the uri from the file where the camera has saved the photo.
Don't know if it as a bug, but it works that way.
EDIT: So in onActivityResult() you no longer need to check for data if null. The following worked with me:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PICK_IMAGE_REQUEST://actionCode
if (resultCode == RESULT_OK && data != null && data.getData() != null) {
//For Image Gallery
}
return;
case CAPTURE_IMAGE_REQUEST://actionCode
if (resultCode == RESULT_OK) {
//For CAMERA
//You can use image PATH that you already created its file by the intent that launched the CAMERA (MediaStore.EXTRA_OUTPUT)
return;
}
}
}
Hope it helps
回答2:
A sample written in Kotlin. You create a Uri
for camera app, CameraFragment
holds it until camera returns from saving your picture and gives it back to you in onActivityResult
as you would expect.
CameraFragment.kt
Acts as an intermediary between consumer and camera app. Takes Uri
as input and returns it in data Intent
.
class CameraFragment : Fragment() {
companion object {
val TAG = CameraFragment::class.java.simpleName
private val KEY_URI = ".URI"
fun newInstance(uri: Uri, targetFragment: Fragment, requestCode: Int): CameraFragment {
val args = Bundle()
args.putParcelable(KEY_URI, uri)
val fragment = CameraFragment()
fragment.arguments = args
fragment.setTargetFragment(targetFragment, requestCode)
return fragment
}
}
private lateinit var uri: Uri
private var fired = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
fired = savedInstanceState?.getBoolean("fired") ?: false
if (!fired) {
val args = arguments
uri = args.getParcelable(KEY_URI)
val i = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
i.putExtra(MediaStore.EXTRA_OUTPUT, uri)
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
context.grantUriPermission(i, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
startActivityForResult(i, targetRequestCode)
fired = true
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean("fired", fired)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == targetRequestCode) {
context.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
val newData = Intent()
newData.data = uri
targetFragment.onActivityResult(requestCode, resultCode, newData)
dismiss()
}
}
private fun dismiss() {
fragmentManager.beginTransaction().remove(this).commit()
}
}
/** Grant Uri permissions for all camera apps. */
fun Context.grantUriPermission(intent: Intent, uri: Uri, modeFlags: Int) {
val resolvedIntentActivities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (resolvedIntentInfo in resolvedIntentActivities) {
val packageName = resolvedIntentInfo.activityInfo.packageName;
grantUriPermission(packageName, uri, modeFlags);
}
}
Invoke camera intent
this
is a fragment in your app which will trigger the camera. RC_CAMERA
is your request code for this action.
val uri = /* Your output Uri. */
val f = CameraFragment.newInstance(uri, this, RC_CAMERA)
fragmentManager.beginTransaction().add(f, CameraFragment.TAG).commit()
Handle camera result
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when(requestCode) {
RC_CAMERA -> {
if (resultCode == Activity.RESULT_OK) {
val uri = data?.data
// Do whatever you need.
}
}
}
}
回答3:
Where did you create the f
for the Uri.fromFile(f)
?
It must be a valid File
object. Try to create it before the EXTRA_OUTPUT
line.
File f = new File("valid path");
Try with something like this:
File file = new File(dataFile);
Uri outFileUri = Uri.fromFile(file);
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, outFileUri);
startActivityForResult(intent, TAKE_PHOTO);
回答4:
When we will capture the image from Camera in android then Uri
or data.getdata()
comes null. we have two solutions to resolve this issue.
- We can got the Uri path from the Bitmap Image
- We can got the Uri path from cursor.
I will implement all methods here, Please carefully watch and read these:-
First i will tell how to get Uri from Bitmap Image: Complete code is :
First we will capture image through Intent that will same for both methods so this code i will write one time only here :
// Capture Image
captureImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, reqcode);
}
}
});
Now we will Implement OnActivityResult :-(This will be same for both above 2 methods):-
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==reqcode && resultCode==RESULT_OK)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView.setImageBitmap(photo);
// CALL THIS METHOD TO GET THE URI FROM THE BITMAP
Uri tempUri = getImageUri(getApplicationContext(), photo);
\\ Show Uri path based on Image
Toast.makeText(LiveImage.this,"Here "+ tempUri, Toast.LENGTH_LONG).show();
\\ Show Uri path based on Cursor Content Resolver
Toast.makeText(this, "Real path for URI : "+getRealPathFromURI(tempUri), Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(this, "Failed To Capture Image", Toast.LENGTH_SHORT).show();
}
}
\now we will create all above method to create Uri from Image and Cursor methods via classes:
Now URI path from Bitmap Image
private Uri getImageUri(Context applicationContext, Bitmap photo) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(LiveImage.this.getContentResolver(), photo, "Title", null);
return Uri.parse(path);
}
\ Uri from Real path of saved image
public String getRealPathFromURI(Uri uri) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
回答5:
use the following:
Bitmap bitmap = data.getExtras().getParcelable("data");
it works.
来源:https://stackoverflow.com/questions/12564112/android-camera-onactivityresult-intent-is-null-if-it-had-extras