web-dev-qa-db-fra.com

android camera: onActivityResult () l'intention est nulle si elle avait des extras

Après avoir cherché beaucoup dans tous les problèmes liés à Stack Overflow et n'avoir rien trouvé, essayez de m'aider.

J'ai créé une intention pour capturer une image. Ensuite, j'ai vu un comportement différent dans onActivityResult(): si je ne mets aucun extra dans l'intention (pour les petites photos), l'intention dans onActivityResult est correcte, mais quand je mets des extras dans l'intention d'écrire l'image à un fichier, l'intention dans onActivityResult est null!

La création d'intention:

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);

Pourquoi est-il nul et comment puis-je le résoudre?

37
dvrm

Il m'arrive la même chose, si vous fournissez MediaStore.EXTRA_OUTPUT, Alors l'intention est nulle, mais vous aurez la photo dans le fichier que vous avez fourni (Uri.fromFile(f)).

Si vous ne spécifiez pas MediaStore.EXTRA_OUTPUT, Vous aurez alors une intention qui contient l'URI du fichier où l'appareil photo a enregistré la photo.

Je ne sais pas si c'est un bug, mais ça fonctionne comme ça.

EDIT: Donc, dans onActivityResult (), vous n'avez plus besoin de vérifier les données si elles sont nulles. Les personnes suivantes ont travaillé avec moi:

 @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;
            }
    }
}

J'espère que cela aide

59
richardtz

Un échantillon écrit en Kotlin. Vous créez un Uri pour l'application appareil photo, CameraFragment le maintient jusqu'à ce que l'appareil photo revienne de l'enregistrement de votre image et vous la restitue dans onActivityResult comme vous vous y attendez.

CameraFragment.kt

Agit comme intermédiaire entre le consommateur et l'application appareil photo. Prend Uri en entrée et le renvoie dans les données 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);
    }
}

Invoquer l'intention de la caméra

this est un fragment de votre application qui déclenchera la caméra. RC_CAMERA est votre code de demande pour cette action.

val uri = /* Your output Uri. */
val f = CameraFragment.newInstance(uri, this, RC_CAMERA)
fragmentManager.beginTransaction().add(f, CameraFragment.TAG).commit()

Gérer le résultat de la caméra

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.
            }
        }
    }
}
1
Eugen Pechanec

Où avez-vous créé le f pour la Uri.fromFile(f)?

Il doit s'agir d'un objet File valide. Essayez de le créer avant le EXTRA_OUTPUT ligne.

File f = new File("valid path");

Essayez avec quelque chose comme ça:

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);
0
Mun0n