at.ac.uniklu.mobile.sportal.notification.GCMUtils.java Source code

Java tutorial

Introduction

Here is the source code for at.ac.uniklu.mobile.sportal.notification.GCMUtils.java

Source

/*
 * Copyright (c) 2014 Mario Guggenberger <mario.guggenberger@aau.at>
 *
 * This file is part of AAU Studentenportal.
 *
 * AAU Studentenportal is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * AAU Studentenportal is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AAU Studentenportal.  If not, see <http://www.gnu.org/licenses/>.
 */

package at.ac.uniklu.mobile.sportal.notification;

import java.lang.reflect.Method;

import com.google.android.gcm.GCMRegistrar;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import at.ac.uniklu.mobile.sportal.R;
import at.ac.uniklu.mobile.sportal.Studentportal;
import at.ac.uniklu.mobile.sportal.util.Analytics;
import at.ac.uniklu.mobile.sportal.util.Preferences;

public class GCMUtils {

    private static final String TAG = "GCMUtils";

    public static final int DISABLED = 1;
    public static final int ALREADY_REGISTERED = 2;
    public static final int REGISTERING_TRIGGERED = 3;
    public static final int UNSUPPORTED = 4;

    public static final String SENDER_ID = "222426773067";

    public static NotificationCompat.Builder getDefaultNotification(Context context) {
        String defaultText = context.getString(R.string.app_name);
        return new NotificationCompat.Builder(context)
                .setDefaults(android.app.Notification.DEFAULT_VIBRATE | android.app.Notification.DEFAULT_SOUND)
                .setLights(context.getResources().getColor(R.color.unilightblue), 1000, 3000).setAutoCancel(true)
                .setOnlyAlertOnce(true).setTicker(defaultText).setContentTitle(defaultText)
                .setSmallIcon(R.drawable.ic_stat_default);
    }

    public static NotificationCompat.Builder getBroadcastMessageNotification(Context context, CharSequence message,
            String url) {
        NotificationCompat.Builder nb = getDefaultNotification(context).setContentText(message)
                .setStyle(new NotificationCompat.BigTextStyle().bigText(message));

        Intent i;

        if (url != null) {
            i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        } else {
            i = new Intent();
        }

        PendingIntent pi = PendingIntent.getActivity(context, 0, i, Intent.FLAG_ACTIVITY_NEW_TASK);
        nb.setContentIntent(pi);

        return nb;
    }

    public static int register(Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        if (Preferences.isNotificationsEnabled(context, preferences)) {
            //GCMRegistrar.unregister(context);
            try {
                GCMRegistrar.checkDevice(context);
                if (Studentportal.isDebugBuild()) { // the published app manifest doesn't need to be checked
                    GCMRegistrar.checkManifest(context);
                }
                String regId = GCMRegistrar.getRegistrationId(context);
                if (regId.equals("")) {
                    GCMRegistrar.register(context, SENDER_ID);
                    return REGISTERING_TRIGGERED;
                } else {
                    Log.v(TAG, "Already registered");
                    return ALREADY_REGISTERED;
                }
            } catch (UnsupportedOperationException e) {
                Log.i(TAG, "this device doesn't support cloud messaging");
                Toast.makeText(context, R.string.error_notification_not_supported, Toast.LENGTH_SHORT).show();
                Preferences.setNotificationsEnabled(context, preferences, false);
                GCMStatusBroadcastCommunicator.sendBroadcast(context,
                        new Intent().putExtra(GCMStatusBroadcastCommunicator.EXTRA_GCM_UP, false));
                return UNSUPPORTED;
            }
        } else {
            return DISABLED;
        }
    }

    public static void unregister(Context context) {
        GCMRegistrar.unregister(context);
    }

    /**
     * 
     * @param context
     * @return true if registered and unregistering has been triggered, false if not registered
     */
    public static boolean unregisterIfRegistered(Context context) {
        if (GCMRegistrar.isRegistered(context)) {
            GCMUtils.unregister(context);
            return true;
        }
        return false;
    }

    public static void registerToCampus(Context context, String regId) {
        context.startService(new Intent(context, GCMCampusService.class).setAction(GCMCampusService.ACTION_REGISTER)
                .putExtra(GCMCampusService.EXTRA_REGID, regId));
    }

    public static void unregisterFromCampus(Context context, String regId) {
        context.startService(new Intent(context, GCMCampusService.class)
                .setAction(GCMCampusService.ACTION_UNREGISTER).putExtra(GCMCampusService.EXTRA_REGID, regId));
    }

    public static void notifyUser(Context context) {
        context.startService(new Intent(context, GCMCampusService.class).setAction(GCMCampusService.ACTION_NOTIFY));
    }

    public static void OnMainActivityCreate(Context context) {
        int registrationStatus = register(context);

        /* If the app has been registered to GCM but not to the campus server, catch
         * up the registration on the campus server. */
        if (registrationStatus == ALREADY_REGISTERED && !GCMRegistrar.isRegisteredOnServer(context)) {
            registerToCampus(context, GCMRegistrar.getRegistrationId(context));
        }
    }

    public static void OnMainActivityDestroy(Context context) {
        // application context must be used, else an exception is thrown
        // http://stackoverflow.com/a/11937272
        GCMRegistrar.onDestroy(context.getApplicationContext());
    }

    /**
     * Clears the registered GCM ID and makes the GCM library think that the app isn't 
     * registered at GCM.
     * After this method has been called, the ID is still stored in the GCM system and
     * also on the campus server for the previous user. Sooner or later the GCM will
     * invalidate the ID (either because it's getting too old or it notices that no client
     * responds to messages with this ID [just my wild guess]), similar to the process
     * described here: http://developer.android.com/google/gcm/adv.html#unreg
     * At some later time the campus server might want to send a message to the device
     * with this ID, get the answer from GCM that the ID is invalid and delete it from
     * it's database.
     * The GCM library does exactly the same after the app has been updated to a new
     * version, so this procedure should be save and the server infrastructure should
     * be able to handle it.
     */
    public static void clearRegistrationId(Context context) {
        try {
            /* The method is private and therefore needs to be accessed by reflection.
             * Maybe Google doesn't want app to call it directly, but the alternative would
             * be to set up a much more complicated workflow that first unregisters the app,
             * and then checks in the onUnregistered handler if some flag is set that tells
             * the app to register again. The advantage would though be, that the ID gets
             * invalidated instantly in the GCM system. */
            Method m = GCMRegistrar.class.getDeclaredMethod("clearRegistrationId", Context.class);
            m.setAccessible(true);
            m.invoke(null, context);
        } catch (Exception e) {
            Log.e(TAG, "reflection call to clear regId failed", e);
            Analytics.onError(Analytics.ERROR_GCM_CLEAR_REGID, e);
        }
    }
}