diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-customurlscheme/src')
6 files changed, 215 insertions, 6 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/android/nl/xservices/plugins/LaunchMyApp.java b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/android/nl/xservices/plugins/LaunchMyApp.java index 9d3f3d63..3a52d287 100644 --- a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/android/nl/xservices/plugins/LaunchMyApp.java +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/android/nl/xservices/plugins/LaunchMyApp.java @@ -4,6 +4,8 @@ import android.content.Intent; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaActivity; import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaWebView; import org.apache.cordova.PluginResult; import org.json.JSONArray; import org.json.JSONException; @@ -16,19 +18,52 @@ import java.util.Locale; public class LaunchMyApp extends CordovaPlugin { private static final String ACTION_CHECKINTENT = "checkIntent"; + private static final String ACTION_CLEARINTENT = "clearIntent"; + private static final String ACTION_GETLASTINTENT = "getLastIntent"; + + private String lastIntentString = null; + + /** + * We don't want to interfere with other plugins requiring the intent data, + * but in case of a multi-page app your app may receive the same intent data + * multiple times, that's why you'll get an option to reset it (null it). + * + * Add this to config.xml to enable that behaviour (default false): + * <preference name="CustomURLSchemePluginClearsAndroidIntent" value="true"/> + */ + private boolean resetIntent; + + @Override + public void initialize(final CordovaInterface cordova, CordovaWebView webView){ + this.resetIntent = preferences.getBoolean("resetIntent", false) || + preferences.getBoolean("CustomURLSchemePluginClearsAndroidIntent", false); + } @Override public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { - if (ACTION_CHECKINTENT.equalsIgnoreCase(action)) { + if (ACTION_CLEARINTENT.equalsIgnoreCase(action)) { + final Intent intent = ((CordovaActivity) this.webView.getContext()).getIntent(); + if (resetIntent){ + intent.setData(null); + } + return true; + } else if (ACTION_CHECKINTENT.equalsIgnoreCase(action)) { final Intent intent = ((CordovaActivity) this.webView.getContext()).getIntent(); final String intentString = intent.getDataString(); - if (intentString != null && intentString.contains("://") && intent.getScheme() != null) { + if (intentString != null && intent.getScheme() != null) { + lastIntentString = intentString; callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, intent.getDataString())); - intent.setData(null); } else { callbackContext.error("App was not started via the launchmyapp URL scheme. Ignoring this errorcallback is the best approach."); } return true; + } else if (ACTION_GETLASTINTENT.equalsIgnoreCase(action)) { + if(lastIntentString != null) { + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, lastIntentString)); + } else { + callbackContext.error("No intent received so far."); + } + return true; } else { callbackContext.error("This plugin only responds to the " + ACTION_CHECKINTENT + " action."); return false; @@ -38,8 +73,10 @@ public class LaunchMyApp extends CordovaPlugin { @Override public void onNewIntent(Intent intent) { final String intentString = intent.getDataString(); - if (intentString != null && intentString.contains("://") && intent.getScheme() != null) { - intent.setData(null); + if (intentString != null && intent.getScheme() != null) { + if (resetIntent){ + intent.setData(null); + } try { StringWriter writer = new StringWriter(intentString.length() * 2); escapeJavaStyleString(writer, intentString, true, false); @@ -133,4 +170,4 @@ public class LaunchMyApp extends CordovaPlugin { private static String hex(char ch) { return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); } -}
\ No newline at end of file +} diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/windows/hooks/prepare-manifest.js b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/windows/hooks/prepare-manifest.js new file mode 100644 index 00000000..06e237f7 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/windows/hooks/prepare-manifest.js @@ -0,0 +1,30 @@ +module.exports = function(context) { + var fs = context.requireCordovaModule('fs'), + et = context.requireCordovaModule('elementtree'), + path = context.requireCordovaModule('path'), + xml= context.requireCordovaModule('cordova-common').xmlHelpers, + projectRoot = path.join(context.opts.projectRoot, "platforms", "windows"); + + var MANIFEST_WINDOWS = 'package.windows.appxmanifest', + MANIFEST_PHONE = 'package.phone.appxmanifest', + MANIFEST_WINDOWS10 = 'package.windows10.appxmanifest', + MANIFEST_WINDOWS80 = 'package.windows80.appxmanifest'; + + function updateManifestFile(manifestPath) { + var doc = xml.parseElementtreeSync(manifestPath); + var root = doc.getroot(); + var app = root.find('./Applications/Application'); + if (!app) { + throw new Error(manifestPath + ' has incorrect XML structure.'); + } + if (!app.find('./Extensions')) { + app.append(new et.Element('Extensions')); + } + fs.writeFileSync(manifestPath, doc.write({indent: 4}), 'utf-8'); + } + + [MANIFEST_PHONE, MANIFEST_WINDOWS80, MANIFEST_WINDOWS, MANIFEST_WINDOWS10] + .forEach(function(manifestFile) { + updateManifestFile(path.join(projectRoot, manifestFile)); + }); +} diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CompositeUriMapper.cs b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CompositeUriMapper.cs new file mode 100644 index 00000000..8db593b8 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CompositeUriMapper.cs @@ -0,0 +1,46 @@ +using System; +using System.Linq; +using System.Windows.Navigation; + +internal class CompositeUriMapper : UriMapperBase +{ + public static string launchUrl; + + public override Uri MapUri(Uri uri) + { + string launchUri = uri.ToString(); + if (launchUri.StartsWith("/Protocol?encodedLaunchUri=")) + { + int launchUrlIndex = launchUri.IndexOf("encodedLaunchUri="); + launchUrl = System.Net.HttpUtility.UrlDecode(launchUri.Substring(launchUrlIndex+17)); + return new Uri("/MainPage.xaml", UriKind.Relative); + } + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + var types = assemblies.SelectMany(a => + { + try + { + return a.ExportedTypes.Where(et => typeof(ICustomUriMapper).IsAssignableFrom(et)); + } + catch + { + return Enumerable.Empty<Type>(); + } + }); + + foreach (var type in types) + { + if (type != typeof(ICustomUriMapper)) + { + var worker = (ICustomUriMapper)Activator.CreateInstance(type); + var mappedUri = worker.CustomMapUri(uri); + if (mappedUri != null) + { + return mappedUri; + } + } + } + + return uri; + } +}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CustomUriMapperCommand.cs b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CustomUriMapperCommand.cs new file mode 100644 index 00000000..2004f2ec --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/CustomUriMapperCommand.cs @@ -0,0 +1,9 @@ +using System; +using WPCordovaClassLib.Cordova.Commands; + +namespace Cordova.Extension.Commands +{ + public class CustomUriMapperCommand : BaseCommand + { + } +}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/ICustomUriMapper.cs b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/ICustomUriMapper.cs new file mode 100644 index 00000000..2cc31e5c --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/ICustomUriMapper.cs @@ -0,0 +1,7 @@ +using System; +using System.Linq; + +public interface ICustomUriMapper +{ + Uri CustomMapUri(Uri uri); +} diff --git a/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/hooks/add-uri-mapper.js b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/hooks/add-uri-mapper.js new file mode 100644 index 00000000..1c1db69c --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-customurlscheme/src/wp8/hooks/add-uri-mapper.js @@ -0,0 +1,80 @@ +module.exports = function (context) { + var deferred = context.requireCordovaModule('q').defer(), + fs = context.requireCordovaModule('fs'), + path = context.requireCordovaModule('path'), + projectRoot = context.opts.projectRoot; + + // While on AppBuilder this may work, the Cordova CLI doesn't like it + // (or at least not all versions of it). + var appXaml = path.join(projectRoot, "App.xaml.cs"); + var mainPageXaml = path.join(projectRoot, "MainPage.xaml.cs"); + try { + fs.statSync(appXaml); + fs.statSync(mainPageXaml); + } catch (err) { + appXaml = path.join(projectRoot, "platforms", "wp8", "App.xaml.cs"); + mainPageXaml = path.join(projectRoot, "platforms", "wp8", "MainPage.xaml.cs"); + try { + fs.statSync(appXaml); + fs.statSync(mainPageXaml); + } catch (err2) { + console.error("Custom URL Scheme plugin couldn't find your App's xaml file! Try to adjust the file manually according to the 'add-uri-mapper.js' hook."); + return; + } + } + + fs.readFile(appXaml, 'utf8', function (err,data) { + if (err) { + console.error("Error while configuring the Custom URL Scheme: " + err); + deferred.reject(err); + return; + } + + var result = data.replace(/^(\s*?)(RootFrame.NavigationFailed\s*?\+=\s*?RootFrame_NavigationFailed;)/gm, + "$1$2\n\n$1// Assign the URI-mapper class to the application frame\n$1RootFrame.UriMapper = new CompositeUriMapper();"); + + fs.writeFile(appXaml, result, 'utf8', function (err) { + if (err){ + deferred.reject(err); + } else{ + deferred.resolve(); + } + }); + }); + + fs.readFile(mainPageXaml, 'utf8', function (err,data) { + if (err) { + console.error("Error while configuring the Custom URL Scheme: " + err); + deferred.reject(err); + return; + } + + // first add a line to refer to a new method + var result = data.replace(/^(\s*?)(this.CordovaView.Loaded\s*?\+=\s*?CordovaView_Loaded;)/gm, + "$1$2\n\n$1// Wire a handler so we can check for our custom scheme\n$1this.CordovaView.Browser.LoadCompleted += CordovaBrowser_LoadCompleted;"); + + // now add that new method + result = result.replace(/^(\s*?)(\/\/ Constructor)/gm, + "$1void CordovaBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e) {\n"+ + "$1\tif (CompositeUriMapper.launchUrl != null) {\n" + + "$1\t\tstring handleOpenURL = string.Format(\"(function() {{ document.addEventListener('deviceready', function() {{ if (typeof handleOpenURL === 'function') {{ handleOpenURL(\\\"{0}\\\"); }} }}); }})()\", CompositeUriMapper.launchUrl);\n" + + "$1\t\ttry {\n" + + "$1\t\t\tthis.CordovaView.CordovaBrowser.InvokeScript(\"eval\", new string[] { handleOpenURL });\n" + + "$1\t\t} catch (Exception) {}\n" + + "$1\t\tCompositeUriMapper.launchUrl = null;\n" + + "$1\t}\n" + + "$1\tthis.CordovaView.Browser.LoadCompleted -= CordovaBrowser_LoadCompleted;\n" + + "$1}\n\n" + + "$1$2"); + + fs.writeFile(mainPageXaml, result, 'utf8', function (err) { + if (err){ + deferred.reject(err); + } else{ + deferred.resolve(); + } + }); + }); + + return deferred.promise; +}
\ No newline at end of file |
