android camera: onActivityResult() intent is null if it had extras

狂风中的少年 提交于 2019-11-27 13:03:33
richardtz

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

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.
            }
        }
    }
}
Mun0n

Where did you create the ffor 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);

use the following:

Bitmap bitmap = data.getExtras().getParcelable("data");

it works.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!