Media is not playing in iOS phonegap 1.5 app - ios

I am developing iOS app using phonegap 1.5. In this app I am using phonegap's Media API to play mp3 files. But it's not working on iOS. Same codebase works on Android without any issue.
Code:
Audio.js
//
var my_media = null;
var mediaTimer = null;
function playAudio(src) {
//alert("inside");
//if (my_media == null) {
// Create Media object from src
my_media = new Media(src, onSuccess, onError);
//alert(my_media);
//} // else play current audio
// Play audio
my_media.play();
//alert("Played");
}
function onSuccess() {
console.log("playAudio():Audio Success");
}
// onError Callback
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
I am including Audio.js in my html file and then calling function
playAudio("audio/welcome.mp3");
All of my mp3 files reside in www/audio folder.
I debugged using alert statements, call comes till this line of code
my_media = new Media(src, onSuccess, onError);
No error callback or no errors in console of xcode.
Am I missing something here? What could be the issue?

Phonegap is pretty difficult with having stuff behaving differently that it should, especially when it comes to media and plugins. You need to have something that changes the file path based off of the device (using the Cordova Device Plugin):
//Gets Device Platform
document.addEventListener("deviceready", getDevicePlatform, false);
function getDevicePlatform() {
$scope.devicePlatform = device.platform;
console.log(device.platform);
}
Then to set the media player file path correctly:
if ($scope.devicePlatform == "Android") {
var songFilePath = '/android_asset/www/res/' + song.name + '.mp3';
}
else {
var songFilePath = 'res/' + song.name + '.mp3';
}
$scope.song = new Media(songFilePath);
The song .name is something special I had to dynamically get the path, but the main thing is that for Android devices you need the /android_asset/, but for other devices like iOS and PhoneGap you can use normal file paths to media inside the /www folder.

Related

Youtube video with hyphen not working in IOS

I am using Cordova YoutubeVideoPlayer Plugin in my ionic project. It works well in android.But in IOS, it is not working with video id having a hyphen(-) in it(eg: "6L-ZHjUhcQY"). It works fine with all other urls. How can I solve this.
.controller('menuController', function () {
var id = "6L-ZHjUhcQY";
YoutubeVideoPlayer.openVideo(id);
});
In the debugger, are the video ids with hyphens correctly saved in the variable? It might be a character encoding issue, or an issue with the plug-in itself.
Fixed the ios issue by updating some files
https://github.com/fingentffts/CordovaYoutubeVideoPlayer
Now I found some issue in android tabs.
Videos are playing even if the screen is locked. And also hyphen video are not playing in samsung tab.
android issue also fixed by editing code in YoutubeVideoPlayer.java file in plugin
private Intent createYoutubeIntent(String videoId) {
// if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){
Intent intent;
Context cordovaContext = cordova.getActivity();
String version = YouTubeIntents.getInstalledYouTubeVersionName(cordovaContext);
if(version != null && version.startsWith("11.16") && YouTubeIntents.canResolvePlayVideoIntent(cordovaContext)) {
intent = YouTubeIntents.createPlayVideoIntent(cordovaContext, videoId);
} else {
if(YouTubeIntents.canResolvePlayVideoIntentWithOptions(cordovaContext)){
intent = YouTubeIntents.createPlayVideoIntentWithOptions(cordovaContext, videoId, true, true);
} else {
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.youtube.com/watch?v=" + videoId), cordovaContext, YouTubeActivity.class);
intent.putExtra("videoId", videoId);
ConfigXmlParser parser = new ConfigXmlParser();
parser.parse(cordovaContext);
CordovaPreferences prefs = parser.getPreferences();
intent.putExtra("YouTubeApiId", prefs.getString("YouTubeDataApiKey","YOUTUBE_API_KEY"));
}
}
return intent;
// }
//return new Intent(null, Uri.parse("ytv://" + videoId), cordova.getActivity(), OpenYouTubePlayerActivity.class);
}

Cordova iOS Video tag Local File Source

I have problem playing local video on iOS on my Cordova based app. At the beginning I want to stress out that this problem is happening only when I'm using WKWebView, and if UiWebView is used, video plays fine. This is scenario I have:
-User comes to screen to which video url is passed
-Via FileTransfer I download it to phone and store it at desired location
-Using JS video is loaded to <video> tag and played.
Basically I'm doing everything as described in answer to this SO question.
The problem with UiWebView was that if relative path was set to src, video for some reason couldn't be loaded (no matter which combination I used), so this solution worked great for me, because it is based on this line of code:
entry.toURL()
This returns full path of the downloaded video which is great, at least for the UiWebView.
The problem for WkWebView is that entry.toURL() returns smth. like this:
file:///var/mobile/Containers/Data/Application/3A43AFB5-BEF6-4A0C-BBDB-FC7D2D98BEE9/Documents/videos/Dips.mp4
And WKWebView doesn't work with file:// protocol. Also, neither WKWebView works wit relative paths :(
Can anyone help me to fix this ?
I got this working today with the following but only when deployed to my device in Release mode. When deploying the app in Debug mode to my device it would not work.
iOS 9.3.2
Cordova 4.0.0 (iOS 3.8.0)
Telerik WKWebView Polyfill 0.6.9
Video list load method:
var path = window.cordova.file.documentsDirectory, //iTunes File Sharing directory
href = 'http://localhost:12344/Documents', //WKWebView default server url to documents
list = [];
function fsSuccess(dir) {
var reader = dir.createReader();
reader.readEntries(function (entries) {
for (var i = 0; i < entries.length; i++) {
list.push({ name: entries[i].name, path: href + entries[i].fullPath });
}
});
}
function fsError(error) {
console.log('error', error)
}
window.resolveLocalFileSystemURL(path, fsSuccess, fsError);
Video list click handler:
var video = $('#video')[0],
source = $('#source');
function play(index) {
source.attr('src', list[index].path);
video.load();
video.play();
}
Video player markup:
<video id="video" autoplay controls loop webkit-playsinline>
<source id="source" type="video/mp4" />
</video>
I was banging my head on my desk a la Ren Hoek while debugging until I attempted a release buid and it worked.
Sample snippet that uses cordova file opener plugin to open the download file from device.(Not tested in WKWebView though)
var fileTransfer = new FileTransfer();
var cdr;
if (sessionStorage.platform.toLowerCase() == "android") {
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, onFileSystemSuccess, onError);
} else {
// for iOS
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemSuccess, onError);
}
function onError(e) {
navigator.notification.alert("Error : Downloading Failed");
};
function onFileSystemSuccess(fileSystem) {
var entry = "";
if (sessionStorage.platform.toLowerCase() == "android") {
entry = fileSystem;
} else {
entry = fileSystem.root;
}
entry.getDirectory("Cordova", {
create: true,
exclusive: false
}, onGetDirectorySuccess, onGetDirectoryFail);
};
function onGetDirectorySuccess(dir) {
cdr = dir;
dir.getFile(filename, {
create: true,
exclusive: false
}, gotFileEntry, errorHandler);
};
function gotFileEntry(fileEntry) {
// URL in which the pdf is available
var documentUrl = "http://localhost:8080/testapp/test.pdf";
var uri = encodeURI(documentUrl);
fileTransfer.download(uri, cdr.nativeURL + "test.pdf",
function(entry) {
// Logic to open file using file opener plugin
openFile();
},
function(error) {
navigator.notification.alert(ajaxErrorMsg);
},
false
);
};
function openFile() {
cordova.plugins.fileOpener2.open(
cdr.nativeURL + "test.pdf",
"application/pdf", //mimetype
{
error: function(e) {
navigator.notification.alert("Error Opening the File.Unsupported document format.");
},
success: function() {
// success callback handler
}
}
);
};

How to play an audio file through Ionic on iOS?

I am using cordovo media plugin to play an audio file on button click. It is working fine on Android but I don't understand the problem with iOS. Here is the code inside a controller:
var url = '';
if(ionic.Platform.isAndroid() == true){
url = "/android_asset/www/sound.wav";
}else{
url = "sound.wav";
}
$scope.playAudio = function() {
// Play the audio file at url
var my_media = new Media(url,
// success callback
function () {
console.log("playAudio():Audio Success");
},
// error callback
function (err) {
console.log("playAudio():Audio Error: " + JSON.stringify(err));
}
);
console.log("Play");
// Play audio
my_media.play();
}
I have spent many of my hours to figure out the problem, but I have no idea what has gone wrong. I will be genuinely thankful to you if you can help me out.
Thanks in advance.

Distorted audio in iOS 7.1 with WebAudio API

On iOS 7.1, I keep getting a buzzing / noisy / distorted sound when playing back audio using the Web Audio API. It sounds distorted like this, in place of normal like this.
The same files are fine when using HTML5 audio. It all works fine on desktop (Firefox, Chrome, Safari.)
EDIT:
The audio is distorted in the iOS Simulator versions iOS 7.1, 8.1, 8.2. The buzzing sound often starts before I even playback anything.
The audio is distorted on a physical iPhone running iOS 7.1, in both Chrome and Safari.
The audio is fine on a physical iPhone running iOS 8.1, in both Chrome and Safari.
i.e.: the buzzing audio is on iOS 7.1. only.
Howler.js is not the issue. The problem is still there using pure JS like so:
var context;
var sound;
var extension = '.' + ( new Audio().canPlayType( 'audio/ogg' ) !== '' ? 'ogg' : 'mp3');
/** Test for WebAudio API support **/
try {
// still needed for Safari
window.AudioContext = window.AudioContext || window.webkitAudioContext;
// create an AudioContext
context = new AudioContext();
} catch(e) {
// API not supported
throw new Error( 'Web Audio API not supported.' );
}
function loadSound( url ) {
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.responseType = 'arraybuffer';
request.onload = function() {
// request.response is encoded... so decode it now
context.decodeAudioData( request.response, function( buffer ) {
sound = buffer;
}, function( err ) {
throw new Error( err );
});
}
request.send();
}
function playSound(buffer) {
var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start(0);
}
loadSound( '/tests/Assets/Audio/En-us-hello' + extension );
$(document).ready(function(){
$( '#clickme' ).click( function( event ) {
playSound(sound);
});
}); /* END .ready() */
A live version of this code is available here: Web Audio API - Hello world
Google did not bring up any result about such a distorted sound issue on iOS 7.1.
Has anyone else run into it? Should I file a bug report to Apple?
I believe the issue is caused due to resetting the audioContext.sampleRate prop, which seem to happen after the browser/OS plays something recorded in a different sampling rate.
I've devised the following workaround, which basically silently plays a short wav file recorded in the sampling rate that the device currently does playback on:
"use strict";
var getData = function( context, filePath, callback ) {
var source = context.createBufferSource(),
request = new XMLHttpRequest();
request.open( "GET", filePath, true );
request.responseType = "arraybuffer";
request.onload = function() {
var audioData = request.response;
context.decodeAudioData(
audioData,
function( buffer ) {
source.buffer = buffer;
callback( source );
},
function( e ) {
console.log( "Error with decoding audio data" + e.err );
}
);
};
request.send();
};
module.exports = function() {
var AudioContext = window.AudioContext || window.webkitAudioContext,
context = new AudioContext();
getData(
context,
"path/to/short/file.wav",
function( bufferSource ) {
var gain = context.createGain();
gain.gain.value = 0;
bufferSource.connect( gain );
gain.connect( context.destination );
bufferSource.start( 0 );
}
);
};
Obviously, if some of the devices have different sampling rates, you would need to detect and use a specific file for every rate.
it looks like iOS6+ Safari defaults to a sample rate of 48000. If you type this into the developer console when you first open mobile safari, you'll get 48000:
var ctx = new window.webkitAudioContext();
console.log(ctx.sampleRate);
Further Reference: https://forums.developer.apple.com/thread/20677
Then if you close the initial context on load: ctx.close(), the next created context will use the sample rate most other browsers use (44100) and sound will play without distortion.
Credit to this for pointing me in the right direction (and in case the above no longer works in the future): https://github.com/Jam3/ios-safe-audio-context/blob/master/index.js
function as of post date:
function createAudioContext (desiredSampleRate) {
var AudioCtor = window.AudioContext || window.webkitAudioContext
desiredSampleRate = typeof desiredSampleRate === 'number'
? desiredSampleRate
: 44100
var context = new AudioCtor()
// Check if hack is necessary. Only occurs in iOS6+ devices
// and only when you first boot the iPhone, or play a audio/video
// with a different sample rate
if (/(iPhone|iPad)/i.test(navigator.userAgent) &&
context.sampleRate !== desiredSampleRate) {
var buffer = context.createBuffer(1, 1, desiredSampleRate)
var dummy = context.createBufferSource()
dummy.buffer = buffer
dummy.connect(context.destination)
dummy.start(0)
dummy.disconnect()
context.close() // dispose old context
context = new AudioCtor()
}
return context
}

Is there support to Capture Video with Sound in phonegap (cordova)?

Is there support to Capture Video with Sound in phonegap (cordova)?
I checked on my iPad a phonegap 3.1 app whit Video Capture and no sound recording with the video
appreciate help
Thanks
function uploadFile(mediaFile) {
var ft = new FileTransfer(),
path = mediaFile.fullPath,
name = mediaFile.name;
ft.upload(path,
"http://www/api/up_video",
function(result) {
cordova.logger.log('Upload success: ' + result.responseCode);
cordova.logger.log(result.bytesSent + ' bytes sent');
},
function(error) {
cordova.logger.log('Error uploading file ' + path + ': ' + error.code);
},
{ fileName: name });
}
// capture callback
var captureSuccess = function(mediaFiles) {
var i, path, len;
for (i = 0, len = mediaFiles.length; i < len; i += 1) {
path = mediaFiles[i].fullPath;
name = mediaFiles[i].name;
// do something interesting with the file
alert(name);
//alert(mediaFiles[i].size);
//alert(mediaFiles[i].type);
uploadFile(mediaFiles[i]);
}
};
// capture error callback
var captureError = function(error) {
navigator.notification.alert('Error code: ' + error.code, null, 'Capture Error');
cordova.logger.log( error);
};
navigator.device.capture.captureVideo(captureSuccess, captureError, {duration:6});
Absolutely. Both video and sound can be captured using Phonegap's "Capture" API. See documentation here.
Edit based on comments:
You are never telling the device to capture audio. The capture of Video and Audio are different operations. You need to also call the navigator.device.capture.captureAudio function. See here.

Resources