package com.malcom.library.android.module.notifications.gcm; import static com.malcom.library.android.module.notifications.MCMNotificationModule.applicationCode; import static com.malcom.library.android.module.notifications.MCMNotificationModule.applicationSecretkey; import static com.malcom.library.android.module.notifications.MCMNotificationModule.environmentType; import static com.malcom.library.android.module.notifications.MCMNotificationModule.senderId; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.Random; import java.util.Set; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Bundle; import android.os.PowerManager; import android.util.Log; import com.google.android.gcm.GCMBaseIntentService; import com.google.android.gcm.GCMRegistrar; import com.malcom.library.android.MCMDefines; import com.malcom.library.android.exceptions.ApplicationPackageNotFoundException; import com.malcom.library.android.module.notifications.MCMNotificationModule; /** * Service responsible for handling GCM messages. * * @author Malcom Ventures, S.L. * @since 2012 */ public class GCMIntentService extends GCMBaseIntentService { private static final String TAG = "Malcom GCMIntentService"; private static final Random rnd = new Random(); private static PowerManager.WakeLock wakeLock; private static int idNotification; public GCMIntentService() { super(senderId); idNotification = 0; } protected String getSenderId(Context context) { final SharedPreferences prefs = context.getSharedPreferences( "GCM_SETTINGS", 0); final String id = prefs.getString("GCM_SENDER_ID", null ); return prefs.getString(id, null); } @Override protected void onRegistered(Context context, String registrationId) { Log.i(MCMDefines.LOG_TAG, "Device registered: regId = " + registrationId); // Get the stored registrationId and if it's not equal, update it at server String regId = GCMRegistrar.getRegistrationId(context); if (regId != null) { if(!MalcomServerUtilities.register(context, registrationId, environmentType, applicationCode, applicationSecretkey)){ GCMRegistrar.unregister(context); } } } @Override protected void onUnregistered(Context context, String registrationId) { Log.i(MCMDefines.LOG_TAG, "Device unregistered"); if (GCMRegistrar.isRegisteredOnServer(context)) { MalcomServerUtilities.unregister(context, registrationId, applicationCode, applicationSecretkey); } else { // This callback results from the call to unregister made on // MalcomServerUtilities when the registration to the server failed. Log.i(MCMDefines.LOG_TAG, "Ignoring unregister callback"); } } @Override protected void onMessage(Context context, Intent intent) { Log.i(MCMDefines.LOG_TAG, "Received a new notification message"); generateNotification(context.getApplicationContext(), intent); } @Override public void onError(Context context, String errorId) { Log.e(MCMDefines.LOG_TAG, "Received error: " + errorId); } /* * Issues a notification to inform the user about the received notification. */ private static void generateNotification(Context context, Intent intent) { try { int iconResId = getApplicationIcon(context); long when = System.currentTimeMillis(); SharedPreferences prefs = context.getSharedPreferences( "GCM_SETTINGS", 0); String title = prefs.getString(MCMNotificationModule.GCM_TITLE_NOTIFICATION, ""); String message = (String)intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY); try { message = URLDecoder.decode(message, "UTF8"); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (NullPointerException npe) { npe.printStackTrace(); } String webUrl = (String)intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY + "." + MCMNotificationModule.ANDROID_MESSAGE_RICHMEDIA_KEY); String efficacyKey = (String)intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY + "." + MCMNotificationModule.ANDROID_MESSAGE_EFFICACY_KEY); String segmentId = null; if(intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY + "." + MCMNotificationModule.ANDROID_MESSAGE_SEGMENT_KEY)!=null){ segmentId = (String)intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY + "." + MCMNotificationModule.ANDROID_MESSAGE_SEGMENT_KEY); } Notification notification = new Notification(iconResId, message, when); // Hide the notification after its selected notification.flags |= Notification.FLAG_AUTO_CANCEL; // Vibration notification.defaults |= Notification.DEFAULT_VIBRATE; notification.defaults |= Notification.DEFAULT_LIGHTS; // Sound String soundName = (String)intent.getExtras().get(MCMNotificationModule.ANDROID_MESSAGE_KEY + "." + MCMNotificationModule.ANDROID_NOTIFICATION_SOUND_KEY); int notificationSoundId = 0; if (soundName != null) { notificationSoundId = context.getResources().getIdentifier(soundName , "raw", context.getPackageName()); } if (notificationSoundId != 0) { notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "/"+notificationSoundId); } else { notification.defaults |= Notification.DEFAULT_SOUND; } String className = prefs.getString("GCM_CLASS", null ); Class classNotification = null; try { classNotification = Class.forName(className); } catch (ClassNotFoundException e) { Log.d(MCMDefines.LOG_TAG, "Class not found: "+className); } if (classNotification == null) { classNotification = GCMIntentService.class; } Intent notificationIntent = new Intent(context, classNotification); //Required to avoid getting the same intent in the activity each time. Each message is different so //the intent should be different (the action) so extras can be different. notificationIntent.setAction((String.valueOf(rnd.nextLong())+message)); notificationIntent.putExtra(MCMNotificationModule.HAS_NOTIFICATION_TO_HANDLE, true); notificationIntent.putExtra(MCMNotificationModule.ANDROID_MESSAGE_EFFICACY_KEY, efficacyKey); if(segmentId!=null) notificationIntent.putExtra(MCMNotificationModule.ANDROID_MESSAGE_SEGMENT_KEY,segmentId); notificationIntent.putExtra(MCMNotificationModule.ANDROID_MESSAGE_KEY, message); notificationIntent.putExtra(MCMNotificationModule.ANDROID_MESSAGE_RICHMEDIA_KEY, webUrl); // Add custom fields notificationIntent.putExtras(intent); //Set intent so it does not start a new activity // //Notes: // - The flag FLAG_ACTIVITY_SINGLE_TOP makes that only one instance of the activity exists(each time the // activity is summoned no onCreate() method is called instead, onNewIntent() is called. // - If we use FLAG_ACTIVITY_CLEAR_TOP it will make that the last "snapshot"/TOP of the activity it will // be this called this intent. We do not want this because the HOME button will call this "snapshot". // To avoid this behaviour we use FLAG_ACTIVITY_BROUGHT_TO_FRONT that simply takes to foreground the // activity. // //See http://developer.android.com/reference/android/content/Intent.html notificationIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); notification.setLatestEventInfo(context, title, message, pendingIntent); //This makes the device to wake-up is is idle with the screen off. wakeUp(context); NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE); Random randomGenerator = new Random(); idNotification = randomGenerator.nextInt(1000); notificationManager.notify(idNotification, notification); Log.d(MCMDefines.LOG_TAG, "Notification created for the recieve PUSH message."); } catch (ApplicationPackageNotFoundException e) { Log.e(MCMDefines.LOG_TAG, "The notification could not be created because it is not possible to locate the application icon."); } } /* * gets the application Icon. * * @param context * @return * @throws ApplicationPackageNotFoundException */ private static int getApplicationIcon(Context context) throws ApplicationPackageNotFoundException{ try { //ApplicationInfo app = context.getPackageManager().getApplicationInfo(MCMCoreAdapter.applicationPackage, 0); PackageManager pm = context.getPackageManager(); PackageInfo packageInfo = pm.getPackageInfo(context.getPackageName(), 0); ApplicationInfo app = context.getPackageManager().getApplicationInfo(packageInfo.packageName, 0); return app.icon; } catch (NameNotFoundException e) { Log.e(MCMDefines.LOG_TAG, "Application package not found!."); throw new ApplicationPackageNotFoundException(); } } /* * Makes the device to wake-up. yeah! * * @param ctx */ public static void wakeUp(Context ctx) { // Log.d(MCMDefines.LOG_TAG, "Wake up!."); if (wakeLock != null) wakeLock.release(); PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); boolean isScreenOn = pm.isScreenOn(); if(isScreenOn==false) { PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.ON_AFTER_RELEASE,"malcom_library_wakeup"); wl.acquire(10000); PowerManager.WakeLock wl_cpu = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"malcom_library_cpuwakeup"); wl_cpu.acquire(10000); } } }