net.omplanet.starwheel.GCMIntentService.java Source code

Java tutorial

Introduction

Here is the source code for net.omplanet.starwheel.GCMIntentService.java

Source

/*
 * Copyright (c) 2013 Google Inc.
 *
 * 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 net.omplanet.starwheel;

import java.io.IOException;

import net.omplanet.starwheel.cloud.backend.core.Consts;
import android.app.Application;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;

/**
 * This class manages Google Cloud Messaging push notifications and CloudQuery
 * subscriptions.
 */
public class GCMIntentService extends IntentService {

    private static final String GCM_KEY_SUBID = "subId";

    private static final String GCM_TYPEID_QUERY = "query";

    private static final String PROPERTY_REG_ID = "registration_id";

    private static final String PROPERTY_APP_VERSION = "app_version";

    public static final String BROADCAST_ON_MESSAGE = "on-message-event";

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        // The getMessageType() intent parameter must be the intent you received
        // in your BroadcastReceiver.
        String messageType = gcm.getMessageType(intent);

        if (!extras.isEmpty()) { // has effect of unparcelling Bundle
            /*
             * Filter messages based on message type. Since it is likely that GCM will be
             * extended in the future with new message types, just ignore any message types you're
             * not interested in, or that you don't recognize.
             */
            if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                Log.i(Consts.TAG, "onHandleIntent: message error");
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
                Log.i(Consts.TAG, "onHandleIntent: message deleted");
                // If it's a regular GCM message, do some work.
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                String subId = intent.getStringExtra(GCM_KEY_SUBID);
                Log.i(Consts.TAG, "onHandleIntent: subId: " + subId);
                String[] tokens = subId.split(":");
                String typeId = tokens[1];

                // dispatch message
                if (GCM_TYPEID_QUERY.equals(typeId)) {
                    Intent messageIntent = new Intent(BROADCAST_ON_MESSAGE);
                    messageIntent.putExtras(intent);
                    messageIntent.putExtra("token", tokens[2]);
                    boolean isReceived = LocalBroadcastManager.getInstance(this).sendBroadcast(messageIntent);

                    //Send push notification if the application did not receive the broadcast.
                    if (!isReceived) {
                        Log.i(Consts.TAG, "A message has been recieved but no broadcast was handled.");
                        NotificationUtil.generateNotification(this, intent);
                    } else {
                        Log.i(Consts.TAG, "A message has been recieved, broadcasted and handled.");
                    }
                }
            }
        }
        // Release the wake lock provided by the WakefulBroadcastReceiver.
        GCMBroadcastReceiver.completeWakefulIntent(intent);
    }

    /**
     * Returns registration id associated with the specified {@link Application}
     * . This method will block the thread until regId will be available.
     * 
     * @param app {@link Application}
     * @return registration id
     */
    public static String getRegistrationId(Application app) {
        SharedPreferences prefs = getGcmPreferences(app);
        String regId = prefs.getString(PROPERTY_REG_ID, "");

        if (regId.isEmpty()) {
            Log.i(Consts.TAG, "Registration not found.");
            return doRegister(app);
        }
        // Check if app was updated; if so, it must clear the registration ID
        // since the existing regID is not guaranteed to work with the new
        // app version.
        int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
        int currentVersion = getAppVersion(app);
        if (registeredVersion != currentVersion) {
            Log.i(Consts.TAG, "App version changed.");
            return doRegister(app);
        }
        return regId;
    }

    private static String doRegister(Context context) {
        String msg = "";

        try {
            // Check device for Play Services APK. If check succeeds, proceed with GCM registration.
            if (checkPlayServices(context)) {
                GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
                String regId = gcm.register(Consts.PROJECT_NUMBER);
                msg = "Device registered, registration ID=" + regId;

                // For this demo: we don't need to send it because the device will send
                // upstream messages to a server that echo back the message using the
                // 'from' address in the message.

                SharedPreferences prefs = getGcmPreferences(context);
                int appVersion = getAppVersion(context);
                Log.i(Consts.TAG, "Saving regId on app version " + appVersion);
                SharedPreferences.Editor editor = prefs.edit();
                editor.putString(PROPERTY_REG_ID, regId);
                editor.putInt(PROPERTY_APP_VERSION, appVersion);
                editor.commit();
            } else {
                Log.i(Consts.TAG, "No valid Google Play Services APK found.");
            }
        } catch (IOException ex) {
            msg = "Error :" + ex.getMessage();
            // If there is an error, don't just keep trying to register.
            // Require the user to click a button again, or perform
            // exponential back-off.
        }
        return msg;
    }

    public GCMIntentService() {
        super(Consts.PROJECT_NUMBER);
    }

    /**
     * @return the stored SharedPreferences for GCM
     */
    private static SharedPreferences getGcmPreferences(Context context) {
        return context.getSharedPreferences(GCMIntentService.class.getSimpleName(), MODE_PRIVATE);
    }

    /**
     * @return Application's version code from the {@code PackageManager}.
     */
    private static int getAppVersion(Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionCode;
        } catch (NameNotFoundException e) {
            // should never happen
            throw new RuntimeException("Could not get package name: " + e);
        }
    }

    /**
     * Check the device to make sure it has the Google Play Services APK. If
     * it doesn't, display a dialog that allows users to download the APK from
     * the Google Play Store or enable it in the device's system settings.
     */
    private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

    private static boolean checkPlayServices(Context context) {
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
        if (resultCode != ConnectionResult.SUCCESS) {
            return false;
        }
        return true;
    }
}