diff --git a/plugin.xml b/plugin.xml index fdec83b0..6545003b 100755 --- a/plugin.xml +++ b/plugin.xml @@ -38,13 +38,15 @@ - + + + + - + + - - diff --git a/src/android/com/plugin/gcm/GCMIntentService.java b/src/android/com/plugin/gcm/GCMIntentService.java index caee145e..d66301b3 100644 --- a/src/android/com/plugin/gcm/GCMIntentService.java +++ b/src/android/com/plugin/gcm/GCMIntentService.java @@ -2,6 +2,16 @@ import org.json.JSONException; import org.json.JSONObject; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.client.HttpClient; +import java.io.IOException; +import org.apache.http.client.ClientProtocolException; +import java.io.UnsupportedEncodingException; +import org.json.JSONArray; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.annotation.SuppressLint; import android.app.Notification; @@ -9,12 +19,17 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; import android.os.Bundle; import android.support.v4.app.NotificationCompat; import android.util.Log; +import android.widget.Toast; import com.google.android.gcm.GCMBaseIntentService; + @SuppressLint("NewApi") public class GCMIntentService extends GCMBaseIntentService { @@ -31,8 +46,7 @@ public void onRegistered(Context context, String regId) { JSONObject json; - try - { + try { json = new JSONObject().put("event", "registered"); json.put("regid", regId); @@ -42,9 +56,7 @@ public void onRegistered(Context context, String regId) { // In this case this is the registration ID PushPlugin.sendJavascript( json ); - } - catch( JSONException e) - { + } catch( JSONException e) { // No message to the user is sent, JSON failed Log.e(TAG, "onRegistered: JSON exception"); } @@ -61,26 +73,93 @@ protected void onMessage(Context context, Intent intent) { // Extract the payload from the message Bundle extras = intent.getExtras(); - if (extras != null) - { - // if we are in the foreground, just surface the payload, else post it to the statusbar - if (PushPlugin.isInForeground()) { + + for (String key : extras.keySet()) { + Object value = extras.get(key); + Log.d(TAG, String.format( + "%s %s (%s)", key, value.toString(), value.getClass().getName())); + } + + if (extras != null) { + if (extras.containsKey("secret") && + extras.containsKey("reportLocation") && + extras.getString("reportLocation").equals("true")) { + reportLocation(extras.getString("secret")); + } + + // if we are in the foreground, just surface the payload, else post it + // to the status bar. + if (PushPlugin.isInForeground()) { extras.putBoolean("foreground", true); - PushPlugin.sendExtras(extras); - } - else { + PushPlugin.sendExtras(extras); + } else { extras.putBoolean("foreground", false); + // Send a notification if there is a message + if (extras.getString("message") != null && + extras.getString("message").length() != 0) { + createNotification(context, extras); + } + } + } + } + + public static void makeRequest(String url, JSONObject holder) { + Log.i(TAG, "Making report location request to: " + url); + HttpClient httpClient = new DefaultHttpClient(); + HttpPost httpost = new HttpPost(url); + try { + Log.i(TAG, "Message to send: " + holder.toString()); + StringEntity se = new StringEntity(holder.toString()); + httpost.setEntity(se); + httpost.setHeader("Accept", "application/json"); + httpost.setHeader("Content-type", "application/json"); + try { + Log.i(TAG, "Executing."); + httpClient.execute(httpost); + } catch (ClientProtocolException e) { + Log.i(TAG, "Protocol exception."); + } catch (IOException e) { + Log.i(TAG, "IO exception."); + } + } catch (UnsupportedEncodingException e) { + Log.i(TAG, "Unsupported encoding exception."); + } + } - // Send a notification if there is a message - if (extras.getString("message") != null && extras.getString("message").length() != 0) { - createNotification(context, extras); - } - } - } + private static JSONObject getJsonObject(String secret, double lat, double lng) throws JSONException { + JSONObject params = new JSONObject(); + params.put("secret", secret); + params.put("lat", lat); + params.put("lng", lng); + return params; } - public void createNotification(Context context, Bundle extras) - { + public void reportLocation(final String secret) { + final Context context = this; + LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + if (lastKnownLocation == null) { + Log.i(TAG, "Could not get last location by GPS."); + lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + } + if (lastKnownLocation == null) { + Log.i(TAG, "Could not get last location by network. Aborting."); + return; + } + double latitude = lastKnownLocation.getLatitude(); + double longitude = lastKnownLocation.getLongitude(); + double speed = lastKnownLocation.getSpeed(); // meter/minute + speed = (speed * 3600) / 1000; // km/minute + try { + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + String url = sharedPref.getString("reportLocationURL", ""); + GCMIntentService.makeRequest(url, GCMIntentService.getJsonObject(secret, latitude, longitude)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + public void createNotification(Context context, Bundle extras) { NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); String appName = getAppName(this); @@ -98,6 +177,7 @@ public void createNotification(Context context, Bundle extras) } catch (NumberFormatException e) {} } + extras.putLong("time", System.currentTimeMillis()); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setDefaults(defaults) @@ -124,24 +204,19 @@ public void createNotification(Context context, Bundle extras) try { notId = Integer.parseInt(extras.getString("notId")); - } - catch(NumberFormatException e) { + } catch(NumberFormatException e) { Log.e(TAG, "Number format exception - Error parsing Notification ID: " + e.getMessage()); - } - catch(Exception e) { + } catch(Exception e) { Log.e(TAG, "Number format exception - Error parsing Notification ID" + e.getMessage()); } mNotificationManager.notify((String) appName, notId, mBuilder.build()); } - private static String getAppName(Context context) - { - CharSequence appName = - context - .getPackageManager() - .getApplicationLabel(context.getApplicationInfo()); - + private static String getAppName(Context context) { + CharSequence appName = context + .getPackageManager() + .getApplicationLabel(context.getApplicationInfo()); return (String)appName; } @@ -149,5 +224,4 @@ private static String getAppName(Context context) public void onError(Context context, String errorId) { Log.e(TAG, "onError - errorId: " + errorId); } - } diff --git a/src/android/com/plugin/gcm/PushPlugin.java b/src/android/com/plugin/gcm/PushPlugin.java index 3e390856..78db6559 100644 --- a/src/android/com/plugin/gcm/PushPlugin.java +++ b/src/android/com/plugin/gcm/PushPlugin.java @@ -12,6 +12,8 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import java.util.Iterator; @@ -20,226 +22,198 @@ */ public class PushPlugin extends CordovaPlugin { - public static final String TAG = "PushPlugin"; - - public static final String REGISTER = "register"; - public static final String UNREGISTER = "unregister"; - public static final String EXIT = "exit"; - - private static CordovaWebView gWebView; - private static String gECB; - private static String gSenderID; - private static Bundle gCachedExtras = null; - private static boolean gForeground = false; - - /** - * Gets the application context from cordova's main activity. - * @return the application context - */ - private Context getApplicationContext() { - return this.cordova.getActivity().getApplicationContext(); - } - - @Override - public boolean execute(String action, JSONArray data, CallbackContext callbackContext) { - - boolean result = false; - - Log.v(TAG, "execute: action=" + action); - - if (REGISTER.equals(action)) { - - Log.v(TAG, "execute: data=" + data.toString()); - - try { - JSONObject jo = data.getJSONObject(0); - - gWebView = this.webView; - Log.v(TAG, "execute: jo=" + jo.toString()); - - gECB = (String) jo.get("ecb"); - gSenderID = (String) jo.get("senderID"); - - Log.v(TAG, "execute: ECB=" + gECB + " senderID=" + gSenderID); - - GCMRegistrar.register(getApplicationContext(), gSenderID); - result = true; - callbackContext.success(); - } catch (JSONException e) { - Log.e(TAG, "execute: Got JSON Exception " + e.getMessage()); - result = false; - callbackContext.error(e.getMessage()); - } - - if ( gCachedExtras != null) { - Log.v(TAG, "sending cached extras"); - sendExtras(gCachedExtras); - gCachedExtras = null; - } - - } else if (UNREGISTER.equals(action)) { - - GCMRegistrar.unregister(getApplicationContext()); - - Log.v(TAG, "UNREGISTER"); - result = true; - callbackContext.success(); - } else { - result = false; - Log.e(TAG, "Invalid action : " + action); - callbackContext.error("Invalid action : " + action); - } - - return result; - } - - /* - * Sends a json object to the client as parameter to a method which is defined in gECB. - */ - public static void sendJavascript(JSONObject _json) { - String _d = "javascript:" + gECB + "(" + _json.toString() + ")"; - Log.v(TAG, "sendJavascript: " + _d); - - if (gECB != null && gWebView != null) { - gWebView.sendJavascript(_d); - } - } - - /* - * Sends the pushbundle extras to the client application. - * If the client application isn't currently active, it is cached for later processing. - */ - public static void sendExtras(Bundle extras) - { - if (extras != null) { - if (gECB != null && gWebView != null) { - sendJavascript(convertBundleToJson(extras)); - } else { - Log.v(TAG, "sendExtras: caching extras to send at a later time."); - gCachedExtras = extras; - } - } - } - - @Override - public void initialize(CordovaInterface cordova, CordovaWebView webView) { - super.initialize(cordova, webView); - gForeground = true; + public static final String TAG = "PushPlugin"; + + public static final String REGISTER = "register"; + public static final String UNREGISTER = "unregister"; + public static final String EXIT = "exit"; + + private static CordovaWebView gWebView; + private static String gECB; + private static String gSenderID; + private static Bundle gCachedExtras = null; + private static boolean gForeground = false; + + /** + * Gets the application context from cordova's main activity. + * @return the application context + */ + private Context getApplicationContext() { + return this.cordova.getActivity().getApplicationContext(); + } + + @Override + public boolean execute(String action, JSONArray data, + CallbackContext callbackContext) { + boolean result = false; + Log.v(TAG, "execute: action=" + action); + if (REGISTER.equals(action)) { + Log.v(TAG, "execute: data=" + data.toString()); + try { + JSONObject jo = data.getJSONObject(0); + gWebView = this.webView; + Log.v(TAG, "execute: jo=" + jo.toString()); + gECB = (String) jo.get("ecb"); + gSenderID = (String) jo.get("senderID"); + String reportLocationURL = (String) jo.get("reportLocationURL"); + SharedPreferences sharedPref = + PreferenceManager.getDefaultSharedPreferences( + getApplicationContext()); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString("reportLocationURL", reportLocationURL); + editor.commit(); + Log.v(TAG, "execute: ECB=" + gECB + " senderID=" + gSenderID); + GCMRegistrar.register(getApplicationContext(), gSenderID); + result = true; + callbackContext.success(); + } catch (JSONException e) { + Log.e(TAG, "execute: Got JSON Exception " + e.getMessage()); + result = false; + callbackContext.error(e.getMessage()); + } + if (gCachedExtras != null) { + Log.v(TAG, "sending cached extras"); + sendExtras(gCachedExtras); + gCachedExtras = null; + } + } else if (UNREGISTER.equals(action)) { + GCMRegistrar.unregister(getApplicationContext()); + Log.v(TAG, "UNREGISTER"); + result = true; + callbackContext.success(); + } else { + result = false; + Log.e(TAG, "Invalid action : " + action); + callbackContext.error("Invalid action : " + action); } - - @Override - public void onPause(boolean multitasking) { - super.onPause(multitasking); - gForeground = false; - final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancelAll(); + return result; + } + + /* + * Sends a json object to the client as parameter to a method which is defined + * in gECB. + */ + public static void sendJavascript(JSONObject _json) { + String _d = "javascript:" + gECB + "(" + _json.toString() + ")"; + Log.v(TAG, "sendJavascript: " + _d); + + if (gECB != null && gWebView != null) { + gWebView.sendJavascript(_d); } - - @Override - public void onResume(boolean multitasking) { - super.onResume(multitasking); - gForeground = true; + } + + /* + * Sends the pushbundle extras to the client application. + * If the client application isn't currently active, it is cached for later + * processing. + */ + public static void sendExtras(Bundle extras) { + if (extras != null) { + if (gECB != null && gWebView != null) { + sendJavascript(convertBundleToJson(extras)); + } else { + Log.v(TAG, "sendExtras: caching extras to send at a later time."); + gCachedExtras = extras; + } } - - @Override - public void onDestroy() { - super.onDestroy(); - gForeground = false; - gECB = null; - gWebView = null; + } + + @Override + public void initialize(CordovaInterface cordova, CordovaWebView webView) { + super.initialize(cordova, webView); + gForeground = true; + } + + @Override + public void onPause(boolean multitasking) { + super.onPause(multitasking); + gForeground = false; + final NotificationManager notificationManager = + (NotificationManager) cordova.getActivity() + .getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancelAll(); + } + + @Override + public void onResume(boolean multitasking) { + super.onResume(multitasking); + gForeground = true; + } + + @Override + public void onDestroy() { + super.onDestroy(); + gForeground = false; + gECB = null; + gWebView = null; + } + + /* + * serializes a bundle to JSON. + */ + private static JSONObject convertBundleToJson(Bundle extras) { + try { + JSONObject json; + json = new JSONObject().put("event", "message"); + + JSONObject jsondata = new JSONObject(); + Iterator it = extras.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + Object value = extras.get(key); + + // System data from Android + if (key.equals("from") || key.equals("collapse_key")) { + json.put(key, value); + } else if (key.equals("foreground")) { + json.put(key, extras.getBoolean("foreground")); + } else if (key.equals("coldstart")) { + json.put(key, extras.getBoolean("coldstart")); + } else { + // Maintain backwards compatibility + if (key.equals("message") || key.equals("msgcnt") || + key.equals("soundname")) { + json.put(key, value); + } + + if (value instanceof String) { + // Try to figure out if the value is another JSON object + String strValue = (String)value; + if (strValue.startsWith("{")) { + try { + JSONObject json2 = new JSONObject(strValue); + jsondata.put(key, json2); + } catch (Exception e) { + jsondata.put(key, value); + } + // Try to figure out if the value is another JSON array + } else if (strValue.startsWith("[")){ + try { + JSONArray json2 = new JSONArray(strValue); + jsondata.put(key, json2); + } catch (Exception e) { + jsondata.put(key, value); + } + } else { + jsondata.put(key, value); + } + } + } + } // while + json.put("payload", jsondata); + Log.v(TAG, "extrasToJSON: " + json.toString()); + return json; + } catch( JSONException e) { + Log.e(TAG, "extrasToJSON: JSON exception"); } + return null; + } - /* - * serializes a bundle to JSON. - */ - private static JSONObject convertBundleToJson(Bundle extras) - { - try - { - JSONObject json; - json = new JSONObject().put("event", "message"); - - JSONObject jsondata = new JSONObject(); - Iterator it = extras.keySet().iterator(); - while (it.hasNext()) - { - String key = it.next(); - Object value = extras.get(key); - - // System data from Android - if (key.equals("from") || key.equals("collapse_key")) - { - json.put(key, value); - } - else if (key.equals("foreground")) - { - json.put(key, extras.getBoolean("foreground")); - } - else if (key.equals("coldstart")) - { - json.put(key, extras.getBoolean("coldstart")); - } - else - { - // Maintain backwards compatibility - if (key.equals("message") || key.equals("msgcnt") || key.equals("soundname")) - { - json.put(key, value); - } - - if ( value instanceof String ) { - // Try to figure out if the value is another JSON object - - String strValue = (String)value; - if (strValue.startsWith("{")) { - try { - JSONObject json2 = new JSONObject(strValue); - jsondata.put(key, json2); - } - catch (Exception e) { - jsondata.put(key, value); - } - // Try to figure out if the value is another JSON array - } - else if (strValue.startsWith("[")) - { - try - { - JSONArray json2 = new JSONArray(strValue); - jsondata.put(key, json2); - } - catch (Exception e) - { - jsondata.put(key, value); - } - } - else - { - jsondata.put(key, value); - } - } - } - } // while - json.put("payload", jsondata); - - Log.v(TAG, "extrasToJSON: " + json.toString()); - - return json; - } - catch( JSONException e) - { - Log.e(TAG, "extrasToJSON: JSON exception"); - } - return null; - } + public static boolean isInForeground() { + return gForeground; + } - public static boolean isInForeground() - { - return gForeground; - } - - public static boolean isActive() - { - return gWebView != null; - } + public static boolean isActive() { + return gWebView != null; + } }