diff options
Diffstat (limited to 'StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java')
| -rw-r--r-- | StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java new file mode 100644 index 00000000..f6faaa2b --- /dev/null +++ b/StoneIsland/plugins/phonegap-plugin-push/src/android/com/adobe/phonegap/push/PushPlugin.java @@ -0,0 +1,458 @@ +package com.adobe.phonegap.push; + +import android.app.NotificationManager; +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Log; + +import com.google.android.gms.gcm.GcmPubSub; +import com.google.android.gms.iid.InstanceID; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaWebView; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; + +import me.leolin.shortcutbadger.ShortcutBadger; + +public class PushPlugin extends CordovaPlugin implements PushConstants { + + public static final String LOG_TAG = "PushPlugin"; + + private static CallbackContext pushContext; + private static CordovaWebView gWebView; + private static List<Bundle> gCachedExtras = Collections.synchronizedList(new ArrayList<Bundle>()); + private static boolean gForeground = false; + + private static String registration_id = ""; + + /** + * 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(final String action, final JSONArray data, final CallbackContext callbackContext) { + Log.v(LOG_TAG, "execute: action=" + action); + gWebView = this.webView; + + if (INITIALIZE.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + pushContext = callbackContext; + JSONObject jo = null; + + Log.v(LOG_TAG, "execute: data=" + data.toString()); + SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + String senderID = null; + + try { + jo = data.getJSONObject(0).getJSONObject(ANDROID); + + Log.v(LOG_TAG, "execute: jo=" + jo.toString()); + + senderID = jo.getString(SENDER_ID); + + Log.v(LOG_TAG, "execute: senderID=" + senderID); + + String savedSenderID = sharedPref.getString(SENDER_ID, ""); + registration_id = InstanceID.getInstance(getApplicationContext()).getToken(senderID, GCM); + + if (!"".equals(registration_id)) { + JSONObject json = new JSONObject().put(REGISTRATION_ID, registration_id); + + Log.v(LOG_TAG, "onRegistered: " + json.toString()); + + JSONArray topics = jo.optJSONArray(TOPICS); + subscribeToTopics(topics, registration_id); + + PushPlugin.sendEvent( json ); + } else { + callbackContext.error("Empty registration ID received from GCM"); + return; + } + } catch (JSONException e) { + Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); + callbackContext.error(e.getMessage()); + } catch (IOException e) { + Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); + callbackContext.error(e.getMessage()); + } + + if (jo != null) { + SharedPreferences.Editor editor = sharedPref.edit(); + try { + editor.putString(ICON, jo.getString(ICON)); + } catch (JSONException e) { + Log.d(LOG_TAG, "no icon option"); + } + try { + editor.putString(ICON_COLOR, jo.getString(ICON_COLOR)); + } catch (JSONException e) { + Log.d(LOG_TAG, "no iconColor option"); + } + + boolean clearBadge = jo.optBoolean(CLEAR_BADGE, false); + if (clearBadge) { + setApplicationIconBadgeNumber(getApplicationContext(), 0); + } + + editor.putBoolean(SOUND, jo.optBoolean(SOUND, true)); + editor.putBoolean(VIBRATE, jo.optBoolean(VIBRATE, true)); + editor.putBoolean(CLEAR_BADGE, clearBadge); + editor.putBoolean(CLEAR_NOTIFICATIONS, jo.optBoolean(CLEAR_NOTIFICATIONS, true)); + editor.putBoolean(FORCE_SHOW, jo.optBoolean(FORCE_SHOW, false)); + editor.putString(SENDER_ID, senderID); + editor.commit(); + + } + + if (!gCachedExtras.isEmpty()) { + Log.v(LOG_TAG, "sending cached extras"); + synchronized(gCachedExtras) { + Iterator<Bundle> gCachedExtrasIterator = gCachedExtras.iterator(); + while (gCachedExtrasIterator.hasNext()) { + sendExtras(gCachedExtrasIterator.next()); + } + } + gCachedExtras.clear(); + } + } + }); + } else if (UNREGISTER.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + SharedPreferences sharedPref = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + JSONArray topics = data.optJSONArray(0); + if (topics != null && !"".equals(registration_id)) { + unsubscribeFromTopics(topics, registration_id); + } else { + InstanceID.getInstance(getApplicationContext()).deleteInstanceID(); + Log.v(LOG_TAG, "UNREGISTER"); + + // Remove shared prefs + SharedPreferences.Editor editor = sharedPref.edit(); + editor.remove(SOUND); + editor.remove(VIBRATE); + editor.remove(CLEAR_BADGE); + editor.remove(CLEAR_NOTIFICATIONS); + editor.remove(FORCE_SHOW); + editor.remove(SENDER_ID); + editor.commit(); + } + + callbackContext.success(); + } catch (IOException e) { + Log.e(LOG_TAG, "execute: Got JSON Exception " + e.getMessage()); + callbackContext.error(e.getMessage()); + } + } + }); + } else if (FINISH.equals(action)) { + callbackContext.success(); + } else if (HAS_PERMISSION.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + JSONObject jo = new JSONObject(); + try { + jo.put("isEnabled", PermissionUtils.hasPermission(getApplicationContext(), "OP_POST_NOTIFICATION")); + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, jo); + pluginResult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginResult); + } catch (UnknownError e) { + callbackContext.error(e.getMessage()); + } catch (JSONException e) { + callbackContext.error(e.getMessage()); + } + } + }); + } else if (SET_APPLICATION_ICON_BADGE_NUMBER.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + Log.v(LOG_TAG, "setApplicationIconBadgeNumber: data=" + data.toString()); + try { + setApplicationIconBadgeNumber(getApplicationContext(), data.getJSONObject(0).getInt(BADGE)); + } catch (JSONException e) { + callbackContext.error(e.getMessage()); + } + callbackContext.success(); + } + }); + } else if (CLEAR_ALL_NOTIFICATIONS.equals(action)) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + Log.v(LOG_TAG, "clearAllNotifications"); + clearAllNotifications(); + callbackContext.success(); + } + }); + } else if (SUBSCRIBE.equals(action)){ + // Subscribing for a topic + cordova.getThreadPool().execute(new Runnable() { + public void run() { + try { + String topic = data.getString(0); + subscribeToTopic(topic, registration_id); + callbackContext.success(); + } catch (JSONException e) { + callbackContext.error(e.getMessage()); + } catch (IOException e) { + callbackContext.error(e.getMessage()); + } + } + }); + } else if (UNSUBSCRIBE.equals(action)){ + // un-subscribing for a topic + cordova.getThreadPool().execute(new Runnable(){ + public void run() { + try { + String topic = data.getString(0); + unsubscribeFromTopic(topic, registration_id); + callbackContext.success(); + } catch (JSONException e) { + callbackContext.error(e.getMessage()); + } catch (IOException e) { + callbackContext.error(e.getMessage()); + } + } + }); + } else { + Log.e(LOG_TAG, "Invalid action : " + action); + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.INVALID_ACTION)); + return false; + } + + return true; + } + + public static void sendEvent(JSONObject _json) { + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, _json); + pluginResult.setKeepCallback(true); + if (pushContext != null) { + pushContext.sendPluginResult(pluginResult); + } + } + + public static void sendError(String message) { + PluginResult pluginResult = new PluginResult(PluginResult.Status.ERROR, message); + pluginResult.setKeepCallback(true); + if (pushContext != null) { + pushContext.sendPluginResult(pluginResult); + } + } + + /* + * 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 (gWebView != null) { + sendEvent(convertBundleToJson(extras)); + } else { + Log.v(LOG_TAG, "sendExtras: caching extras to send at a later time."); + gCachedExtras.add(extras); + } + } + } + + public static void setApplicationIconBadgeNumber(Context context, int badgeCount) { + if (badgeCount > 0) { + ShortcutBadger.applyCount(context, badgeCount); + } else { + ShortcutBadger.removeCount(context); + } + } + + @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; + + SharedPreferences prefs = getApplicationContext().getSharedPreferences(COM_ADOBE_PHONEGAP_PUSH, Context.MODE_PRIVATE); + if (prefs.getBoolean(CLEAR_NOTIFICATIONS, true)) { + clearAllNotifications(); + } + } + + @Override + public void onResume(boolean multitasking) { + super.onResume(multitasking); + gForeground = true; + } + + @Override + public void onDestroy() { + super.onDestroy(); + gForeground = false; + gWebView = null; + } + + private void clearAllNotifications() { + final NotificationManager notificationManager = (NotificationManager) cordova.getActivity().getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancelAll(); + } + + /** + * Transform `topic name` to `topic path` + * Normally, the `topic` inputed from end-user is `topic name` only. + * We should convert them to GCM `topic path` + * Example: + * when topic name = 'my-topic' + * then topic path = '/topics/my-topic' + * + * @param String topic The topic name + * @return The topic path + */ + private String getTopicPath(String topic) + { + return "/topics/" + topic; + } + + private void subscribeToTopics(JSONArray topics, String registrationToken) throws IOException { + if (topics != null) { + String topic = null; + for (int i=0; i<topics.length(); i++) { + topic = topics.optString(i, null); + subscribeToTopic(topic, registrationToken); + } + } + } + + private void subscribeToTopic(String topic, String registrationToken) throws IOException + { + try { + if (topic != null) { + Log.d(LOG_TAG, "Subscribing to topic: " + topic); + GcmPubSub.getInstance(getApplicationContext()).subscribe(registrationToken, getTopicPath(topic), null); + } + } catch (IOException e) { + Log.e(LOG_TAG, "Failed to subscribe to topic: " + topic, e); + throw e; + } + } + + private void unsubscribeFromTopics(JSONArray topics, String registrationToken) { + if (topics != null) { + String topic = null; + for (int i=0; i<topics.length(); i++) { + try { + topic = topics.optString(i, null); + if (topic != null) { + Log.d(LOG_TAG, "Unsubscribing to topic: " + topic); + GcmPubSub.getInstance(getApplicationContext()).unsubscribe(registrationToken, getTopicPath(topic)); + } + } catch (IOException e) { + Log.e(LOG_TAG, "Failed to unsubscribe to topic: " + topic, e); + } + } + } + } + + private void unsubscribeFromTopic(String topic, String registrationToken) throws IOException + { + try { + if (topic != null) { + Log.d(LOG_TAG, "Unsubscribing to topic: " + topic); + GcmPubSub.getInstance(getApplicationContext()).unsubscribe(registrationToken, getTopicPath(topic)); + } + } catch (IOException e) { + Log.e(LOG_TAG, "Failed to unsubscribe to topic: " + topic, e); + throw e; + } + } + + /* + * serializes a bundle to JSON. + */ + private static JSONObject convertBundleToJson(Bundle extras) { + Log.d(LOG_TAG, "convert extras to json"); + try { + JSONObject json = new JSONObject(); + JSONObject additionalData = new JSONObject(); + + // Add any keys that need to be in top level json to this set + HashSet<String> jsonKeySet = new HashSet(); + Collections.addAll(jsonKeySet, TITLE,MESSAGE,COUNT,SOUND,IMAGE); + + Iterator<String> it = extras.keySet().iterator(); + while (it.hasNext()) { + String key = it.next(); + Object value = extras.get(key); + + Log.d(LOG_TAG, "key = " + key); + + if (jsonKeySet.contains(key)) { + json.put(key, value); + } + else if (key.equals(COLDSTART)) { + additionalData.put(key, extras.getBoolean(COLDSTART)); + } + else if (key.equals(FOREGROUND)) { + additionalData.put(key, extras.getBoolean(FOREGROUND)); + } + else if ( value instanceof String ) { + String strValue = (String)value; + try { + // Try to figure out if the value is another JSON object + if (strValue.startsWith("{")) { + additionalData.put(key, new JSONObject(strValue)); + } + // Try to figure out if the value is another JSON array + else if (strValue.startsWith("[")) { + additionalData.put(key, new JSONArray(strValue)); + } + else { + additionalData.put(key, value); + } + } catch (Exception e) { + additionalData.put(key, value); + } + } + } // while + + json.put(ADDITIONAL_DATA, additionalData); + Log.v(LOG_TAG, "extrasToJSON: " + json.toString()); + + return json; + } + catch( JSONException e) { + Log.e(LOG_TAG, "extrasToJSON: JSON exception"); + } + return null; + } + + public static boolean isInForeground() { + return gForeground; + } + + public static boolean isActive() { + return gWebView != null; + } + + protected static void setRegistrationID(String token) { + registration_id = token; + } +} |
