I am quite new in cordova and android native code
I had created my own plugin by using plugman.
plugman create --name myCustomPlugin --plugin_id myCustomPlugin --plugin_version 1.0
plugman had generated all the needed files for me to get started.
js file www/myCustomPlugin.js
var exec = require('cordova/exec');
exports.coolMethod = function(arg0, success, error) {
exec(success, error, "myCustomPlugin", "coolMethod", [arg0]);
};
java file src/android/myCustomPlugin.java, method execute
#Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
if (action.equals("coolMethod")) {
String message = args.getString(0);
this.coolMethod(message, callbackContext);
return true;
}
return false;
}
private void coolMethod(String message, CallbackContext callbackContext) {
if (message != null && message.length() > 0) {
callbackContext.success(message);
} else {
callbackContext.error("Expected one non-empty string argument.");
}
}
The question is:
On the cordova project js file. How do I call myCustomPlugin? and how do I know that it is working?
I am using angular in my cordova project, let say my controller is like this:
.controller('mainCtrl', function($scope){
// how to call myCustomPlugin here?
});
My motive is just to learn how to call and how it work only, maybe after click it will do a native alert or open native view or something.
Thanks in advance!
You can do:
www/myCustomPlugin.js
var MyCustomPlugin {
coolMethod : function(arg0, success, error) {
exec(success, error, "myCustomPlugin", "coolMethod", [arg0]);
}
}
module.exports = MyCustomPlugin
And in your js client just:
MyCustomPlugin.coolMethod("Arg1", function(){}, function(){});
Cordova will inject JavaScript file for you.
Hope it helps.
Related
In a program I am developing using jcef, I want to allow the camera to be used inside. I am trying to give --enable-media-stream switch for the program that I am building using jcef. I am tried to turn on switch with the following cases:
settings.windowless_rendering_enabled = useOSR;
settings.command_line_args_disabled = false;
String[] args = new String[]{
"--enable-media-stream=true"
// "--enable-media-steam",
// "enable-media-stream", "1"
};
cefApp = CefApp.getInstance(args, settings);
Program gives
[1031/094701.279:INFO:CONSOLE(0)] "Uncaught (in promise) NotAllowedError: Permission denied", source: theUrl
error in every cases.
However, the camera is allowed if I run *.jar app from command line with: "java -jar appName.jar --enable-media-stream" command.
What might be the issue here?
Thanks in advance.
I solved it with next code:
CefApp.addAppHandler(new CefAppHandlerAdapter(null) {
#Override
public void onBeforeCommandLineProcessing(String process_type, CefCommandLine command_line) {
super.onBeforeCommandLineProcessing(process_type, command_line);
if (process_type.isEmpty()) {
command_line.appendSwitchWithValue("enable-media-stream","true");
}
}
});
Apply Deep Linking in flutter app to open
a specific page in another app or same app
i want to know to how implement deep links in flutter
or open channel with android native and ios native ?
?
I think it would be the same as in a normal android app. Deeplinking is a configuration thing rather than code.
You need to write some things in your android manifest.
Have a look at the firebase manual for deep linking:
Firebase deeplinking manual
You can use firebase dynamic links for deep linking in a flutter. Refer this link for full implement steps and create and receive a link, https://medium.com/better-programming/deep-linking-in-flutter-with-firebase-dynamic-links-8a4b1981e1eb.
Here is a sample code for receiving a link inside the app and open a new screen.
class MainWidgetState extends State<MainWidget> {
#override
void initState() {
super.initState();
this.initDynamicLinks();
}
initDynamicLinks(BuildContext context) async {
await Future.delayed(Duration(seconds: 3));
var data = await FirebaseDynamicLinks.instance.getInitialLink();
var deepLink = data?.link;
final queryParams = deepLink.queryParameters;
if (queryParams.length > 0) {
var userName = queryParams['userId'];
openNewScreen(userName);
}
FirebaseDynamicLinks.instance.onLink(onSuccess: (dynamicLink)
async {
var deepLink = dynamicLink?.link;
final queryParams = deepLink.queryParameters;
if (queryParams.length > 0) {
var userName = queryParams['userId'];
openNewScreen(userName);
}
debugPrint('DynamicLinks onLink $deepLink');
}, onError: (e) async {
debugPrint('DynamicLinks onError $e');
});
}
openNewScreen(String userName){
Navigator.of(context).pushNamed("routeFormScreen", arguments: {"name": userName});
}
}
For jabber support i use library Smack. Android port asmack.
I have class SmackAPI which implements MessageListener interface and contains methods to connect, login, send message. In the same time this class contains method:
#Override
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
this.recievedMessage = message;
}
It provides by MessageListener interface. All new messages processed by this method.
I write jabber plugin to connect, login, send message from phonegap.
My question: how i can in javascript listen for new messages?
I did it. I dont know however it is right way, but it works!
Cordova plugin class:
public class SmackJabber extends CordovaPlugin {
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
this.cbContext = callbackContext;
switch (action) {
case LISTEN_MESSAGE:
res = new PluginResult(PluginResult.Status.NO_RESULT);
res.setKeepCallback(true);
cordova.getThreadPool().execute(new Runnable() {
#Override
public void run() {
String callbackId = cbContext.getCallbackId();
while (true) {
String msg = getMsg();
if (msg != null) {
res = new PluginResult(PluginResult.Status.OK, msg);
res.setKeepCallback(true);
CallbackContext cb = new CallbackContext(callbackId, webView);
cb.sendPluginResult(res);
}
}
}
});
cbContext.sendPluginResult(res);
break;
And easy javascript. Just call plugin method:
window.plugins.smackJabber.listenMessage(function(result) {
alert(result)
}, function(error) {
alert(error)
}
);
Explanation:
I call plugin method "listenMessage" (calling "execute" method with action "LISTEN_MESSAGE"). There i start thread from cordova threadpool with runnable, in runnable i got recursive function which check message. But before start runnable i have to take callbackId of method who call method execute. Also, for exit from method, i create new PluginResult with status "NO_RESULT" and set it option "keepCallback" to true - it means, that method calls in javascript awaiting one more callback result from me. When i got message, i create new callbackcontext based on callbackid and my webview, do setKeepCallback to true for futher possible responses for pluginresult, putting in pluginresult my message with status "OK" and sending it to callbackcontext. That's all.
I am attempting to integrate the Dropbox chooser drop-in api into my application. I am running into an abnormal issue. In my app when I launch the dbx chooser, anytime that I select a file the application fails with the following error code:
Sorry, an error has occurred. Please try again later.
Here is the portion of my code that implements the Dropbox API. This portion of the code is where the dropbox api is initially invoked.
public void StartDropboxApplication() {
// create the chooser
DbxChooser chooser = new DbxChooser(APP_KEY);
DbxChooser.ResultType result;
// determine which mode to be in // TODO REMOVE ALL BUT FILE CONTENT TODO SIMPLIFY by making this a setting
switch(( (RadioGroup) ParentActivity.findViewById(R.id.link_type)).getCheckedRadioButtonId() ) {
case R.id.link_type_content:
result = DbxChooser.ResultType.DIRECT_LINK;
break;
default:
throw new RuntimeException("Radio Group Related error.");
}
// launch the new activity
chooser.forResultType(result).launch(ParentActivity, 0);
}
Here is the position where the code should then pick it up although it never does.
protected void onActivityResult( int request, int result, Intent data ) {
Log.i(fileName, "result: " + result);
// check to see if the camera took a picture
if (request == 1) {
// check to see if the picture was successfully taken
if (result == Activity.RESULT_OK) {
onPicture();
} else {
Log.i(fileName, "Camera App cancelled.");
}
} else if (request == 0) {
if ( result == Activity.RESULT_OK ) {
onDropbox(data);
} else {
Log.i(fileName, "dropbox related issue.");
}
}
}
Thank you for any help or suggestions that you are able to provide.
I was able to solve my own issues and get this working. On the off chance that someone else has a similar problem I will detail the solution. The first issue was I was that my APP_KEY was incorrect.
The next issue was that I was attempting to read from a direct link instead of a content link. The direct link provides the application with a link to the file on the Dropbox server whereas the content link provides the application with a cached version of the file. If the file is not present on the device, the SDK downloads a copy for you.
I have built a custom plugin called TCPIPCommPlugin that uses Phonegap/Cordova 1.6.1. Everything is all great and the callbacks/plugin results work just fine. However I need to get it upgraded to Cordova 2.3. The reason is that we are now starting dev on Win8 as well as iOS/Android.
That aside, I have the following code in javascript.
var TCPComm = function() {
};
TCPComm.prototype.Open = function(Cmd,successCallback, failureCallback) {
return PhoneGap.exec( successCallback, //Success callback from the plugin
failureCallback, //Error callback from the plugin
'TCPIPCommPlugin', //Tell PhoneGap to run "DirectoryListingPlugin" Plugin
'Open', //Tell plugin, which action we want to perform
[Cmd]); //Passing list of args to the plugin
};
This code continues with about 10-12 different function calls to the plugin, which is then concluded with...
PhoneGap.addConstructor(function() {
PhoneGap.addPlugin("TCPComm", new TCPComm());
});
Within the javascript itself, the actual function call looks like this.
window.plugins.TCPComm.Open(g_IpAddr, OpenOK,OpenFail);
Additionally here is what the JAVA Plugin looks like.
#Override
public PluginResult execute(String action, JSONArray data, String callbackId) {
PluginResult result = null;
try {
Actions currentAction = Actions.valueOf(action.toUpperCase());
JSONObject Resp = new JSONObject();
String RespStr;
switch(currentAction){
case OPEN:
{
//do work
}catch (JSONException jsonEx) {
System.out.println(jsonEx.toString());
result = new PluginResult(Status.JSON_EXCEPTION);
}
return result;}
This works great with Cordova 1.6.1. However not so much with Cordova 2.x.x. Now with all this said and done, I have perused the web trying to find a way to convert the JAVA. I came up with the following.
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {
PluginResult result = null;
try {
Actions currentAction = Actions.valueOf(action.toUpperCase());
JSONObject Resp = new JSONObject();
String RespStr;
switch(currentAction){
case OPEN:
{
//do work
}catch (JSONException jsonEx) {
System.out.println(jsonEx.toString());
result = new PluginResult(Status.JSON_EXCEPTION);
}
return true;
}
This seems to match the updated code. What I have not been able to find is a way to update the JAVASCRIPT calls to make this plugin work with the updated CORDOVA.
Any help/points in the right direction would be much appreciated!
I have used the following documentation with no success.
http://docs.phonegap.com/en/2.3.0/guide_plugin-development_index.md.html#Plugin%20Development%20Guide
https://github.com/apache/cordova-android/tree/master/framework/src/org/apache/cordova
UPDATE
Thanks for the response Simon. In the interim I had replaced my javascript with the following. Do I need to revert it back to what it was prior?
cordova.define("cordova/plugin/TCPIPCommPlugin", function(require, exports, module){
var exec = require('cordova/exec');
var TCPComm = function() {};
// var TCPCommError = function(code, message) {
// this.code = code || null;
// this.message = message || '';
// };
TCPComm.prototype.Open = function(success,fail) {
return cordova.exec( successCallback, //Success callback from the plugin
failureCallback, //Error callback from the plugin
'TCPIPCommPlugin', //Tell PhoneGap to run "DirectoryListingPlugin" Plugin
'Open', //Tell plugin, which action we want to perform
[Cmd]);
};
var TCPIPCommPlugin = new TCPComm();
module.exports = TCPIPCommPlugin;
});
UPDATE #2 - Fixed some errors
I went back to the old javascript and replaced it all so it looks like this now..
var TCPComm = function() {};
TCPComm.prototype.Open = function(Cmd, successCallback,failureCallback) {
return cordova.exec( successCallback, //Success callback from the plugin
failureCallback, //Error callback from the plugin
'TCPIPCommPlugin', //Tell PhoneGap to run "DirectoryListingPlugin" Plugin
'Open', //Tell plugin, which action we want to perform
[Cmd]);
};
I also replaced the constructor with..
if(!window.plugins) {
window.plugins = {};
}
if (!window.plugins.TCPComm) {
window.plugins.TCPComm = new TCPComm();
}
Now when I run it in Chrome, (UI debugging), I can see the plugin built with all the proper functions inside the function.
The Java was fine, I forgot to include the return on the forum code. Whoops.
Now I tried calling the function like I always have and I get a Object # has no method 'exec' at the first JAVASCRIPT call of either Close/Open..
window.plugins.TCPComm.Close("", Dummy, Dummy);
window.plugins.TCPComm.Open(g_IpAddr, OpenOK,OpenFail);
I have breakpoints set in the Java on the execute to let me know when the plugin has called successfully to the Java and still no luck.
Any other thoughts? Thanks again for your insight.
Replace PhoneGap.exec with the following code:
var TCPComm = function() {
};
TCPComm.prototype.Open = function(Cmd,successCallback, failureCallback) {
return cordova.exec( successCallback, //Success callback from the plugin
failureCallback, //Error callback from the plugin
'TCPIPCommPlugin', //Tell PhoneGap to run "DirectoryListingPlugin" Plugin
'Open', //Tell plugin, which action we want to perform
[Cmd]); //Passing list of args to the plugin
};
The add constructor method is deprecated so do:
if(!window.plugins) {
window.plugins = {};
}
if (!window.plugins.videoPlayer) {
window.plugins.TCPComm = new TCPComm();
}
For your Java code you are most of the way there but you need to return the result:
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) {
PluginResult result = null;
try {
Actions currentAction = Actions.valueOf(action.toUpperCase());
JSONObject Resp = new JSONObject();
String RespStr;
switch(currentAction){
case OPEN:
//do work
this.callbackContext.sendPluginResult(
new PluginResult(PluginResult.Status.OK, results));
} catch (JSONException jsonEx) {
System.out.println(jsonEx.toString());
result = new PluginResult(Status.JSON_EXCEPTION);
}
return true;
}
That should get you upgraded.