AIR pour Android – Prendre des photos / vidéos avec CameraUI

Encore un tutorial sur Air pour Android. Cette fois, on va voir comment utiliser la classe CameraUI depuis son application Air.

La classe CameraUI permet, depuis son application Air, de laisser l’utilisateur prendre une photo ou une vidéo. Cet opération se fait par l’intermédiaire des applications natives d’Android.

Une fois que l’utilisateur a pris sa photo ou sa vidéo, il indique qu’il a terminé et retourne automatiquement sur l’application. La photo peut ensuite être affichée directement dans l’application.

Pour l’instant (source forum pre-release), les vidéos prises de cette manière ne peuvent pas être pré-visualisées ensuite dans l’application Air. En effet, celles-ci sont prises en basse résolution et Air ne sait pas (encore?) les lire.

On peut ainsi imaginer de nombreux cas d’utilisation. Par exemple, vous voulez ajouter un lieu à votre application. Vous laissez l’utilisateur remplir le formulaire avec des données alpha-numériques puis il peut prendre une photo et l’ajouter à sa description.

Notez qu’il est possible que l’utilisateur ne puisse pas revenir sur votre application une fois l’opération effectuée car le Garbage Collector a décidé de tuer votre application. En effet, celle-ci n’avait pas le focus et était donc « moins importante » à ses yeux, il se permet donc de faire le ménage. Ce problème se pose aussi pour les applications natives écrites en Java

Détection du support de la fonctionnalité

Comme toujours, vous disposez d’une méthode permettant de tester si oui ou non, le mobile peut vous permettre de prendre des photos / vidéos. Pour cela, utilisez la méthode suivante:

if (CameraUI.isSupported) {

La classe CameraUI fonctionne ensuite un peu comme la classe CameraRoll et sa méthode browseForImage():

Air Android – Récupérer une image issue de la galerie Caméra avec CameraRoll (browseForImage)

Vidéo de l’application

L’application est très simple et permet de prendre des photos ou des vidéos. Si l’utilisateur prend une photo, celle-ci sera affichée dans l’application. Pour une vidéo, on affiche simplement le nom du fichier .3GP

Code de l’application

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
                applicationComplete="application1_applicationCompleteHandler(event)" paddingLeft="0"
                paddingRight="0" paddingTop="0" paddingBottom="0" xmlns:local="*">
  <mx:Script>
    <![CDATA[
      import mx.events.FlexEvent;
      /**
       * Access the native image gallery
       */
      private var _cameraRoll:CameraRoll = null;
      /**
       * Access the native camera application
       */
      private var _cameraUI:CameraUI = null;
      /**
       * Intermediate object that contain a reference to the
       * media file the user just created using the Camera
       */
      private var _mediaPromise:MediaPromise = null;
      /**
       *
       */
      private var _cameraUILoader:Loader = null;

      private function onErrorEvent(event:ErrorEvent):void {
        showInfo("Erreur lors de la sauvegarade");
      }

      private function onIOError(event:IOErrorEvent):void {
        showInfo("Erreur lors de la récupération de la sélection...");
      }

      private function showInfo(text:String):void {
        log.text = text;
      }

      private function onComplete(event:Event):void {
        showInfo("Sauvegarde effectuée");
      }

      protected function application1_applicationCompleteHandler(event:FlexEvent):void {
        if (CameraUI.isSupported) {
          getPictureButton.enabled = true;
          getVideoButton.enabled = true;
          //
          _cameraUI = new CameraUI;
          _cameraUI.addEventListener(MediaEvent.COMPLETE, onMediaEventComplete);
          _cameraUI.addEventListener(ErrorEvent.ERROR, onCameraUIErrorEvent);
          _cameraUI.addEventListener(Event.CANCEL, onCameraUICancel);
        } else {
          showInfo("CameraUI non supportée");
        }
      }

      /**
       * Once the user finished taking the picture / video
       */
      private function onMediaEventComplete(event:MediaEvent):void {
        _mediaPromise = event.data as MediaPromise;
        if (_cameraUILoader) {
          _cameraUILoader.unload();
          _cameraUILoader = null;
        }
        if (_mediaPromise.mediaType == MediaType.IMAGE) {
          loadImage();
        } else if (_mediaPromise.mediaType == MediaType.VIDEO) {
          showInfo("Fichier " + _mediaPromise.relativePath + " créé");
        }
      }

      public function loadImage():void {
        //Loads the MediaPromise object
        _cameraUILoader = new Loader();
        _cameraUILoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadImageHandler);
        _cameraUILoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
        _cameraUILoader.loadFilePromise(_mediaPromise);
      }

      public function loadImageHandler(event:Event):void {

        //adds the bitmapdata to stage
        showInfo("\n" + event.type + " " + event.toString());
        var content:Bitmap = event.currentTarget.content as Bitmap;
        if (!content) {
          showInfo("Impossible de récupérer le Bitmap associé");
          return;
        }
        mainImage.source = content;
      }

      /**
       * L'utilisation a annulé
       */
      private function onCameraUICancel(event:Event):void {
        showInfo("Annulation...");
      }

      /**
       * Erreur lors du process
       */
      private function onCameraUIErrorEvent(event:ErrorEvent):void {
        showInfo("Une erreur s'est produite...");
      }

      private function onGetPicture():void {
        //Launch CameraUI for Image Capture
        _cameraUI.launch(MediaType.IMAGE);
      }

      private function onGetVideo():void {
        //Launch CameraUI for Video Capture
        _cameraUI.launch(MediaType.VIDEO);
      }
    ]]>
  </mx:Script>
  <mx:Style>
    global {
      font-size: 24;
    }
  </mx:Style>
  <mx:ApplicationControlBar left="0" right="0" bottom="0" height="80" paddingTop="8" paddingLeft="8"
                            paddingBottom="8" paddingRight="8" horizontalGap="8" verticalGap="8"
                            dock="true">
    <mx:Box width="100%">
      <mx:HBox>
        <mx:Button id="getPictureButton" label="Get Picture" click="onGetPicture();" height="100%"
                   width="100%" enabled="false" />
        <mx:Button id="getVideoButton" label="Get Video" click="onGetVideo();" height="100%"
                   width="100%" enabled="false" />
      </mx:HBox>
      <mx:Label id="log" fontSize="18" />
    </mx:Box>
  </mx:ApplicationControlBar>
  <mx:Image id="mainImage" width="100%" height="100%" />
</mx:Application>

Télécharger le projet au format FXP

Télécharger l’application au format APK

14 réflexions au sujet de « AIR pour Android – Prendre des photos / vidéos avec CameraUI »

  1. Ping : Flex Library – PNGEncoder asynchrone (encodage BitmapData vers ByteArray PNG async) - Adobe Flex Tutorial - Tutoriaux Flex Builder, MXML, ActionScript, AS3

  2. AndroidSearch

    Bonjour,
    j’ai testé (télécharger l’apk) et quand je prend une photo, elle s’enregistre 2 fois dans la galerie d’image. Normal?

  3. AndroidSearch

    Pourtant j’ai la dernière version de AIR (2.6.0.1912)
    J’ai testé avec le code le plus simple :
    var cam:cameraUI = new cameraUI();
    cam.launch(MediaType.IMAGE);
    Et il y a 2 photos qui s’enregistre. (Sur un HTC Desire S)

  4. Ping : AIR Mobile – Utilisation de CameraUI (Appareil photo) sous Android, iOS et BlackBerry Tablet OS - Adobe Flex Tutorial - Tutoriaux Flex Builder, MXML, ActionScript, AS3

  5. nona

    Bonjour,
    j’ai testé ce script pour prebdre un photos il m’a affiché ce message : Une erreur s’est produite…
    portant pour a video ca marche très bien,
    merci de m’aider

    voila une portion de mon code :
    < ?xml version="1.0" encoding="utf-8"?>

    xmlns:s="library://ns.adobe.com/flex/spark" title="Nouveau fournisseur" creationComplete="application1_applicationCompleteHandler(event)">

    < ![CDATA[

    import mx.events.FlexEvent;
    /**
    * Access the native image gallery
    */
    private var _cameraRoll:CameraRoll = null;
    /**
    * Access the native camera application
    */
    private var _cameraUI:CameraUI = null;
    /**
    * Intermediate object that contain a reference to the
    * media file the user just created using the Camera
    */
    private var _mediaPromise:MediaPromise = null;
    /**
    *
    */
    private var _cameraUILoader:Loader = null;

    private function onErrorEvent(event:ErrorEvent):void {
    showInfo("Erreur lors de la sauvegarade");
    }

    private function onIOError(event:IOErrorEvent):void {
    showInfo("Erreur lors de la récupération de la sélection...");
    }

    private function showInfo(text:String):void {
    log.text = text;
    }

    private function onComplete(event:Event):void {
    showInfo("Sauvegarde effectuée");
    }

    protected function application1_applicationCompleteHandler(event:FlexEvent):void {
    if (CameraUI.isSupported) {
    getPictureButton.enabled = true;
    getVideoButton.enabled = true;
    //
    _cameraUI = new CameraUI;
    _cameraUI.addEventListener(MediaEvent.COMPLETE, onMediaEventComplete);
    _cameraUI.addEventListener(ErrorEvent.ERROR, onCameraUIErrorEvent);
    _cameraUI.addEventListener(Event.CANCEL, onCameraUICancel);
    } else {
    showInfo("CameraUI non supportée");
    }
    }

    /**
    * Once the user finished taking the picture / video
    */
    private function onMediaEventComplete(event:MediaEvent):void {
    _mediaPromise = event.data as MediaPromise;
    if (_cameraUILoader) {
    _cameraUILoader.unload();
    _cameraUILoader = null;
    }
    if (_mediaPromise.mediaType == MediaType.IMAGE) {
    loadImage();
    } else if (_mediaPromise.mediaType == MediaType.VIDEO) {
    showInfo("Fichier " + _mediaPromise.relativePath + " créé");
    }
    }

    public function loadImage():void {
    //Loads the MediaPromise object
    _cameraUILoader = new Loader();
    _cameraUILoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadImageHandler);
    _cameraUILoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
    _cameraUILoader.loadFilePromise(_mediaPromise);
    }

    public function loadImageHandler(event:Event):void {

    //adds the bitmapdata to stage
    showInfo("\n" + event.type + " " + event.toString());
    var content:Bitmap = event.currentTarget.content as Bitmap;
    if (!content) {
    showInfo("Impossible de récupérer le Bitmap associé");
    return;
    }
    mainImage.source = content;
    }

    /**
    * L'utilisation a annulé
    */
    private function onCameraUICancel(event:Event):void {
    showInfo("Annulation...");
    }

    /**
    * Erreur lors du process
    */
    private function onCameraUIErrorEvent(event:ErrorEvent):void {
    showInfo("Une erreur s'est produite...");
    }

    private function onGetPicture():void {
    //Launch CameraUI for Image Capture
    _cameraUI.launch(MediaType.IMAGE);
    }

    private function onGetVideo():void {
    //Launch CameraUI for Video Capture
    _cameraUI.launch(MediaType.VIDEO);
    }
    ]]>

    click="onGetPicture();" enabled="false">
    click="onGetVideo();" enabled="false">

  6. fnicollet Auteur de l’article

    Salut, essaye de voir s’il y a plus d’information dans l’objet ErrorEvent qui est renvoyé en debug. Sinon vérifie que tu as bien mi les autorisations dans ton *-app.xml pour l’utilisation de la caméra

    Fabien

  7. nona

    Bonjour, effectivement c’est un problème des autorisations de mon mobile :)

    merci pour ton aide

  8. fnicollet Auteur de l’article

    Salut,
    récupère une référence vers le fichier et fait une copie (File). Au passage, tu pourra changer le nom

    Fabien

  9. sabrine

    Salut,

    merci pour le script, mais j’ai un soucis sous ipad ou iphone je sais pas ou il stock les images capturés !!!!! et il m’affiche pas le chemin
    SVP aidez moi

  10. Ping : Adobe Flex Tutorial - Adobe Flex Tutorial

Les commentaires sont fermés.