/*
* Copyright (c) 2012 Socialize Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.socialize.notifications;
import android.app.Notification;
import android.content.Context;
import android.os.Bundle;
import com.socialize.api.SocializeSession;
import com.socialize.api.action.user.UserSystem;
import com.socialize.config.SocializeConfig;
import com.socialize.entity.JSONFactory;
import com.socialize.entity.User;
import com.socialize.error.SocializeException;
import com.socialize.log.SocializeLogger;
import com.socialize.ui.profile.UserSettings;
import com.socialize.util.AppUtils;
import com.socialize.util.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Map;
/**
* @author Jason Polites
*/
public class SocializeC2DMCallback implements C2DMCallback {
private int notificationIcon = android.R.drawable.sym_action_chat;
private SocializeLogger logger;
private SocializeConfig config;
private AppUtils appUtils;
private UserSystem userSystem;
private Map<String, JSONFactory<NotificationMessage>> messageFactories;
private Map<String, NotificationMessageBuilder> messageBuilders;
private NotificationRegistrationState notificationRegistrationState;
private NotificationRegistrationSystem notificationRegistrationSystem;
private NotificationManagerFacade notificationManagerFacade;
@Override
public void onRegister(Context context, String registrationId) {
if(logger != null && logger.isInfoEnabled()) {
logger.info("Registration with GCM successful: " + registrationId);
if(logger.isDebugEnabled()) {
logger.debug("GCM ID [" +
registrationId +
"]");
}
}
notificationRegistrationState.setC2DMRegistrationId(registrationId);
notificationRegistrationState.save(context);
// Trigger socialize registration
notificationRegistrationSystem.registerSocialize(context, registrationId);
}
@Override
public void onError(Context context, String errorId) {
if(logger != null && logger.isWarnEnabled()) {
logger.warn("Registration with GCM failed: " + errorId);
}
}
@Override
public void onUnregister(Context context) {
// Do nothing
}
/* (non-Javadoc)
* @see com.socialize.notifications.NotificationSystem#sendNotification(android.os.Bundle)
*/
@Override
public void onMessage(final Context context, final Bundle data) {
// DON'T Use Socialize instance here, we are using a different container!
try {
// This should be synchronous. We don't want to launch an async task off the main UI thread.
SocializeSession session = userSystem.authenticateSynchronous(context, config.getProperty(SocializeConfig.SOCIALIZE_CONSUMER_KEY), config.getProperty(SocializeConfig.SOCIALIZE_CONSUMER_SECRET));
handleNotification(context, data, session);
}
catch (SocializeException e) {
handleError("Failed to authenticate user for notification receipt", e);
}
}
protected void handleNotification(final Context context, final Bundle data, final SocializeSession session) {
final UserSettings settings = session.getUserSettings();
final User user = session.getUser();
if(settings != null && settings.isNotificationsEnabled()) {
String json = data.getString(MESSAGE_KEY);
if(!StringUtils.isEmpty(json)) {
if(logger != null && logger.isDebugEnabled()) {
logger.debug("Received notification [" +
json +
"]");
}
try {
JSONObject message = newJSONObject(json);
String notification_type = "notification_type";
if(message.has(notification_type) && !message.isNull(notification_type)) {
String type = message.getString(notification_type).trim().toUpperCase();
NotificationType notificationType = null;
try {
notificationType = NotificationType.valueOf(type);
}
catch (Exception e) {
handleError("Invalid notification_type [" +
type +
"] defined in notification message [" +
json +
"]", e);
}
if(notificationType != null) {
JSONFactory<NotificationMessage> factory = messageFactories.get(notificationType.name());
if(factory != null) {
NotificationMessage notificationMessage = factory.fromJSON(message);
NotificationMessageBuilder builder = messageBuilders.get(notificationType.name());
if(builder != null) {
int icon = getNotificationIcon(context);
Notification notification = builder.build(context, data, notificationMessage, icon);
doNotify(context, getNotificationTag(notificationMessage), getNotificationId(notificationMessage), notification);
}
else {
handleError("No message builder defined for notification type [" +
notificationType +
"]");
}
}
else {
handleError("No message factory defined for notification type [" +
notificationType +
"]");
}
}
}
else {
handleError("No notification_type defined in notification message [" +
json +
"]");
}
}
catch (JSONException e) {
handleError("Notification system received an invalid JSON message [" +
json +
"]", e);
}
catch (Exception e) {
handleError("Error building notification message", e);
}
}
else {
handleError("No data found in message bundle under key [" +
MESSAGE_KEY +
"]");
}
}
else {
if(settings == null) {
handleError("No user settings found in session!");
}
else {
if(logger != null && logger.isDebugEnabled()) {
logger.debug("Notification for user [" +
user.getId() +
"] ignored. Notifications are disabled for this user");
}
}
}
}
protected void doNotify(Context context, String tag, int id, Notification notification) {
notificationManagerFacade.notify(context, tag, id, notification);
}
protected String getNotificationTag(NotificationMessage message) {
if(message.getEntityId() != null) {
return String.valueOf(message.getEntityId().longValue());
}
else if(message.getUrl() != null) {
return message.getUrl();
}
else {
return String.valueOf(message.getActionId());
}
}
protected int getNotificationId(NotificationMessage message) {
if(message.getEntityId() != null) {
return message.getEntityId().intValue();
}
return 0;
}
protected JSONObject newJSONObject(String json) throws JSONException {
return new JSONObject(json);
}
protected int getNotificationIcon(Context context) {
int icon = notificationIcon;
if(config.getBooleanProperty(SocializeConfig.SOCIALIZE_NOTIFICATION_APP_ICON, true)) {
icon = appUtils.getAppIconId(context);
if(icon <= 0) {
if(logger != null && logger.isDebugEnabled()) {
logger.debug("Could not locate ID for application icon. Using default icon for notification");
icon = notificationIcon;
}
}
}
return icon;
}
protected void handleError(String msg) {
if(logger != null) {
logger.error(msg);
}
else {
System.err.println(msg);
}
}
protected void handleError(String msg, Exception e) {
if(logger != null) {
logger.error(msg, e);
}
else {
SocializeLogger.e(msg, e);
}
}
public void setLogger(SocializeLogger logger) {
this.logger = logger;
}
public void setConfig(SocializeConfig config) {
this.config = config;
}
public void setAppUtils(AppUtils appUtils) {
this.appUtils = appUtils;
}
public int getNotificationIcon() {
return notificationIcon;
}
public void setNotificationIcon(int notificationIcon) {
this.notificationIcon = notificationIcon;
}
public void setMessageFactories(Map<String, JSONFactory<NotificationMessage>> messageFactories) {
this.messageFactories = messageFactories;
}
public void setMessageBuilders(Map<String, NotificationMessageBuilder> messageBuilders) {
this.messageBuilders = messageBuilders;
}
public void setNotificationRegistrationState(NotificationRegistrationState notificationRegistrationState) {
this.notificationRegistrationState = notificationRegistrationState;
}
public void setNotificationRegistrationSystem(NotificationRegistrationSystem notificationRegistrationSystem) {
this.notificationRegistrationSystem = notificationRegistrationSystem;
}
public void setUserSystem(UserSystem userSystem) {
this.userSystem = userSystem;
}
public void setNotificationManagerFacade(NotificationManagerFacade notificationManagerFacade) {
this.notificationManagerFacade = notificationManagerFacade;
}
}