/*
* Copyright 2014-2015 GameUp
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gameup.android.push;
import java.io.IOException;
import java.util.LinkedList;
import org.json.*;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/**
* Helper for various push notification functions.
*/
public class Push {
/** Used to register for push notifications. */
private static final String GOOGLE_PROJECT = "132114574564";
public interface NotificationOpenedHandler {
/**
* A custom handler interface. If a handler is registered, it is called
* when the gamer opens a push notification.
*
* @param message The message associated with the notification.
* @param additionalData Any additional background data received.
*/
void notificationOpened(String message, JSONObject additionalData);
}
private static Activity appContext;
private static NotificationOpenedHandler notificationOpenedHandler;
public static void init(final Activity context,
final NotificationOpenedHandler handler) {
appContext = context;
notificationOpenedHandler = handler;
// Called from tapping on a Notification from the status bar when the
// activity is completely dead and not open in any state.
if (appContext.getIntent() != null &&
appContext.getIntent().getBundleExtra("data") != null) {
runNotificationOpenedCallback(
appContext.getIntent().getBundleExtra("data"), true);
}
}
public static String registerForPush(final Context context) {
try {
return GoogleCloudMessaging.getInstance(context)
.register(GOOGLE_PROJECT);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private static void runNotificationOpenedCallback(final Bundle data,
final boolean isUiThread) {
try {
final JSONObject custom = new JSONObject(data.getString("custom"));
if (notificationOpenedHandler != null) {
JSONObject additionalDataJSON = new JSONObject();
if (custom.has("a")) {
additionalDataJSON = custom.getJSONObject("a");
}
if (additionalDataJSON.equals(new JSONObject())) {
additionalDataJSON = null;
}
final JSONObject finalAdditionalDataJSON = additionalDataJSON;
Runnable callBack = new Runnable() {
@Override
public void run() {
notificationOpenedHandler.notificationOpened(
data.getString("alert"),
finalAdditionalDataJSON);
}
};
if (isUiThread) {
callBack.run();
}
else {
appContext.runOnUiThread(callBack);
}
}
} catch (final Throwable t) {}
}
// Called when opening a notification when the app is suspended in the
// background.
public static void handleNotificationOpened(final Context inContext,
final Bundle data) {
// Open/Resume app when opening the notification.
final Intent launchIntent = inContext.getPackageManager()
.getLaunchIntentForPackage(inContext.getPackageName())
.putExtra("data", data);
launchIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
inContext.startActivity(launchIntent);
runNotificationOpenedCallback(data, false);
}
// If true(default) - Device will always vibrate unless the device is in
// silent mode. If false - Device will only vibrate when the device is set
// on its vibrate only mode.
public static void enableVibrate(final boolean enable) {
final SharedPreferences prefs = getGcmPreferences(appContext);
final SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("GT_VIBRATE_ENABLED", enable);
editor.commit();
}
public static boolean isVibrateEnabled(final Context appContext) {
final SharedPreferences prefs = getGcmPreferences(appContext);
return prefs.getBoolean("GT_VIBRATE_ENABLED", true);
}
// If true(default) - Sound plays when receiving notification. Vibrates when
// device is on vibrate only mode. If false - Only vibrates unless
// enableVibrate(false) was set.
public static void enableSound(final boolean enable) {
final SharedPreferences prefs = getGcmPreferences(appContext);
final SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("GT_SOUND_ENABLED", enable);
editor.commit();
}
public static boolean isSoundEnabled(final Context appContext) {
final SharedPreferences prefs = getGcmPreferences(appContext);
return prefs.getBoolean("GT_SOUND_ENABLED", true);
}
static SharedPreferences getGcmPreferences(final Context context) {
return context.getSharedPreferences(
Push.class.getSimpleName(), Context.MODE_PRIVATE);
}
private static LinkedList<String> notificationsReceivedStack;
private static void getNotificationsReceived(final Context context) {
if (notificationsReceivedStack == null) {
notificationsReceivedStack = new LinkedList<String>();
final SharedPreferences prefs = getGcmPreferences(context);
final String jsonListStr = prefs.getString(
"GT_RECEIVED_NOTIFICATION_LIST", null);
if (jsonListStr != null) {
try {
final JSONArray received = new JSONArray(jsonListStr);
for (int i = 0; i < received.length(); i++) {
notificationsReceivedStack.push(received.getString(i));
}
} catch (final Throwable t) {}
}
}
}
private static void addNotificationIdToList(final String id,
final Context context) {
getNotificationsReceived(context);
if (notificationsReceivedStack == null) {
return;
}
if (notificationsReceivedStack.size() >= 10) {
notificationsReceivedStack.removeLast();
}
notificationsReceivedStack.addFirst(id);
final JSONArray jsonArray = new JSONArray();
String notificationId;
for (int i = notificationsReceivedStack.size() - 1; i > -1; i--) {
notificationId = notificationsReceivedStack.get(i);
if (notificationId == null) {
continue;
}
jsonArray.put(notificationsReceivedStack.get(i));
}
final SharedPreferences prefs = getGcmPreferences(context);
final SharedPreferences.Editor editor = prefs.edit();
editor.putString("GT_RECEIVED_NOTIFICATION_LIST", jsonArray.toString());
editor.commit();
}
static boolean isDuplicateNotification(final String id,
final Context context) {
getNotificationsReceived(context);
if (notificationsReceivedStack == null || id == null || "".equals(id)) {
return false;
}
if (notificationsReceivedStack.contains(id)) {
return true;
}
addNotificationIdToList(id, context);
return false;
}
static boolean isValidAndNotDuplicated(final Context context,
final Bundle bundle) {
if (bundle.isEmpty()) {
return false;
}
try {
if (bundle.containsKey("custom")) {
final JSONObject customJSON =
new JSONObject(bundle.getString("custom"));
if (customJSON.has("i")) {
return !Push.isDuplicateNotification(
customJSON.getString("i"), context);
}
}
} catch (final Throwable t) {}
return false;
}
}