web-dev-qa-db-fra.com

Caméra sur Android Exemple

Je veux écrire une activité qui:

  1. Affiche l'aperçu de l'appareil photo (viseur) et comporte un bouton "capture".
  2. Lorsque le bouton "capture" est enfoncé, prend une photo et la renvoie à l'activité d'appel (setResult () & finish ()).

Existe-t-il des exemples complete compatibles avec chaque périphérique? Un lien vers une simple application open source prenant des photos serait la réponse idéale.


Mes recherches jusqu'à présent:

Il s’agit d’un scénario courant, qui comporte de nombreuses questions et tutoriels.

Il y a deux approches principales:

  1. Utilisez l'événement Android.provider.MediaStore.ACTION_IMAGE_CAPTURE. Voir cette question
  2. Utilisez directement l’API de la caméra. Voir cet exemple ou cette question (avec beaucoup de références) .

L'approche 1 aurait été parfaite, mais le problème est que l'intention est mise en œuvre différemment sur chaque périphérique. Sur certains appareils, cela fonctionne bien. Cependant, sur certains appareils, vous pouvez prendre une photo, mais celle-ci n'est jamais renvoyée vers votre application. Sur certains appareils, rien ne se produit lorsque vous lancez l'intention. En règle générale, il enregistre également l'image sur la carte SD et requiert la présence de la carte SD. L'interaction de l'utilisateur est également différente sur chaque appareil.

Avec l'approche 2, l'enjeu est la stabilité. J'ai essayé quelques exemples, mais j'ai réussi à empêcher la caméra de fonctionner (jusqu'au redémarrage) sur certains appareils et à geler complètement un autre appareil. Sur un autre appareil, la capture a fonctionné, mais l'aperçu est resté noir.

J'aurais utilisé ZXing comme exemple d'application (je travaille souvent), mais il utilise uniquement l'aperçu (viseur) et ne prend aucune photo. J'ai également constaté que sur certains appareils, ZXing ne réglait pas automatiquement la balance des blancs lorsque les conditions d'éclairage changeaient, alors que l'application native pour appareil photo le faisait correctement (je ne suis pas sûr que cela puisse être corrigé).


Mettre à jour:

Pendant un certain temps, j'ai utilisé directement l'API de caméra. Cela donne plus de contrôle (interface utilisateur personnalisée, etc.), mais je ne le recommanderais à personne. Je travaillerais sur 90% des appareils, mais de temps en temps, un nouvel appareil serait publié, avec un problème différent.

Certains des problèmes que j'ai rencontrés:

  • Gestion de l'autofocus
  • Manipulation du flash
  • Prise en charge des appareils avec une caméra frontale, une caméra arrière ou les deux
  • Chaque appareil a une combinaison différente de résolution d'écran, de résolutions d'aperçu (qui ne correspond pas toujours à la résolution d'écran) et de résolutions d'image.

Donc, en général, je ne recommanderais pas du tout cette voie, à moins qu'il n'y ait pas d'autre moyen. Après deux ans, j’ai abandonné l’utilisation de code personnalisé pour revenir à l’approche fondée sur l’intention. Depuis lors, j'ai eu beaucoup moins de problèmes. Les problèmes que j'avais avec l'approche fondée sur l'intention dans le passé étaient probablement juste ma propre incompétence.

Si vous vraiment devez emprunter cette voie, j'ai entendu dire que c'est beaucoup plus facile si vous ne supportez que les appareils dotés d'Android 4.0+.

19
Ralf

Avec l'approche 2, l'enjeu est la stabilité. J'ai essayé quelques exemples, mais j'ai réussi à empêcher la caméra de fonctionner (jusqu'au redémarrage) sur certains appareils et à geler complètement un autre appareil. Sur un autre appareil, la capture a fonctionné, mais la prévisualisation est restée noire.

Soit il y a un bogue dans les exemples, soit il y a un problème de compatibilité avec les périphériques.

9
CommonsWare

L'exemple donné par CommonsWare fonctionne bien. L'exemple fonctionne lorsqu'il est utilisé tel quel, mais voici les problèmes que j'ai rencontrés lors de sa modification pour mon cas d'utilisation:

  1. Ne prenez jamais une deuxième photo avant la fin de la première, c’est-à-dire que PictureCallback.onPictureTaken() a été appelé. L'exemple CommonsWare utilise l'indicateur inPreview à cette fin.
  2. Assurez-vous que votre SurfaceView est en plein écran. Si vous souhaitez une prévisualisation plus petite, vous devrez peut-être modifier la logique de sélection de la taille de la prévisualisation, sinon la prévisualisation risque de ne pas correspondre à la SurfaceView de certains périphériques. Certains appareils ne prennent en charge qu'une taille d'aperçu en plein écran. La solution la plus simple est donc de la garder en plein écran.

Pour ajouter d'autres composants à l'écran d'aperçu, FrameLayout fonctionne bien selon mon expérience. J'ai commencé par utiliser un LinearLayout pour ajouter du texte au-dessus de l'aperçu, mais cela a enfreint la règle n ° 2. Lorsque vous utilisez une variable FrameLayout pour ajouter des composants en haut de l'aperçu, vous ne rencontrez aucun problème de résolution de l'aperçu.

J'ai également posté un problème mineur relatif à Camera.open() sur GitHub .

1
Ralf

"Le moyen recommandé pour accéder à la caméra est d'ouvrir Caméra sur un fil séparé" . Sinon, Camera.open () peut prendre un certain temps et risque de compliquer le processus d'interface utilisateur.

"Les rappels seront invoqués si l'événement thread open (int) a été appelé à partir de" . C'est pourquoi, pour obtenir des performances optimales avec les rappels d'aperçu de caméra (par exemple, pour les encoder dans une vidéo à faible temps de latence pour la communication en direct), je recommande d'ouvrir la caméra dans un nouveau HandlerThread, comme indiqué ici .

0
Alex Cohn