diff --git a/plugins/cordova-webintent/.gitignore b/plugins/cordova-webintent/.gitignore new file mode 100644 index 0000000..0fabd2d --- /dev/null +++ b/plugins/cordova-webintent/.gitignore @@ -0,0 +1,24 @@ +#If ignorance is bliss, then somebody knock the smile off my face + +*.csproj.user +*.suo +*.cache +Thumbs.db +*.DS_Store + +*.bak +*.cache +*.log +*.swp +*.user +.idea + + + + + + + + + + \ No newline at end of file diff --git a/plugins/cordova-webintent/README.md b/plugins/cordova-webintent/README.md new file mode 100644 index 0000000..3031aa8 --- /dev/null +++ b/plugins/cordova-webintent/README.md @@ -0,0 +1,121 @@ +# WebIntent Android Plugin for Cordova 3.X # +By Boris Smus + +Phonegap/Cordova 2.X version available at the [WebIntent](https://github.com/phonegap/phonegap-plugins/tree/master/Android/WebIntent) plugin site. + +## Adding the Plugin to your project ## +1. To install the plugin, use the Cordova CLI and enter the following: + +`cordova plugin add https://github.com/Initsogar/cordova-webintent.git` + +2. Confirm that the following is in your `res/xml/config.xml` file: + +`` + +## Sample code + +Here is an example of using webintent to open an Android .apk package, which then launches the Installer: + + window.plugins.webintent.startActivity({ + action: window.plugins.webintent.ACTION_VIEW, + url: theFile.toURL(), + type: 'application/vnd.android.package-archive' + }, + function() {}, + function() { + alert('Failed to open URL via Android Intent.'); + console.log("Failed to open URL via Android Intent. URL: " + theFile.fullPath) + } + ); + + +## Using the plugin ## +The plugin creates the object `window.plugins.webintent` with five methods: + +### startActivity ### +Launches an Android intent. For example: + + + window.plugins.webintent.startActivity({ + action: window.plugins.webintent.ACTION_VIEW, + url: 'geo:0,0?q=' + address}, + function() {}, + function() {alert('Failed to open URL via Android Intent')}; + ); + + +### hasExtra ### +checks if this app was invoked with the specified extra. For example: + + window.plugins.webintent.hasExtra(window.plugins.webintent.EXTRA_TEXT, + function(has) { + // has is true iff it has the extra + }, function() { + // Something really bad happened. + } + ); + +### getExtra ### +Gets the extra that this app was invoked with. For example: + + window.plugins.webintent.getExtra(window.plugins.webintent.EXTRA_TEXT, + function(url) { + // url is the value of EXTRA_TEXT + }, function() { + // There was no extra supplied. + } + ); + +### getUri ### +Gets the Uri the app was invoked with. For example: + + window.plugins.webintent.getUri(function(url) { + if(url !== "") { + // url is the url the intent was launched with + } + }); + +### onNewIntent ### +Gets called when onNewIntent is called for the parent activity. Used in only certain launchModes. For example: + + window.plugins.webintent.onNewIntent(function(url) { + if(url !== "") { + // url is the url that was passed to onNewIntent + } + }); + +### sendBroadcast ### +Sends a custom intent passing optional extras + + window.plugins.webintent.sendBroadcast({ + action: 'com.dummybroadcast.action.triggerthing', + extras: { + 'option': true + } + }, function() { + }, function() { + }); + +## Licence ## + +The MIT License + +Copyright (c) 2010 Boris Smus + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/plugins/cordova-webintent/plugin.xml b/plugins/cordova-webintent/plugin.xml new file mode 100644 index 0000000..50bc842 --- /dev/null +++ b/plugins/cordova-webintent/plugin.xml @@ -0,0 +1,25 @@ + + + + WebIntent + Web intents for Cordova + MIT + cordova,webintent + + + + + + + + + + + + + + + + diff --git a/plugins/cordova-webintent/src/android/WebIntent.java b/plugins/cordova-webintent/src/android/WebIntent.java new file mode 100644 index 0000000..2d2c1e5 --- /dev/null +++ b/plugins/cordova-webintent/src/android/WebIntent.java @@ -0,0 +1,217 @@ +package com.borismus.webintent; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.cordova.CordovaActivity; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import android.content.Intent; +import android.net.Uri; +import android.text.Html; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaResourceApi; +import org.apache.cordova.PluginResult; + +/** + * WebIntent is a PhoneGap plugin that bridges Android intents and web + * applications: + * + * 1. web apps can spawn intents that call native Android applications. 2. + * (after setting up correct intent filters for PhoneGap applications), Android + * intents can be handled by PhoneGap web applications. + * + * @author boris@borismus.com + * + */ +public class WebIntent extends CordovaPlugin { + + private CallbackContext onNewIntentCallbackContext = null; + + //public boolean execute(String action, JSONArray args, String callbackId) { + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) { + try { + + if (action.equals("startActivity")) { + if (args.length() != 1) { + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + + // Parse the arguments + final CordovaResourceApi resourceApi = webView.getResourceApi(); + JSONObject obj = args.getJSONObject(0); + String type = obj.has("type") ? obj.getString("type") : null; + Uri uri = obj.has("url") ? resourceApi.remapUri(Uri.parse(obj.getString("url"))) : null; + JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null; + Map extrasMap = new HashMap(); + + // Populate the extras if any exist + if (extras != null) { + JSONArray extraNames = extras.names(); + for (int i = 0; i < extraNames.length(); i++) { + String key = extraNames.getString(i); + String value = extras.getString(key); + extrasMap.put(key, value); + } + } + + startActivity(obj.getString("action"), uri, type, extrasMap); + //return new PluginResult(PluginResult.Status.OK); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK)); + return true; + + } else if (action.equals("hasExtra")) { + if (args.length() != 1) { + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + Intent i = ((CordovaActivity)this.cordova.getActivity()).getIntent(); + String extraName = args.getString(0); + //return new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName)); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName))); + return true; + + } else if (action.equals("getExtra")) { + if (args.length() != 1) { + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + Intent i = ((CordovaActivity)this.cordova.getActivity()).getIntent(); + String extraName = args.getString(0); + if (i.hasExtra(extraName)) { + //return new PluginResult(PluginResult.Status.OK, i.getStringExtra(extraName)); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, i.getStringExtra(extraName))); + return true; + } else { + //return new PluginResult(PluginResult.Status.ERROR); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR)); + return false; + } + } else if (action.equals("getUri")) { + if (args.length() != 0) { + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + + Intent i = ((CordovaActivity)this.cordova.getActivity()).getIntent(); + String uri = i.getDataString(); + //return new PluginResult(PluginResult.Status.OK, uri); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, uri)); + return true; + } else if (action.equals("onNewIntent")) { + //save reference to the callback; will be called on "new intent" events + this.onNewIntentCallbackContext = callbackContext; + + if (args.length() != 0) { + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + + PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT); + result.setKeepCallback(true); //re-use the callback on intent events + callbackContext.sendPluginResult(result); + return true; + //return result; + } else if (action.equals("sendBroadcast")) + { + if (args.length() != 1) { + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + + // Parse the arguments + JSONObject obj = args.getJSONObject(0); + + JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null; + Map extrasMap = new HashMap(); + + // Populate the extras if any exist + if (extras != null) { + JSONArray extraNames = extras.names(); + for (int i = 0; i < extraNames.length(); i++) { + String key = extraNames.getString(i); + String value = extras.getString(key); + extrasMap.put(key, value); + } + } + + sendBroadcast(obj.getString("action"), extrasMap); + //return new PluginResult(PluginResult.Status.OK); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK)); + return true; + } + //return new PluginResult(PluginResult.Status.INVALID_ACTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } catch (JSONException e) { + e.printStackTrace(); + String errorMessage=e.getMessage(); + //return new PluginResult(PluginResult.Status.JSON_EXCEPTION); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION,errorMessage)); + return false; + } + } + + @Override + public void onNewIntent(Intent intent) { + + if (this.onNewIntentCallbackContext != null) { + PluginResult result = new PluginResult(PluginResult.Status.OK, intent.getDataString()); + result.setKeepCallback(true); + this.onNewIntentCallbackContext.sendPluginResult(result); + } + } + + void startActivity(String action, Uri uri, String type, Map extras) { + Intent i = (uri != null ? new Intent(action, uri) : new Intent(action)); + + if (type != null && uri != null) { + i.setDataAndType(uri, type); //Fix the crash problem with android 2.3.6 + } else { + if (type != null) { + i.setType(type); + } + } + + for (String key : extras.keySet()) { + String value = extras.get(key); + // If type is text html, the extra text must sent as HTML + if (key.equals(Intent.EXTRA_TEXT) && type.equals("text/html")) { + i.putExtra(key, Html.fromHtml(value)); + } else if (key.equals(Intent.EXTRA_STREAM)) { + // allowes sharing of images as attachments. + // value in this case should be a URI of a file + final CordovaResourceApi resourceApi = webView.getResourceApi(); + i.putExtra(key, resourceApi.remapUri(Uri.parse(value))); + } else if (key.equals(Intent.EXTRA_EMAIL)) { + // allows to add the email address of the receiver + i.putExtra(Intent.EXTRA_EMAIL, new String[] { value }); + } else { + i.putExtra(key, value); + } + } + ((CordovaActivity)this.cordova.getActivity()).startActivity(i); + } + + void sendBroadcast(String action, Map extras) { + Intent intent = new Intent(); + intent.setAction(action); + for (String key : extras.keySet()) { + String value = extras.get(key); + intent.putExtra(key, value); + } + + ((CordovaActivity)this.cordova.getActivity()).sendBroadcast(intent); + } +} diff --git a/plugins/cordova-webintent/www/webintent.js b/plugins/cordova-webintent/www/webintent.js new file mode 100644 index 0000000..9f01ef3 --- /dev/null +++ b/plugins/cordova-webintent/www/webintent.js @@ -0,0 +1,73 @@ +/** + * cordova Web Intent plugin + * Copyright (c) Boris Smus 2010 + * + */ + (function(cordova){ + var WebIntent = function() { + + }; + + WebIntent.prototype.ACTION_SEND = "android.intent.action.SEND"; + WebIntent.prototype.ACTION_VIEW= "android.intent.action.VIEW"; + WebIntent.prototype.EXTRA_TEXT = "android.intent.extra.TEXT"; + WebIntent.prototype.EXTRA_SUBJECT = "android.intent.extra.SUBJECT"; + WebIntent.prototype.EXTRA_STREAM = "android.intent.extra.STREAM"; + WebIntent.prototype.EXTRA_EMAIL = "android.intent.extra.EMAIL"; + WebIntent.prototype.ACTION_CALL = "android.intent.action.CALL"; + WebIntent.prototype.ACTION_SENDTO = "android.intent.action.SENDTO"; + + WebIntent.prototype.startActivity = function(params, success, fail) { + return cordova.exec(function(args) { + success(args); + }, function(args) { + fail(args); + }, 'WebIntent', 'startActivity', [params]); + }; + + WebIntent.prototype.hasExtra = function(params, success, fail) { + return cordova.exec(function(args) { + success(args); + }, function(args) { + fail(args); + }, 'WebIntent', 'hasExtra', [params]); + }; + + WebIntent.prototype.getUri = function(success, fail) { + return cordova.exec(function(args) { + success(args); + }, function(args) { + fail(args); + }, 'WebIntent', 'getUri', []); + }; + + WebIntent.prototype.getExtra = function(params, success, fail) { + return cordova.exec(function(args) { + success(args); + }, function(args) { + fail(args); + }, 'WebIntent', 'getExtra', [params]); + }; + + + WebIntent.prototype.onNewIntent = function(callback) { + return cordova.exec(function(args) { + callback(args); + }, function(args) { + }, 'WebIntent', 'onNewIntent', []); + }; + + WebIntent.prototype.sendBroadcast = function(params, success, fail) { + return cordova.exec(function(args) { + success(args); + }, function(args) { + fail(args); + }, 'WebIntent', 'sendBroadcast', [params]); + }; + + window.webintent = new WebIntent(); + + // backwards compatibility + window.plugins = window.plugins || {}; + window.plugins.webintent = window.webintent; +})(window.PhoneGap || window.Cordova || window.cordova);