I am building an with cordova.js library [version 3.4.1] and I would also like to debug it as web page directly using the web browser.
There are some issues in iOS emulator when loading dynamically the external cordova.js library [I have 2 version specific for android and iOS]
I have this piece of code in place to deal with this:
//check if mobile or local browser:
var isMobile = true;
if (document.URL.indexOf("local") > 0) {
isMobile = false;
}
var deviceReadyDeferred = $.Deferred();
var jqmReadyDeferred = $.Deferred();
function onDeviceReady () {
deviceReadyDeferred.resolve();
}
if (isMobile) {
$(document).bind('mobileinit', function () {
$.mobile.allowCrossDomainPages = true;
jqmReadyDeferred.resolve();
var useragent = navigator.userAgent;
var loadScript = function (url) {
url = url.replace(/\//, '\\/');
document.write('<script charset="utf-8" src="' + url + ' "><\/script>');
};
if (/Android/i.test(useragent)) {
$.getScript('js/lib/cordova_android.js', function (data, textStatus, jqxhr) {
document.addEventListener("deviceReady", onDeviceReady, false);
});
} else {
loadScript('js/lib/cordova_ios.js');
setTimeout(function () {
document.addEventListener("deviceReady", onDeviceReady, false);
}, 500);
}
});
} else {
jqmReadyDeferred.resolve();
onDeviceReady();
}
So when the page is requested with localhost... then the isMobile is set to false.
Is there a reason why iOS [6.1] does not load the external script like Android did [with jQuery getscript ] instead than the horrible hack ? I tried to debug and it seems that iOS is reporting status error 400 when requesting the script.
Followed the logic used in this other SO question:
Issue with dynamically loaded phonegap.js
UPDATE:
Following the suggestion of the accepted answer, I rewrote the whole function and now it is working well both in iOS / ANDROID and local browser:
var deviceReadyDeferred = $.Deferred();
var jqmReadyDeferred = $.Deferred();
(function () {
//check if mobile or local browser:
var isMobile = true;
var useragent = navigator.userAgent;
var cordova_js = 'cordova_';
if (/Android/i.test(useragent)) {
cordova_js += 'android.js'
} else if ((/iPhone/i.test(useragent)) || (/iPad/i.test(useragent))) {
cordova_js += 'ios.js'
} else {
// local browser testing
isMobile = false;
jqmReadyDeferred.resolve();
onDeviceReady();
}
if (isMobile) {
$(document).bind('mobileinit', function () {
$.mobile.allowCrossDomainPages = true;
jqmReadyDeferred.resolve();
var url = document.URL;
url = url.substring(0, url.lastIndexOf("/"));
$.getScript(url + '/js/lib/' + cordova_js, function (data, textStatus, jqxhr) {
document.addEventListener("deviceReady", onDeviceReady, false);
});
});
}
function onDeviceReady () {
deviceReadyDeferred.resolve();
}
})();
Your isMobile check is prone to break. Think of a remote URL like this:
http://www.somesite.com/local/foo/bar
And probably the "local" URL in iOS looks different. Try logging the document.URL in iOS to check, or maybe show it in an alert if console is not an option.
Related
I hope you can help me with this problem. I have tried EVERYTHING the last 5 days, but I fail every time.
I have buildt a simple app using HTML5, CSS and little bit of Javascript.The app works fine.Than I want a simple banner ad that shows at the bottom of the app.I just can't get it to work. Sometimes a black box shows up at the bottom, that's all, but not ad. I'm not very good with Javascript so the problem is maby with the code, but I've copied most of it from plugin exemple.
Source: https://www.npmjs.com/package/phonegap-admob
I'm using:
- Phonegap 6.1.2 (Build Service)
- admob-phonegap plugin(<plugin name="phonegap-admob" spec="4.2.1" />)
- Other plugins that work fine.
What I need:
- Only a small banner ad at the bottom of the page.
Platform:
- Only Andriod
In my config.xml I have this line:
<plugin name="phonegap-admob" spec="4.2.1" />
In my index.html inside the <script></script> tags, I have this code:
<script>
var isAppForeground = true;
function initAds() {
if (admob) {
var adPublisherIds = {
android : {
banner : "ca-app-pub-1467389904102750/404191XXXX",
}
};
var admobid = (/(android)/i.test(navigator.userAgent)) ? adPublisherIds.android : adPublisherIds.ios;
admob.setOptions({
publisherId: admobid.banner,
interstitialAdId: admobid.interstitial,
});
registerAdEvents();
} else {
alert('AdMobAds plugin not ready');
}
}
function onAdLoaded(e) {
if (isAppForeground) {
if (e.adType === admob.AD_TYPE.INTERSTITIAL) {
console.log("An interstitial has been loaded and autoshown. If you want to load the interstitial first and show it later, set 'autoShowInterstitial: false' in admob.setOptions() and call 'admob.showInterstitialAd();' here");
} else if (e.adType === admob.AD_TYPE_BANNER) {
console.log("New banner received");
}
}
}
function onPause() {
if (isAppForeground) {
admob.destroyBannerView();
isAppForeground = false;
}
}
function onResume() {
if (!isAppForeground) {
setTimeout(admob.createBannerView, 1);
setTimeout(admob.requestInterstitialAd, 1);
isAppForeground = true;
}
}
// optional, in case respond to events
function registerAdEvents() {
document.addEventListener(admob.events.onAdLoaded, onAdLoaded);
document.addEventListener(admob.events.onAdFailedToLoad, function (e) {});
document.addEventListener(admob.events.onAdOpened, function (e) {});
document.addEventListener(admob.events.onAdClosed, function (e) {});
document.addEventListener(admob.events.onAdLeftApplication, function (e) {});
document.addEventListener("pause", onPause, false);
document.addEventListener("resume", onResume, false);
}
function onDeviceReady() {
document.removeEventListener('deviceready', onDeviceReady, false);
initAds();
// display a banner at startup
admob.createBannerView();
}
document.addEventListener("deviceready", onDeviceReady, false);
</script>
I hope someone can help me. Thank you so much
Allright, the whole code was correct. The problem was just that I didn't link to Cordova in the Script tag. I read it somewhere that you didn't need it and Phonegap / Cordova would include it automatically. It was all that was needed. Do you want Admob to be displayed (and probably many other plugins), please include
<script type = "text / javascript" src = "cordova.js"> </script>.
I've been trying to implement the Phonegap Media plugin to playback an audio file.
I understand I'll need to refer to the correct file path (android_asset/www/...) and use an .amr file as per the docs but it's still returning with a code: 1 error, which I believe has something to do with a disruption in getting the file.
function sound(){
var backgroundMusic = null;
var musicPlaying = false;
function playAudio(){
function getPhoneGapPath() {
var devicePlatform = device.platform;
if (devicePlatform === "iOS") {
path = "";
} else if (devicePlatform === "Android" || devicePlatform === 'android') {
path = "/android_asset/www/";
}
return path;
};
var backgroundMusic = new Media(getPhoneGapPath() + 'audio/bg.amr', success, error);
function success(){
backgroundMusic.release();
alert('success');
}
function error(e){
alert(getPhoneGapPath() + 'audio/bg.amr');
alert(JSON.stringify(e));
}
if (!musicPlaying) {
backgroundMusic.play();
musicPlaying = true;
$(".audio-off").css('display', 'block');
$(".audio-on").css('display', 'none');
}
else if (musicPlaying){
backgroundMusic.stop();
musicPlaying = false;
$(".audio-on").css('display', 'block');
$(".audio-off").css('display', 'none');
};
}
$(".audio-on, .audio-off").on("touchstart", function() {
playAudio();
});
}
window.onload = function() {
document.addEventListener("deviceready", onDeviceReady, false);
}
function onDeviceReady(){
sound();
//other code...
}
After reading so many questions and tutorials I can't see where I've gone wrong. The media plugin is also definitely included in my config.xml as well.
I'm testing on my Nexus 5 with Lollipop 5.0.1.
Any help would be greatly appreciated, thanks :-)
I manage to play several sounds on Android (Cordova 4.1) but now I would like to dynamically change the volume of each video.
My code for playing sounds is the following:
function onDeviceReady() {
document.querySelector("#play").addEventListener("touchend", playMP3(), false);
function playMP3() {
var mp3_1 = getMediaURL("audio/sound1.mp3");
var mp3_2 = getMediaURL("audio/sound2.mp3");
media1 = new Media(mp3_1, null, mediaError);
media2 = new Media(mp3_2, null, mediaError);
media1.play();
media2.play();
}
function getMediaURL(s) {
if(device.platform.toLowerCase() === "android") return "/android_asset/www/" + s;
return s;
}
function mediaError(e) {
alert('Media Error');
alert(JSON.stringify(e));
}
}
Then I would like to control volume with something like media1.volume = 0.5; from outside the onDeviceReady function but I can't make it work...
Any idea of what I'm missing?
Finally, the whole package to play and control sounds with Cordova 4.1 and Android 4.4 wich worked for me. To set the volume call the function with something like onclick=setVolume(media1, "0.5")
Hope it can help !
var media1 = null;
var media2 = null;
//set volume of one sound
function setVolume(media, volume) {
if (media) {
media.setVolume(volume);
}
}
//play the 2 sounds at the same time
function playMP3() {
var mp3_1 = getMediaURL("audio/media1.mp3");
var mp3_2 = getMediaURL("audio/media2.mp3");
media1 = new Media(mp3gauche, null, mediaError);
media2 = new Media(mp3droite, null, mediaError);
media1.play();
media2.play();
}
//for android devices (need the Device Cordova plugin)
function getMediaURL(s) {
if(device.platform.toLowerCase() === "android") return "/android_asset/www/" + s;
return s;
}
//help to get log when errors occur
function mediaError(e) {
alert('Media Error');
alert(JSON.stringify(e));
}
//launch the 2 sounds when the device is ready
function onDeviceReady() {
document.querySelector("#playMp3").addEventListener("touchend", playMP3(), false);
}
i have been written this code in main.js and adding this file index.html but on android emulator events everything working correctly but on device ready event showing error on cat log that device ready event not fired i am not understanding where i am wrong is there any problem with this code .
main.js
$(document).ready(function () {
// setup global error handler
window.onerror = function (message, url, lineNumber) {
console.log([lineNumber, url, message].join(" "));
return false;
};
window.isphone = false;
if(document.URL.indexOf("http://") === -1
&& document.URL.indexOf("https://") === -1) {
window.isphone = true;
}
if(window.isphone) {
document.addEventListener("deviceready", onDeviceReady, false);
} else {
onDeviceReady();
}
console.log("document.ready");
console.log(window.location.hash);
// start the app
});
function onDeviceReady() {
app.init();
}
var app = app || { _timeStart: null };
app.init = function () {
//events binding
});
};
I have the following code snippet to enable extension after firefox quit,
observe: function (subject, topic, data) {
if (topic == "quit-application") {
LOG("inside quit-application Testing ");
var os = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
//os.addObserver(this, "http-on-examine-cached-response", false);
os.addObserver(this, "quit-application", false);
var appInfo = Components.classes["#mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var tempappVersion = appInfo.version;
var appVersion = tempappVersion.split(".");
// adding add-on listener dsable event on add-on for FF4 and later versions.
if (appVersion[0] >= 4) {
setAddonEnableListener();
LOG("\napp-startup Testing from javascript file....");
}
return;
}
}
And inside the setAddonEnableListener I am trying to enable the extension like this:
function setAddonEnableListener() {
try {
alert("setAddonEnableListener akbar nsListener called from ");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID("somename#extension.com", function(addon)
{
if (addon.userDisabled)
addon.userDisabled = false;
});
} catch (ex) {
}
}
And I am registering the quit-application event var like this:
myModule = {
registerSelf: function (compMgr, fileSpec, location, type) {
var compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.registerFactoryLocation(this.myCID,
this.myName,
this.myProgID,
fileSpec,
location,
type);
var catMgr = Components.classes["#mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
catMgr.addCategoryEntry("app-startup", this.myName, this.myProgID, true, true);
catMgr.addCategoryEntry("quit-application", this.myName, this.myProgID, true, true);
}
When Firefox quits, inside quit-application Testing message is not getting displayed. What am I doing wrong here?
There is no category quit-application. You should receive app-startup notification (or rather profile-after-change starting with Firefox 4) and register your observer for quit-application:
observe: function (subject, topic, data) {
if (topic == "app-startup" || topic == "profile-after-change") {
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(this, "quit-application", false);
}
else if (topic == "quit-application") {
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(this, "quit-application");
...
}
}
To quote the documentation:
Unless otherwise noted you register for the topics using the nsIObserverService.
And there is no note about registration via category manager on any shutdown notifications.
Btw, I sincerely recommend XPCOMUtils for component registration. You shouldn't need to write the module definition yourself.