Java tutorial
/** * Copyright 2015 Google Inc. All Rights Reserved. * * 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 com.twofours.surespot.services; 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.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.support.v4.app.NotificationCompat; import android.support.v4.app.TaskStackBuilder; import android.text.TextUtils; import com.google.android.gms.gcm.GcmListenerService; import com.twofours.surespot.R; import com.twofours.surespot.SurespotApplication; import com.twofours.surespot.activities.MainActivity; import com.twofours.surespot.chat.ChatController; import com.twofours.surespot.chat.ChatUtils; import com.twofours.surespot.chat.SurespotMessage; import com.twofours.surespot.common.SurespotConstants; import com.twofours.surespot.common.SurespotLog; import com.twofours.surespot.identity.IdentityController; import com.twofours.surespot.ui.UIUtils; import java.util.ArrayList; import java.util.Date; public class SurespotGcmListenerService extends GcmListenerService { private static final String TAG = "SurespotGcmListenerService"; private PowerManager mPm; NotificationCompat.Builder mBuilder; NotificationManager mNotificationManager; @Override public void onCreate() { super.onCreate(); mPm = (PowerManager) getSystemService(Context.POWER_SERVICE); mBuilder = new NotificationCompat.Builder(this); mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); } /** * Called when message is received. * * @param senderId SenderID of the sender. * @param bundle Data bundle containing message data as key/value pairs. * For Set of keys use data.keySet(). */ // [START receive_message] @Override public void onMessageReceived(String senderId, Bundle bundle) { SurespotLog.i(TAG, "received GCM message, bundle: " + bundle); String to = bundle.getString("to"); String type = bundle.getString("type"); String from = bundle.getString("sentfrom"); if ("message".equals(type)) { // make sure to is someone on this phone if (!IdentityController.getIdentityNames(this).contains(to)) { return; } // if the chat is currently showing don't show a notification // TODO setting for this boolean isScreenOn = false; if (mPm != null) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { isScreenOn = mPm.isInteractive(); } else { isScreenOn = mPm.isScreenOn(); } } boolean hasLoggedInUser = IdentityController.hasLoggedInUser(); boolean sameUser = to.equals(IdentityController.getLoggedInUser()); //if current chat controller is for to user boolean tabOpenToUser = false; ChatController chatController = SurespotApplication.getChatController(); if (chatController != null) { if (to.equals(chatController.getUsername())) { //if tab is open on from user if (from.equals(chatController.getCurrentChat())) { tabOpenToUser = true; } } } boolean uiAttached = CommunicationService.isUIAttached(); SurespotLog.d(TAG, "gcm is screen on: %b, uiAttached: %b, hasLoggedInUser: %b, sameUser: %b, tabOpenToUser: %b", isScreenOn, uiAttached, hasLoggedInUser, sameUser, tabOpenToUser); if (hasLoggedInUser && isScreenOn && sameUser && tabOpenToUser && uiAttached) { SurespotLog.d(TAG, "not displaying gcm notification because the tab is open for it."); return; } String spot = ChatUtils.getSpot(from, to); // add the message if it came in the GCM String message = bundle.getString("message"); if (message != null) { SurespotMessage sm = SurespotMessage.toSurespotMessage(message); if (sm != null) { sm.setGcm(true); // see if we can add it to existing chat controller boolean added = false; if (chatController != null) { if (chatController.addMessageExternal(sm)) { SurespotLog.d(TAG, "adding gcm message to controller"); if (SurespotApplication.getCommunicationServiceNoThrow() != null) { SurespotApplication.getCommunicationService().saveMessages(from); } else { SurespotLog.w(TAG, "could not add gcm message to controller - transmission service was null"); } added = true; } } // if not add it directly if (!added) { ArrayList<SurespotMessage> messages = SurespotApplication.getStateController() .loadMessages(to, spot); if (!messages.contains(sm)) { messages.add(sm); SurespotLog.d(TAG, "added gcm message directly to disk"); added = true; SurespotApplication.getStateController().saveMessages(to, spot, messages, 0); } else { SurespotLog.d(TAG, "did not add gcm message directly to disk as it's already there"); // AEP what was happening here is it wasn't adding the message because // it's already been received on the websocket and saved to disk before the push message arrives // so gonna show notification now; was unnecessary before because the socket would have been // disconnected before push arrived if we got this far thanks to above isscreenon...etc. check // OE hmmm... is there a flag we can set if the main activity is not paused to indicate the user has truly "seen" the message or not? // added = true; } } if (added) { //String password = IdentityController.getStoredPasswordForIdentity(this, to); //SurespotLog.d(TAG, "GOT PASSWORD: %s", password); String fromName = null; //get friend name if we can otherwise no name if (sameUser && chatController != null) { fromName = chatController.getAliasedName(from); } generateNotification(this, SurespotConstants.IntentFilters.MESSAGE_RECEIVED, from, to, getString(R.string.notification_title), TextUtils.isEmpty(fromName) ? getString(R.string.notification_message_no_from, to) : getString(R.string.notification_message, to, fromName), to + ":" + spot, SurespotConstants.IntentRequestCodes.NEW_MESSAGE_NOTIFICATION); } } } return; } if ("invite".equals(type)) { // make sure to is someone on this phone if (!IdentityController.getIdentityNames(this).contains(to)) { return; } ChatController chatController = MainActivity.getChatController(); boolean sameUser = to.equals(IdentityController.getLoggedInUser()); String fromName = null; //get friend name if we can otherwise no name if (sameUser && chatController != null) { fromName = chatController.getAliasedName(from); } generateNotification(this, SurespotConstants.IntentFilters.INVITE_REQUEST, from, to, getString(R.string.notification_title), TextUtils.isEmpty(fromName) ? getString(R.string.notification_invite_no_from, to) : getString(R.string.notification_invite, to, fromName), to + ":" + from, SurespotConstants.IntentRequestCodes.INVITE_REQUEST_NOTIFICATION); return; } if ("inviteResponse".equals(type)) { // make sure to is someone on this phone if (!IdentityController.getIdentityNames(this).contains(to)) { return; } ChatController chatController = MainActivity.getChatController(); boolean sameUser = to.equals(IdentityController.getLoggedInUser()); String fromName = null; //get friend name if we can otherwise no name if (sameUser && chatController != null) { fromName = chatController.getAliasedName(from); } generateNotification(this, SurespotConstants.IntentFilters.INVITE_RESPONSE, from, to, getString(R.string.notification_title), TextUtils.isEmpty(fromName) ? getString(R.string.notification_invite_accept_no_from, to) : getString(R.string.notification_invite_accept, to, fromName), to, SurespotConstants.IntentRequestCodes.INVITE_RESPONSE_NOTIFICATION); return; } if ("system".equals(type)) { String tag = bundle.getString("tag"); String title = bundle.getString("title"); String message = bundle.getString("message"); if (!TextUtils.isEmpty(tag) && !TextUtils.isEmpty(message) && !TextUtils.isEmpty(title)) { generateSystemNotification(this, title, message, tag, SurespotConstants.IntentRequestCodes.SYSTEM_NOTIFICATION); } } } // [END receive_message] private void generateNotification(Context context, String type, String from, String to, String title, String message, String tag, int id) { SurespotLog.d(TAG, "generateNotification"); // get shared prefs SharedPreferences pm = context.getSharedPreferences(to, Context.MODE_PRIVATE); if (!pm.getBoolean("pref_notifications_enabled", true)) { return; } int icon = R.drawable.surespot_logo; // need to use same builder for only alert once to work: // http://stackoverflow.com/questions/6406730/updating-an-ongoing-notification-quietly mBuilder.setSmallIcon(icon).setContentTitle(title).setAutoCancel(true).setOnlyAlertOnce(false) .setContentText(message); TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); Intent mainIntent = null; mainIntent = new Intent(context, MainActivity.class); mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); mainIntent.putExtra(SurespotConstants.ExtraNames.MESSAGE_TO, to); mainIntent.putExtra(SurespotConstants.ExtraNames.MESSAGE_FROM, from); mainIntent.putExtra(SurespotConstants.ExtraNames.NOTIFICATION_TYPE, type); stackBuilder.addNextIntent(mainIntent); PendingIntent resultPendingIntent = stackBuilder.getPendingIntent((int) new Date().getTime(), PendingIntent.FLAG_CANCEL_CURRENT); mBuilder.setContentIntent(resultPendingIntent); int defaults = 0; boolean showLights = pm.getBoolean("pref_notifications_led", true); boolean makeSound = pm.getBoolean("pref_notifications_sound", true); boolean vibrate = pm.getBoolean("pref_notifications_vibration", true); int color = pm.getInt("pref_notification_color", getResources().getColor(R.color.surespotBlue)); if (showLights) { SurespotLog.v(TAG, "showing notification led"); mBuilder.setLights(color, 500, 5000); defaults |= Notification.FLAG_SHOW_LIGHTS; // shouldn't need this - setLights does it. Just to make sure though... } else { mBuilder.setLights(color, 0, 0); } if (makeSound) { SurespotLog.v(TAG, "making notification sound"); defaults |= Notification.DEFAULT_SOUND; } if (vibrate) { SurespotLog.v(TAG, "vibrating notification"); defaults |= Notification.DEFAULT_VIBRATE; } mBuilder.setDefaults(defaults); mNotificationManager.notify(tag, id, mBuilder.build()); } private void generateSystemNotification(Context context, String title, String message, String tag, int id) { // need to use same builder for only alert once to work: // http://stackoverflow.com/questions/6406730/updating-an-ongoing-notification-quietly mBuilder.setAutoCancel(true).setOnlyAlertOnce(true); int defaults = 0; mBuilder.setLights(0xff0000FF, 500, 5000); defaults |= Notification.DEFAULT_SOUND; defaults |= Notification.DEFAULT_VIBRATE; mBuilder.setDefaults(defaults); PendingIntent contentIntent = PendingIntent.getActivity(context, (int) new Date().getTime(), new Intent(), PendingIntent.FLAG_CANCEL_CURRENT); Notification notification = UIUtils.generateNotification(mBuilder, contentIntent, getPackageName(), title, message); mNotificationManager.notify(tag, id, notification); } }