Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a Phonegap app to receive variables on Android?

With much help from the Stack OVerflow community, I now have successfully set up my Android app so that when one clicks on a link in an email, it opens my app directly. In other words, I have my <intent-filter> in my AndroidManifest.xml properly configured.

So far so good, but there is one last step that I am still struggling with, which is getting my Phonegap-built app to pick up and use the variables that I pass to it from a URL in an email.

The link in the email looks like this:

<a target="_blank" href="https://mysite.com/confirmation.html?verification=XXXXXXXXX&username=larry">Complete verification with MYAPP</a>

Clicking on the link opens up my app. To be precise, when one clicks on it, a dialog pops up asking the user whether they want to open using a browser or my app, which is cool.

Anyway, the point is that if they use my app to open my app, it opens to the default welcome screen. The desired behaviour, though, is that the app open to a specific page, confirmation.html, and have two fields filled with the variables from the URL, the verification and username.

How do I get my Phonegap app to start on the right page and use the variables in the URL?

Important: I really want to stress, just so it's absolutely clear, this is a Phonegap build, meaning the app uses HTML and Javascript, not native Android code. Thanks for your understanding.

like image 888
Questioner Avatar asked Aug 22 '13 07:08

Questioner


1 Answers

If you are using WebIntent (which I assume you do?) you can simple do this:

window.plugins.webintent.getUri(function(url) {
        if(url !== "") {
            // url is the url the intent was launched with
            document.querySelector("#tag").innerHTML = "URL = " + url;
        }
    });

Edit:

Ok so I managed to get the plugin working on PhoneGap 2.9.0.

However I have to clarify some things.

First off, you said that certain methods were deprecated, however deprecation does not mean that the methods wont function. The (old) plugin as it is listed on github works fine, but I did manage to get it working with the CordovaPlugin as well.

The problem with the lastest version of the plugin seems to be in the webintent.js file.

I changed a few lines of code to fix an error that occurred inside the file.

/**
 * 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.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);

Inside WebIntent.java I changed a variable to private CallbackContext onNewIntentCallback = null;

package com.borismus.webintent;

import java.util.HashMap;
import java.util.Map;

import org.apache.cordova.DroidGap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Intent;
import android.net.Uri;
import android.util.Log;
import android.text.Html;

import org.apache.cordova.api.CordovaPlugin;
import org.apache.cordova.api.PluginResult;
import org.apache.cordova.api.CallbackContext;

/**
 * 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 [email protected]
 *
 */
public class WebIntent extends CordovaPlugin {

    private CallbackContext onNewIntentCallback = null;

    /**
     * Executes the request and returns PluginResult.
     *
     * @param action
     *            The action to execute.
     * @param args
     *            JSONArray of arguments for the plugin.
     * @param callbackContext
     *            The callbackContext used when calling back into JavaScript.
     * @return boolean
     */
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) {
        try {
            if (action.equals("startActivity")) {
                if (args.length() != 1) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }

                // Parse the arguments
                JSONObject obj = args.getJSONObject(0);
                String type = obj.has("type") ? obj.getString("type") : null;
                Uri uri = obj.has("url") ? Uri.parse(obj.getString("url")) : null;
                JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
                Map<String, String> extrasMap = new HashMap<String, String>();

                // 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);
                callbackContext.success();
                return true;

            } else if (action.equals("hasExtra")) {
                if (args.length() != 1) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }
                Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
                String extraName = args.getString(0);
                PluginResult res = new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName));
                callbackContext.sendPluginResult(res);
                return true;

            } else if (action.equals("getExtra")) {
                if (args.length() != 1) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }
                Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
                String extraName = args.getString(0);

                if (i.hasExtra(extraName)) {
                    PluginResult res = new PluginResult(PluginResult.Status.OK, i.hasExtra(extraName));
                    callbackContext.sendPluginResult(res);
                    return true;

                } else {
                    PluginResult res = new PluginResult(PluginResult.Status.ERROR);
                    callbackContext.sendPluginResult(res);
                    return false;
                }

            } else if (action.equals("getUri")) {
                if (args.length() != 0) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }

                Intent i = ((DroidGap)this.cordova.getActivity()).getIntent();
                String uri = i.getDataString();

                callbackContext.success(uri);
                return true;

            } else if (action.equals("onNewIntent")) {
                if (args.length() != 0) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }

                this.onNewIntentCallback = callbackContext;
                PluginResult res = new PluginResult(PluginResult.Status.NO_RESULT);
                res.setKeepCallback(true);
                callbackContext.sendPluginResult(res);
                return true;

            } else if (action.equals("sendBroadcast"))
            {
                if (args.length() != 1) {
                    PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
                    callbackContext.sendPluginResult(res);
                    return false;
                }

                // Parse the arguments
                JSONObject obj = args.getJSONObject(0);

                JSONObject extras = obj.has("extras") ? obj.getJSONObject("extras") : null;
                Map<String, String> extrasMap = new HashMap<String, String>();

                // 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);
                callbackContext.success();
                return true;

            }

            PluginResult res = new PluginResult(PluginResult.Status.INVALID_ACTION);
            callbackContext.sendPluginResult(res);
            return false;

        } catch (JSONException e) {
            callbackContext.error(e.getMessage());
            return false;
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        if (this.onNewIntentCallback != null) {
            this.onNewIntentCallback.success(intent.getDataString());
        }
    }

    void startActivity(String action, Uri uri, String type, Map<String, String> 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
                i.putExtra(key, 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);
            }
        }
        ((DroidGap)this.cordova.getActivity()).startActivity(i);
    }

    void sendBroadcast(String action, Map<String, String> extras) {
        Intent intent = new Intent();
        intent.setAction(action);
        for (String key : extras.keySet()) {
            String value = extras.get(key);
            intent.putExtra(key, value);
        }

        ((DroidGap)this.cordova.getActivity()).sendBroadcast(intent);
    }
}

And the html file.

<!DOCTYPE html>
<html>
  <head>
    <title>Intent Test</title>

    <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
    <script src="webintent.js"></script>
    <script type="text/javascript" charset="utf-8">

    // Wait for device API libraries to load
    //
    function onLoad() {
        alert("onLoad");
        document.addEventListener("deviceready", onDeviceReady, false);
    }

    // device APIs are available
    //
    function onDeviceReady() {
        alert("onDeviceReady");
        window.plugins.webintent.getUri(function(url) {
            if(url !== "") {
                // url is the url the intent was launched with
                document.querySelector("#test").innerHTML = "URL was "+url;
            }
        });
    }

    </script>
  </head>
  <body onload="onLoad()">
<h1>Test</h1>

<div id="test"></div>
  </body>
</html>

I tested it with this code and I am correctly receiving an URL. If you want I can send you the whole project (email me). Hope this helps.

Update 3.0: https://github.com/Initsogar/cordova-webintent

like image 174
Edward van Raak Avatar answered Oct 08 '22 04:10

Edward van Raak