Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-2122] Android: Implement Video Recording

GitHub Issuen/a
TypeNew Feature
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2016-04-26T04:57:53.000+0000
Affected Version/sn/a
Fix Version/sRelease 6.0.0, Release 5.4.0
ComponentsAndroid
Labelsdr-list, parity, supportTeam, tbs-1.8.0
ReporterDon Thorp
AssigneeAshraf Abu
Created2011-04-15T03:11:06.000+0000
Updated2016-07-12T21:50:53.000+0000

Description

Comments

  1. Jon Alter 2011-07-21

    Associated Helpdesk Ticket

    http://appc.me/c/APP-632317
  2. ankur garha 2013-06-07

    Is this feature still implemented for android or not???
  3. Dan Peleg 2014-04-21

    Solved here: [https://github.com/appcelerator/titanium_mobile/pull/5634]
  4. Johan Chaves 2014-08-19

    Hi, when is this going to be integrated?
  5. Michael Gangolf 2016-03-15

    @danpe iOS has startVideoCapture( ) and stopVideoCapture(). So renaming the android methods startRecording/stopRecording would help to add this to android
  6. Michael Gangolf 2016-04-09

    Started to work on a new PR: https://github.com/appcelerator/titanium_mobile/pull/7929 Not ready yet but it's already working on a Nexus 4 (5.1.1) with native camera (with overlays and maxDuration) and the intent version! *Example:*
       var isRecording = false;
       var isPhoto = false; // photo or video mode
       
       var win = Ti.UI.createWindow({
           backgroundColor: "#fff"
       });
       
       var btn_cam1 = Ti.UI.createButton({
           bottom: 10,
           title: "CAM INTENT"
       })
       
       var btn_cam2 = Ti.UI.createButton({
           bottom: 50,
           title: "CAM OVERLAY REAR",
           id: "cam_rear"
       })
       var btn_cam3 = Ti.UI.createButton({
           bottom: 90,
           title: "CAM OVERLAY FRONT",
           id: "cam_front"
       })
       
       var btn_cam4 = Ti.UI.createButton({
           bottom: 130,
           title: "PHOTO REAR",
           id: "photo_rear"
       })
       var btn_cam5 = Ti.UI.createButton({
           bottom: 170,
           title: "PHOTO FRONT",
           id: "photo_front"
       })
       
       var btnCamera = Ti.UI.createButton({
           title: 'RECORD',
           bottom: 10
       });
       
       var btnCameraClose = Ti.UI.createButton({
           title: 'CLOSE',
           top: 10
       });
       
       var overlay = Ti.UI.createView({
           top: 0,
           right: 0,
           bottom: 0,
           left: 0
       });
       
       var movie = Titanium.Media.createVideoPlayer({
           movieControlStyle: Titanium.Media.VIDEO_CONTROL_EMBEDDED,
           top: 0,
           height: 200,
           width: 200,
           backgroundColor: "#000",
           autoplay:false
       });
       
       
       overlay.add(btnCamera);
       overlay.add(btnCameraClose);
       
       btnCameraClose.addEventListener('click', function(e) {
           Titanium.Media.hideCamera();
       });
       
       btnCamera.addEventListener('click', function(e) {
           if (isPhoto){
               // photo mode
               Titanium.Media.takePicture();
           } else {
               // video mode
               if (!isRecording) {
                   Titanium.Media.startVideoCapture();
                   isRecording = true;
                   btnCamera.title = "STOP";
               } else {
                   Titanium.Media.stopVideoCapture();
               }
           }
       });
       
       function onClickCam(e) {
           // intent
           Ti.Media.showCamera({
               autohide: false,
               animated: false,
               allowEditing: false,
               saveToPhotoGallery: true,
               success: function(event) {
                   movie.url = event.media.nativePath;
               },
               cancel: function(event) {
                   console.log("error");
               },
               error: function(error) {
                   alert('error');
               },
               mediaTypes: [Titanium.Media.MEDIA_TYPE_VIDEO],
               videoMaximumDuration: 5000,
               videoQuality: Titanium.Media.QUALITY_HIGH
           });
       }
       
       
       function onClickCam2(e) {
           // native camera
           var which = Ti.Media.CAMERA_REAR;
           var type = Titanium.Media.MEDIA_TYPE_VIDEO;
           var autohide = false;
           isPhoto = false;
           
           if (e.source.id == "cam_front") {
               which = Ti.Media.CAMERA_FRONT;
           }
           if (e.source.id=="photo_front") {
               which = Ti.Media.CAMERA_FRONT;
               type = Ti.Media.MEDIA_TYPE_PHOTO;
               isPhoto = true;
               autohide = true;
           }
           if (e.source.id=="photo_rear") {
               type = Ti.Media.MEDIA_TYPE_PHOTO;
               isPhoto = true;
               autohide = true;
           }
           
           console.log(type + " " + which);
           
           Ti.Media.showCamera({
               overlay: overlay,
               autohide: autohide,
               animated: false,
               allowEditing: false,
               saveToPhotoGallery: true,
               whichCamera: which,
               success: function(event) {
                   if (!isPhoto) movie.url = event.media.nativePath;
                   isRecording = false;
                   btnCamera.title = "RECORD";
               },
               cancel: function(event) {
                   console.log("error");
               },
               error: function(error) {
                   alert('error');
               },
               mediaTypes: [type],
               videoMaximumDuration: 5000,
               videoQuality: Titanium.Media.QUALITY_HIGH
           });
       }
       
       btn_cam1.addEventListener("click", onClickCam);
       btn_cam2.addEventListener("click", onClickCam2);
       btn_cam3.addEventListener("click", onClickCam2);
       btn_cam4.addEventListener("click", onClickCam2);
       btn_cam5.addEventListener("click", onClickCam2);
       
       win.add(btn_cam1);
       win.add(btn_cam2);
       win.add(btn_cam3);
       win.add(btn_cam4);
       win.add(btn_cam5);
       win.add(movie);
       win.open();
       
    !http://www.migaweb.de/ti_video_example.png! Added documentation and extended the example
  7. Michael Gangolf 2016-04-10

    Tested on: * Nexus 4 (5.1.1) * HTC A9 (6.0.1) * Samsung Galaxy S2 (4.2.2)
  8. Ashraf Abu 2016-04-26

    PR by [~michael] https://github.com/appcelerator/titanium_mobile/pull/7929 Merged. Additional PR for minor code formatting: https://github.com/appcelerator/titanium_mobile/pull/7965
  9. Ashraf Abu 2016-04-26

    Additional note: For android 6.0, for the Video to record sound as well, you would need to grant the permission android.permission.RECORD_AUDIO
  10. Ashraf Abu 2016-04-27

    Test app code including permission requests that is needed in Android 6.0:-
        var isRecording = false;
        var isPhoto = false; // photo or video mode
        
        var win = Ti.UI.createWindow({
            backgroundColor: "#fff"
        });
        
        var btn_cam1 = Ti.UI.createButton({
            bottom: 10,
            title: "CAM INTENT"
        });
        
        var btn_cam2 = Ti.UI.createButton({
            bottom: 50,
            title: "CAM OVERLAY REAR",
            id: "cam_rear"
        });
        var btn_cam3 = Ti.UI.createButton({
            bottom: 90,
            title: "CAM OVERLAY FRONT",
            id: "cam_front"
        });
        
        var btn_cam4 = Ti.UI.createButton({
            bottom: 130,
            title: "PHOTO REAR",
            id: "photo_rear"
        });
        var btn_cam5 = Ti.UI.createButton({
            bottom: 170,
            title: "PHOTO FRONT",
            id: "photo_front"
        });
        
        var btnCamera = Ti.UI.createButton({
            title: 'RECORD',
            bottom: 10
        });
        
        var btnCameraClose = Ti.UI.createButton({
            title: 'CLOSE',
            top: 10
        });
        
        var overlay = Ti.UI.createView({
            top: 0,
            right: 0,
            bottom: 0,
            left: 0
        });
        
        var movie = Titanium.Media.createVideoPlayer({
            movieControlStyle: Titanium.Media.VIDEO_CONTROL_EMBEDDED,
            top: 0,
            height: 200,
            width: 200,
            backgroundColor: "#000",
            autoplay:false
        });
        
        
        overlay.add(btnCamera);
        overlay.add(btnCameraClose);
        
        btnCameraClose.addEventListener('click', function(e) {
            Titanium.Media.hideCamera();
        });
        
        btnCamera.addEventListener('click', function(e) {
            if (isPhoto){
                // photo mode
                Titanium.Media.takePicture();
            } else {
                // video mode
                if (!isRecording) {
                    Titanium.Media.startVideoCapture();
                    isRecording = true;
                    btnCamera.title = "STOP";
                } else {
                    Titanium.Media.stopVideoCapture();
                }
            }
        });
        
        function onClickCam(e) {
            // intent
            Ti.Media.showCamera({
                autohide: false,
                animated: false,
                allowEditing: false,
                saveToPhotoGallery: true,
                success: function(event) {
                    movie.url = event.media.nativePath;
                },
                cancel: function(event) {
                    console.log("error");
                },
                error: function(error) {
                    alert('error');
                },
                mediaTypes: [Titanium.Media.MEDIA_TYPE_VIDEO],
                videoMaximumDuration: 5000,
                videoQuality: Titanium.Media.QUALITY_HIGH
            });
        }
        
        
        function onClickCam2(e) {
            // native camera
            var which = Ti.Media.CAMERA_REAR;
            var type = Titanium.Media.MEDIA_TYPE_VIDEO;
            var autohide = false;
            isPhoto = false;
        
            if (e.source.id == "cam_front") {
                which = Ti.Media.CAMERA_FRONT;
            }
            if (e.source.id=="photo_front") {
                which = Ti.Media.CAMERA_FRONT;
                type = Ti.Media.MEDIA_TYPE_PHOTO;
                isPhoto = true;
                autohide = true;
            }
            if (e.source.id=="photo_rear") {
                type = Ti.Media.MEDIA_TYPE_PHOTO;
                isPhoto = true;
                autohide = true;
            }
        
            console.log(type + " " + which);
        
            Ti.Media.showCamera({
                overlay: overlay,
                autohide: autohide,
                animated: false,
                allowEditing: false,
                saveToPhotoGallery: true,
                whichCamera: which,
                success: function(event) {
                    if (!isPhoto) movie.url = event.media.nativePath;
                    isRecording = false;
                    btnCamera.title = "RECORD";
                },
                cancel: function(event) {
                    console.log("error");
                },
                error: function(error) {
                    alert('error');
                },
                mediaTypes: [type],
                videoMaximumDuration: 5000,
                videoQuality: Titanium.Media.QUALITY_HIGH
            });
        }
        
        btn_cam1.addEventListener("click", onClickCam);
        btn_cam2.addEventListener("click", onClickCam2);
        btn_cam3.addEventListener("click", onClickCam2);
        btn_cam4.addEventListener("click", onClickCam2);
        btn_cam5.addEventListener("click", onClickCam2);
        
        win.add(btn_cam1);
        win.add(btn_cam2);
        win.add(btn_cam3);
        win.add(btn_cam4);
        win.add(btn_cam5);
        win.add(movie);
        
        
        win.open();
        
        var permissionsToRequest = [];
        
        var audioPermission = "android.permission.RECORD_AUDIO";
        var hasAudioPerm = Ti.Android.hasPermission(audioPermission);
        if (!hasAudioPerm) {
            permissionsToRequest.push(audioPermission);
        } 
        
        var cameraPermission = "android.permission.CAMERA";
        var hasCameraPerm = Ti.Android.hasPermission(cameraPermission);
        if (!hasCameraPerm) {
            permissionsToRequest.push(cameraPermission);
        }
        
        var storagePermission = "android.permission.READ_EXTERNAL_STORAGE";
        var hasStoragePerm = Ti.Android.hasPermission(storagePermission);
        if (!hasStoragePerm) {
            permissionsToRequest.push(storagePermission);
        }
        
        if (permissionsToRequest.length > 0) {
            Ti.Android.requestPermissions(permissionsToRequest, function(e) {
                if (e.success) {
                    Ti.API.info("SUCCESS");
                } else {
                    Ti.API.info("ERROR: " + e.error);
                }
            });
        }
        
  11. Lokesh Choudhary 2016-07-12

    Verified the implementation. Video recording works as expected. Closing. Environment: Appc Studio : 4.7.0.201607111053 Ti SDK : 5.4.0.v20160712013704 Ti CLI : 5.0.9 Alloy : 1.9.1 MAC El Capitan : 10.11.5 Appc NPM : 4.2.8-1 Appc CLI : 5.4.0-31 Node: 4.4.4 Nexus 6 - Android 6.0.1

JSON Source