3

I got iphone/ipad to work fine with the Titanium.Media.showCamera() function. Which is great.

However the same code doesn't work on android like I expect. So I did some research and came up with this code below. The code itself works up to uploading the video. I can record, click save, but when it comes time to upload to my server, I get no communication error and on the server itself, I see no data in the POST or FILES array. The code below executes on the onclick button. I give part of the code since everything works except this. What gives?

button2.addEventListener('click', function() {
    // http://developer.android.com/reference/android/provider/MediaStore.html
    var intent = Titanium.Android.createIntent({ action: 'android.media.action.VIDEO_CAPTURE' });
    Titanium.Android.currentActivity.startActivityForResult(intent, function(e) {
        if (e.error) {
            Ti.UI.createNotification({
                duration: Ti.UI.NOTIFICATION_DURATION_LONG,
                message: 'Error: ' + e.error
            }).show();
        } else {
            if (e.resultCode === Titanium.Android.RESULT_OK) {
                var dataUri = e.intent.data;

                Titanium.Media.saveToPhotoGallery(dataUri);


                var xhr = Titanium.Network.createHTTPClient({enableKeepAlive:false});
                xhr.open('POST', 'http://someserver.com/upload.php');
                xhr.setRequestHeader("enctype", "multipart/form-data");
                xhr.setRequestHeader('Cache-Control', 'no-cache');
                xhr.onerror = function(e) {
                    alert(e.error);
                };
                xhr.onload = function() {
                    var data = JSON.parse(this.responseText);
                    if(data.FILE)
                        alert('File: '+data.FILE);
                    else
                        alert(this.responseText);
                };

                var fileData = Titanium.Filesystem.getFile(dataUri);
                var fileContent = fileData.read();
                xhr.send({video: fileContent});
            } else {
                Ti.UI.createNotification({
                    duration: Ti.UI.NOTIFICATION_DURATION_LONG,
                    message: 'Canceled/Error? Result code: ' + e.resultCode
                }).show();
            }
        }
    });
});

Also if you're interested in the php code, here it is:

<?php

file_put_contents('output.txt', print_r($_POST, true)."\n".print_r($_FILES, true));

if(empty($_FILES['video']))
        die('invalid');

@move_uploaded_file($_FILES['video']['tmp_name'], $_FILES['video']['name']);
echo json_encode(array('FILE' => $_FILES['video']['name']));
user1207047
  • 61
  • 1
  • 6
  • I found a solution. Basically you just need to copy the uri file to an existing file. I'll post a solution later in the day for others who have the same issue. – user1207047 Feb 13 '12 at 17:04

1 Answers1

2

Okay figured it out. The issue is the file is a uri, and the code doesn't read uri on the file system. With that said, you'll have to copy the file to a new file and then use that new file to upload to a server.

The solution below works for me:

button2.addEventListener('click', function() {
    // http://developer.android.com/reference/android/provider/MediaStore.html
    var intent = Titanium.Android.createIntent({ action: 'android.media.action.VIDEO_CAPTURE' });
    Titanium.Android.currentActivity.startActivityForResult(intent, function(e) {
        if (e.error) {
            Ti.UI.createNotification({
                duration: Ti.UI.NOTIFICATION_DURATION_LONG,
                message: 'Error: ' + e.error
            }).show();
        } else {
            if (e.resultCode === Titanium.Android.RESULT_OK) {
                var dataUri = e.intent.data;




                var xhr = Titanium.Network.createHTTPClient({enableKeepAlive:false});
                xhr.open('POST', 'http://something.com/video/uploader.php');
                xhr.setRequestHeader("enctype", "multipart/form-data");
                xhr.setRequestHeader('Cache-Control', 'no-cache');
                xhr.onerror = function(e) {
                    alert(e.error);
                };
                xhr.onload = function() {
                    var data = JSON.parse(this.responseText);
                    if(data.FILE)
                        alert('File: '+data.FILE);
                    else
                        alert(this.responseText);
                };

                var source = Ti.Filesystem.getFile(dataUri);
                var fileData = Ti.Filesystem.getFile('appdata://sample.3gp');
                // note: source.exists() will return false, because this is a URI into the MediaStore.
                // BUT we can still call "copy" to save the data to an actual file
                source.copy(fileData.nativePath);
                Titanium.Media.saveToPhotoGallery(fileData);
                if(fileData.exists())
                {
                    var fileContent = fileData.read();
                    if(fileContent)
                        xhr.send({video: fileContent});
                    else
                        alert('Did not get any data back from file content');
                }
                else
                    alert('Did not get a file data for : '+dataUri);
            } else {
                Ti.UI.createNotification({
                    duration: Ti.UI.NOTIFICATION_DURATION_LONG,
                    message: 'Canceled/Error? Result code: ' + e.resultCode
                }).show();
            }
        }
    });
});
user1207047
  • 61
  • 1
  • 6
  • What if large video file, titanium (3.5.1) crashes TiRemoteApp(213,0x2da3000) malloc: *** mach_vm_map(size=312246272) failed (error code=3) [INFO] : *** error: can't allocate region [INFO] : *** set a breakpoint in malloc_error_break to debug – JRC Apr 25 '15 at 08:40