/*
* Copyright 2012 The Stanford MobiSocial Laboratory
*
* 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 mobisocial.musubi.obj.handler;
import mobisocial.musubi.App;
import mobisocial.musubi.feed.iface.DbEntryHandler;
import mobisocial.musubi.feed.iface.FeedRenderer;
import mobisocial.musubi.model.MIdentity;
import mobisocial.musubi.model.PresenceAwareNotify;
import mobisocial.musubi.model.helpers.FeedManager;
import mobisocial.musubi.model.helpers.IdentitiesManager;
import mobisocial.musubi.obj.ObjHelpers;
import mobisocial.musubi.objects.PictureObj;
import mobisocial.musubi.objects.StatusObj;
import mobisocial.musubi.objects.VoiceObj;
import mobisocial.socialkit.musubi.DbObj;
import mobisocial.socialkit.musubi.Musubi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
/**
* Handles notifications associated with a received obj.
* First, we check with the sender application to allow it to handle this data.
* If the application does not indicate that we should not notify the user,
* we check to see if the obj should be auto activated (for example, in tv mode).
* Finally, we send a standard notification.
*
* An application prevents a notification event by setting the result data
* to RESULT_CANCELLED (setResultCode(Activity.RESULT_CANCELLED)).
*
*/
public class NotificationHandler {
String TAG = "NotificationObjHandler";
private static final int NO_NOTIFY = 0;
private static final int NOTIFY = 1;
private static final int AUTO_ACTIVATE = 2;
private static final String ACTION_DATA_RECEIVED = "mobisocial.intent.action.DATA_RECEIVED";
private static final String EXTRA_NOTIFICATION = "notification";
private static final String EXTRA_OBJ_URI = "objUri";
private final AutoActivateObjHandler mAutoActivate = new AutoActivateObjHandler();
final Context mContext;
private Musubi mMusubi;
private IdentitiesManager mIdentitiesManager;
public NotificationHandler(Context context) {
mContext = context;
mMusubi = App.getMusubi(context);
SQLiteOpenHelper helper = App.getDatabaseSource(mContext);
mIdentitiesManager = new IdentitiesManager(helper);
}
BroadcastReceiver mAppHandler = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() != Activity.RESULT_OK) {
return;
}
int notification = intent.getExtras().getInt(EXTRA_NOTIFICATION);
Uri objUri = intent.getExtras().getParcelable(EXTRA_OBJ_URI);
DbObj obj = mMusubi.objForUri(objUri);
//this deals with non-isolated namespaces in the testing framework. :(
if (obj == null)
return;
//don't notify if the sender is not whitelisted
MIdentity sender = mIdentitiesManager.getIdentityForId(obj.getSenderId());
if(sender == null) {
Log.w(TAG, "obj has no longer valid sending identity? " + obj.getSenderId());
return;
}
if (!sender.whitelisted_) {
return;
}
if (notification == AUTO_ACTIVATE) {
// Auto-activate without notification.
DbEntryHandler handler = ObjHelpers.forType(obj.getType());
mAutoActivate.afterDbInsertion(context, handler, obj);
} else if (notification == NOTIFY) {
if (obj.getContainingFeed() != null) {
Uri feedUri = obj.getContainingFeed().getUri();
Intent launch = FeedManager.getViewingIntent(context, feedUri);
String msgText = null;
String defaultText = "New Musubi message";
String name = obj.getSender().getName();
String type = obj.getType();
if (StatusObj.TYPE.equals(type)) {
try {
msgText = obj.getJson().getString(StatusObj.TEXT);
if (name != null) {
msgText = name + ": " + msgText;
}
} catch (Exception e) {
}
} else if (PictureObj.TYPE.equals(type)) {
msgText = "New picture from " + name;
} else if (VoiceObj.TYPE.equals(type)) {
msgText = "New voice message from " + name;
}
if (msgText == null) {
msgText = defaultText + " from " + name;
}
if (Build.VERSION.SDK_INT < 11) {
launch.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TOP);
} else {
launch.setFlags (Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
}
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
launch, PendingIntent.FLAG_CANCEL_CURRENT);
(new PresenceAwareNotify(context)).notify("New Musubi message",
msgText, contentIntent, feedUri);
} else {
Log.e(TAG, "No containing feed found for " + obj.toString());
}
}
}
};
public void handle(DbEntryHandler handler, boolean fromOwnedIdentity, DbObj obj) {
int notification = NOTIFY;
if (fromOwnedIdentity) {
notification = NO_NOTIFY;
}
if (handler == null || !(handler instanceof FeedRenderer)) {
notification = NO_NOTIFY;
}
if (mAutoActivate.willActivate(mContext, obj)) {
notification = AUTO_ACTIVATE;
}
if (!handler.doNotification(mContext, obj)) {
notification = NO_NOTIFY;
}
// Let applications handle their own messages
Intent objReceived = new Intent(ACTION_DATA_RECEIVED);
objReceived.setPackage(obj.getAppId());
objReceived.putExtra(EXTRA_NOTIFICATION, notification);
objReceived.putExtra(EXTRA_OBJ_URI, obj.getUri());
Bundle initialExtras = null;
int initialCode = Activity.RESULT_OK;
String initialData = null;
Handler scheduler = null;
String receiverPermission = null;
mContext.sendOrderedBroadcast(objReceived, receiverPermission, mAppHandler, scheduler,
initialCode, initialData, initialExtras);
}
}