I am trying to implement my first phonegap plugin (version 2.3) on iOS - but the call of the native function seems not to work.
My plugin is based on this introduction:
http://docs.phonegap.com/en/2.3.0/guide_plugin-development_ios_index.md.html#Developing%20a%20Plugin%20on%20iOS
So I added to the plugins-section of config.xml:
<plugin name="Echo" value="Echo" />
my calling javascript:
$(document).ready (function (){
$('#testBtn').submit(function () {
alert("test");
var param = ["a", false];
cordova.exec(
function(winParam) { alert("ok"); },
function(err) { alert("error"); },
"Echo", "echo", param);
return false;
});
}
(the alert in the first row gets called by pushing my testBtn, so the rest should also be executed...)
In my plugins-directory:
Echo.h:
#import <Cordova/CDV.h>
#interface Echo : CDVPlugin
- (void)echo:(CDVInvokedUrlCommand*)command;
#end
Echo.m:
#import "Echo.h"
#implementation Echo
- (void)echo:(CDVInvokedUrlCommand*)command
{
NSLog(#"echo!");
}
#end
The echo-Function in Echo.m never gets called ... can anyone tell me why? I don't get any error messages - just nothing happens...
I was struggling in this step like you. then I Called that javascript function after device getting ready. Problem has solved. Now, Its working fine...
Related
Using nativescript-webview-interface and event is registered to webview. Event is fired to app and it is working fine. But in nativescript 6 same code is not working.
var webViewInterfaceModule = require('nativescript-webview-interface');
exports.onWebViewLoaded = function(args) {
var webview = args.object;
oWebViewInterface = new webViewInterfaceModule.WebViewInterface(webview, buildSrc());
// where build source returns the html string
webview.on(webViewModule.WebView.loadFinishedEvent, (args) => {
//do something specific to app
});
oWebViewInterface.on("watchInc", (data) => {
console.log("event watchInc - want to do something app specific");
//not receiving this event
});
oWebViewInterface.on("watchEnd", (data) => {
console.log("event watchEnd - want to do something app specific");
//not receiving this event
}, 200); // Timeout needed as loading event is fired when nothing ready...
}
Thanks manoj. Moved to nativescript-webview-ext plugin and communication between webview and javascript is working fine.
I am currently using, IONIC v1.0.0, AngularJs and ngCordova v0.1.23-alpha on IOS and Android.
I have come across an issue with my login view freezing up.
It happens after opening InAppBrowser and hitting "back to app" (close button caption used for IOS to get back) is freezes my login view disabling the ability to touch on the whole screen and making me unable to login. It only happens if I call InAppBrowser when starting the app, if I use it during the app life cycle (after login in), it doesn't do it.
Here are some of my code pieces
In app.js:
angular.module('MyApp', ['ionic', 'MyApp', 'ngCordova', 'mainController', 'loginController', 'pascalprecht.translate', 'ngStorage', 'ngSanitize', 'ngAnimate', 'ngTouch', 'ngCookies', 'ngLocale', 'testController'])
In mainController I have Factory:
.factory('customMainFunction', function ($rootScope, $ionicLoading, $ionicScrollDelegate, $ionicPopup,
$timeout, $localStorage, $location, $ionicHistory, $window, $cordovaInAppBrowser) {
var Token = "";
return {
openBrowser: function (link) {
var options = {
location: 'yes',
clearcache: 'yes',
toolbar: 'yes',
closebuttoncaption: 'Back to App'
};
document.addEventListener("deviceready", function () {
$cordovaInAppBrowser.open(link, '_blank', options)
.then(function (event) {
// success
})
.catch(function (event) {
// error
});
}, false);
$rootScope.$on('$cordovaInAppBrowser:loadstart', function (e, event) {
//console.log(event);
var url = "";
var positionNumber;
var res;
url = event.url;
positionNumber = url.search("ssoToken=");
res = url.substr(Number(positionNumber)+9);
/*positionNumber = url.search("module=");
res = url.substr(Number(positionNumber)+6);*/
if(url !== "" && positionNumber >= 0 && res.length > 0) {
$rootScope.$broadcast('ssoToken', { token: res });
$cordovaInAppBrowser.close();
}
});
$rootScope.$on('$cordovaInAppBrowser:loadstop', function (e, event) {
console.log("loadstop");
//console.log(event);
// insert CSS via code / file
//$cordovaInAppBrowser.insertCSS({
// code: ''
//});
// insert Javascript via code / file
//$cordovaInAppBrowser.executeScript({
// file: ''
//});
});
$rootScope.$on('$cordovaInAppBrowser:loaderror', function (e, event) {
});
$rootScope.$on('$cordovaInAppBrowser:exit', function (e, event) {
});
}
}
})
If anybody has encounter such issue please let me know what can be done to resolve it. Any question or clarifications let me know. Thanks in advance.
Found the issue of my own problem. Basically the problem is related to Threading. Look for Threading. How did I find out about it? On XCode I was able to see a message saying:
THREAD WARNING: ['InAppBrowser'] took '108.12' ms. Plugin should use a
background thread
There are two ways to solve this (I believe):
1- Using background threading (just like the message states). Please refer to:
How to run cordova plugins in the background?
2- Wrap the openBrowser function call (in my case) in a setTimeout. That will delay the call until the thread is done and UI won't be blocked. Once done (in my case) it opened the inAppBrowser and when I hit "Back to app" UI was not block at all.
Hope this helps someone out there.
I'm working on a Phonegap/Cordova(version 2.9.0) custom plugin creation for iOS app. My steps are as follows :
I created a HelloPlugin.js file and copy it under www/js/ folder, its having code :
var HelloPlugin =
{
callNativeFunction: function (success, fail, resultType)
{
alert('a');
return Cordova.exec( success, fail, "HelloPlugin", "nativeFunction", ['1']);
}
};
I created HelloPlugin.h and HelloPlugin.m files under plugins folder, code :
// .h
#import <Cordova/CDVPlugin.h>
#interface HelloPlugin : CDVPlugin
- (void)nativeFunction:(CDVInvokedUrlCommand*)command;
#end
// .m
#import "HelloPlugin.h"
#implementation HelloPlugin
- (void)nativeFunction:(CDVInvokedUrlCommand*)command
{
NSLog(#"Hello, this is a native function called from PhoneGap/Cordova!");
}
#end
I added following code to config.xml file :
<feature name="HelloPlugin">
<param name="ios-package" value="CDVPlugin"/>
</feature>
At last I modified index.html in following way :
Script reference added. ()
JS code added :
function callNativePlugin(returnSuccess)
{
HelloPlugin.callNativeFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess );
}
function nativePluginResultHandler (result) {
alert("SUCCESS: \r\n"+result );
}
function nativePluginErrorHandler (error) {
alert("ERROR: \r\n"+error );
}
Two buttons added and function called:
"callNativePlugin('success');"
"callNativePlugin('error');"
I hope this is the only required things I need to do for activating plugin.
Issue : While running the app, I am getting FAILED pluginJSON error on console.
Output :
-[CDVCommandQueue executePending] [Line 116] FAILED pluginJSON = [
"HelloPlugin2650437",
"HelloPlugin",
"nativeFunction",
[
"1",
"1",
"1"
]
]
What mistake I have done, please let me know. I really Appreciate your efforts. Please help me here.
First thing that jumped out is your plugin package name. It should be your iOS class name which is "HelloPlugin".
<param name="ios-package" value="HelloPlugin"/>
One of the purpose of the new way of referencing plugin is to allow flexibility and backward compatibility of plugin names especially on Android. Example:
<feature name="HelloPlugin">
<param name="ios-package" value="HelloCDVPlugin"/>
<param name="android-package" value="com.phonegap.plugins.HelloCDVPlugin"/>
</feature>
Where "HelloCDVPlugin" is your iOS class name and "com.phonegap.plugins.HelloCDVPlugin" is your Android class name.
Use below code for js
cordova.define("cordova/plugin/hello",
function (require, exports, module) {
var exec = require('cordova/exec');
function greet(name, win, fail) {
exec(win, fail, "Hello",
"greet", [name]);
}
module.exports = {
greet: greet
}
}
);
and change cordova.exec to
exec(this.callbacks.onSuccess, this.callbacks.onError, "Hello", "greet", [defaults]);
You can find example from below link
https://github.com/cristobal/phonegap-ios-datepicker-plugin
You have to modify the code as per your requirement.
I have some values generated from my native code that I would like to pass to phonegap. These data are generated in real time and are not directly influenced by the user's actions through the phonegap gui.My native code is part of a plugin that I made.
What is the best way to approach this? I want to have a function to send data over anytime and have a listener on the cordova side. I'm using Cordova 1.5 with Xcode 4.3.
Here is what I have so far:
swipe.js:
var swipe={
callNativeFunction: function (success, fail, resultType) {
return Cordova.exec( success, fail,
"ca.swipe",
"nativeFunction",
[resultType]); }
};
index.html:
...
function callNativePlugin( returnSuccess ) {
swipe.callNativeFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess );
}
function nativePluginResultHandler (result) {
alert("SUCCESS: \r\n"+result );
}
function nativePluginErrorHandler (error) {
alert("ERROR: \r\n"+error );
} ... <body onload="onBodyLoad()"> <h1>Hey, it's Cordova!</h1>
<button onclick="callNativePlugin('success');">Success</button>
<button onclick="callNativePlugin('error');">Fail</button>
</body> ...
swipe.h:
...
#interface swipe : CDVPlugin
- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
#end
swipe.m:
...
- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options {
NSLog(#"Hello, this is a native function called from PhoneGap/Cordova!");
//get the callback id
NSString *callbackId = [arguments pop];
NSString *resultType = [arguments objectAtIndex:0];
NSMutableArray *GlobalArg=arguments;
CDVPluginResult *result;
if ( [resultType isEqualToString:#"success"] ) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: #"Success :)"];
//writes back the smiley face to phone gap.
[self writeJavascript:[result toSuccessCallbackString:callbackId]];
}
...
The code that I have right now has nothing for doing what I want. I'm not really sure how to setup the code in both cordova and native.
Sounds like you need to be able to talk back down to PhoneGap from objective C, in which case you should be able to use something like:
NSString *jsResult = [theWebView stringByEvaluatingJavaScriptFromString:#"hello()"];
NSLog(#"jsResult=%#",jsResult);
And if you have a JS function like "hello" in your index.html like this:
function hello(){return "hello";}
Its a way of talking back to your PhoneGap web layer
create a class of type CDVPlugin
import #import in that class
initialize a handler method .h class
- (void)Device:(CDVInvokedUrlCommand *)command;
and implement the method in .m class
- (void)openDevice:(CDVInvokedUrlCommand *)command{
CDVPluginResult *pluginResult = nil;
BOOL checkOpenDevice=NO;
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:checkOpenDevice];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
}
in this way through self.commandDelegate your data will be able to reach to the cordova class
if the .js file hit(calls) that particular method which is initialized in .h class.
This is all the code I have and I do not get neither the logs in xcode nor the deviceReady event (which I don't get on any other platform either. On Ubuntu+Android+Eclipse I do get the console logs, but no deviceReady. nor in chrome )
The js/cordova-1.5.0.js exists and being loaded as indicates an alert statement i've put in there.
Any clues where should I look ?
Thanks in advance ;)
<div id="d"></div>
<script>
function foo() {console.log('test'); document.getElementById('d').innerHTML += 'called';}
window.setTimeout(foo, 5000);
window.setTimeout(foo, 15000);
window.setTimeout(foo, 25000);
window.setTimeout(foo, 35000);
alert('hi');
console.log('non timed console.log');
</script>
<script src="js/cordova-1.5.0.js"></script>
<script>
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
alert('deviceReady');
//somewhy this never happens
}
</script>
Console.log works only after deviceReady event
Phonegap uses different phonegap.js files for android and ios, and only the
android one is distributed with the downloadable archive. Read
Dhaval's comment to learn where to get the ios version.
I used Weinre for debugging and almost missed that it overrides the console.log method,
therefore console.log doesn't work with weinre
As Alex pointed out, console.log is not available until after your PhoneGap device is ready. By calling it too soon, you're triggering a reference error.
Remove ALL of your existing javascript, and try this instead (replacing the alert on the second-last line with your own custom code):
var app = {
// denotes whether we are within a mobile device (otherwise we're in a browser)
iAmPhoneGap: false,
// how long should we wait for PhoneGap to say the device is ready.
howPatientAreWe: 10000,
// id of the 'too_impatient' timeout
timeoutID: null,
// id of the 'impatience_remaining' interval reporting.
impatienceProgressIntervalID: null,
// Application Constructor
initialize: function() {
this.bindEvents();
},
// Bind Event Listeners
//
// Bind any events that are required on startup. Common events are:
// `load`, `deviceready`, `offline`, and `online`.
bindEvents: function() {
document.addEventListener('deviceready', this.onDeviceReady, false);
// after 10 seconds, if we still think we're NOT phonegap, give up.
app.timeoutID = window.setTimeout(function(appReference) {
if (!app.iAmPhoneGap) // jeepers, this has taken too long.
// manually trigger (fudge) the receivedEvent() method.
appReference.receivedEvent('too_impatient');
}, howPatientAreWe, this);
// keep us updated on the console about how much longer to wait.
app.impatienceProgressIntervalID = window.setInterval(function areWeThereYet() {
if (typeof areWeThereYet.howLongLeft == "undefined") {
areWeThereYet.howLongLeft = app.howPatientAreWe; // create a static variable
}
areWeThereYet.howLongLeft -= 1000; // not so much longer to wait.
console.log("areWeThereYet: Will give PhoneGap another " + areWeThereYet.howLongLeft + "ms");
}, 1000);
},
// deviceready Event Handler
//
// The scope of `this` is the event. In order to call the `receivedEvent`
// function, we must explicity call `app.receivedEvent(...);`
onDeviceReady: function() {
app.iAmPhoneGap = true; // We have a device.
app.receivedEvent('deviceready');
// clear the 'too_impatient' timeout .
window.clearTimeout(app.timeoutID);
},
// Update DOM on a Received Event
receivedEvent: function(id) {
// clear the "areWeThereYet" reporting.
window.clearInterval(app.impatienceProgressIntervalID);
console.log('Received Event: ' + id);
myCustomJS(app.iAmPhoneGap); // run my application.
}
};
app.initialize();
function myCustomJS(trueIfIAmPhoneGap) {
// put your custom javascript here.
alert("I am "+ (trueIfIAmPhoneGap?"PhoneGap":"a Browser"));
}
I know the question was asked 9 month before but I stumbled over the same problem.
If you want debug messages to appear in the weinre console you have to call:
window.cordova.logger.useConsole(false);
after deviceready.
Update:
It seems that you need luck to get console messages into weinre - thats bad :(