Improve notification by using NotificationCompat.Builder
authorDa Risk <da_risk@beem-project.com>
Fri, 10 Aug 2012 05:38:39 +0200
changeset 984 46b16746d8a2
parent 983 e818646525da
child 985 2a2d82478538
Improve notification by using NotificationCompat.Builder
src/com/beem/project/beem/BeemService.java
src/com/beem/project/beem/service/BeemChatManager.java
src/com/beem/project/beem/service/ChatAdapter.java
src/com/beem/project/beem/service/XmppConnectionAdapter.java
src/com/beem/project/beem/service/aidl/IChat.aidl
--- a/src/com/beem/project/beem/BeemService.java	Tue Jul 24 18:30:07 2012 +0200
+++ b/src/com/beem/project/beem/BeemService.java	Fri Aug 10 05:38:39 2012 +0200
@@ -223,8 +223,8 @@
 	    if (!"".equals(tmpPort))
 		mPort = Integer.parseInt(tmpPort);
 	}
-	if (mSettings.getBoolean(BeemApplication.FULL_JID_LOGIN_KEY, false) ||
-	    "gmail.com".equals(mService) || "googlemail.com".equals(mService))  {
+	if (mSettings.getBoolean(BeemApplication.FULL_JID_LOGIN_KEY, false)
+		|| "gmail.com".equals(mService) || "googlemail.com".equals(mService))  {
 	    mLogin = tmpJid;
 	}
 
@@ -291,8 +291,9 @@
 	notif.ledARGB = 0xff0000ff; // Blue color
 	notif.ledOnMS = 1000;
 	notif.ledOffMS = 1000;
-	notif.defaults |= Notification.DEFAULT_LIGHTS;
-	String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY, Settings.System.DEFAULT_NOTIFICATION_URI.toString());
+	notif.flags |= Notification.FLAG_SHOW_LIGHTS;
+	String ringtoneStr = mSettings.getString(BeemApplication.NOTIFICATION_SOUND_KEY,
+		Settings.System.DEFAULT_NOTIFICATION_URI.toString());
 	notif.sound = Uri.parse(ringtoneStr);
 	mNotificationManager.notify(id, notif);
     }
--- a/src/com/beem/project/beem/service/BeemChatManager.java	Tue Jul 24 18:30:07 2012 +0200
+++ b/src/com/beem/project/beem/service/BeemChatManager.java	Fri Aug 10 05:38:39 2012 +0200
@@ -44,12 +44,37 @@
 package com.beem.project.beem.service;
 
 import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.os.Environment;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.preference.PreferenceManager;
+import android.support.v4.app.NotificationCompat;
+import android.util.Log;
+
+import com.beem.project.beem.BeemApplication;
+import com.beem.project.beem.BeemService;
+import com.beem.project.beem.R;
+import com.beem.project.beem.providers.AvatarProvider;
+import com.beem.project.beem.service.aidl.IChat;
+import com.beem.project.beem.service.aidl.IChatManager;
+import com.beem.project.beem.service.aidl.IChatManagerListener;
+import com.beem.project.beem.service.aidl.IMessageListener;
+import com.beem.project.beem.service.aidl.IRoster;
+import com.beem.project.beem.utils.Status;
+
 import net.java.otr4j.OtrException;
 
 import org.jivesoftware.smack.Chat;
@@ -60,25 +85,6 @@
 import org.jivesoftware.smack.packet.Presence;
 import org.jivesoftware.smack.util.StringUtils;
 
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Environment;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import com.beem.project.beem.BeemApplication;
-import com.beem.project.beem.BeemService;
-import com.beem.project.beem.service.aidl.IChat;
-import com.beem.project.beem.service.aidl.IChatManager;
-import com.beem.project.beem.service.aidl.IChatManagerListener;
-import com.beem.project.beem.service.aidl.IMessageListener;
-import com.beem.project.beem.service.aidl.IRoster;
-import com.beem.project.beem.utils.Status;
-
 /**
  * An adapter for smack's ChatManager. This class provides functionnality to handle chats.
  * @author darisk
@@ -92,6 +98,7 @@
     private final RemoteCallbackList<IChatManagerListener> mRemoteChatCreationListeners =
 	new RemoteCallbackList<IChatManagerListener>();
     private final BeemService mService;
+    private final Roster mRoster;
     private final ChatRosterListener mChatRosterListn = new ChatRosterListener();
 
     /**
@@ -103,7 +110,8 @@
     public BeemChatManager(final ChatManager chatManager, final BeemService service, final Roster roster) {
 	mService = service;
 	mAdaptee = chatManager;
-	roster.addRosterListener(mChatRosterListn);
+	mRoster = roster;
+	mRoster.addRosterListener(mChatRosterListn);
 	mAdaptee.addChatListener(mChatListener);
     }
 
@@ -212,11 +220,10 @@
      */
     public List<Contact> getOpenedChatList() throws RemoteException {
 	List<Contact> openedChats = new ArrayList<Contact>();
-	IRoster mRoster = mService.getBind().getRoster();
-
+	IRoster r = mService.getBind().getRoster();
 	for (ChatAdapter chat : mChats.values()) {
 	    if (chat.getMessages().size() > 0) {
-		Contact t = mRoster.getContact(chat.getParticipant().getJID());
+		Contact t = r.getContact(chat.getParticipant().getJID());
 		if (t == null)
 		    t = new Contact(chat.getParticipant().getJID());
 		openedChats.add(t);
@@ -294,21 +301,48 @@
 	 * @param msgBody the body of the new message
 	 */
 	private void notifyNewChat(IChat chat, String msgBody) {
-	    SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mService);
+	    NotificationCompat.Builder notif = new NotificationCompat.Builder(mService);
 	    try {
-		CharSequence tickerText = mService.getBind().getRoster().getContact(chat.getParticipant().getJID())
-		    .getName();
-		Notification notification = new Notification(android.R.drawable.stat_notify_chat, tickerText, System
-		    .currentTimeMillis());
-		notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
-		notification.setLatestEventInfo(mService, tickerText, msgBody, makeChatIntent(chat));
-		mService.sendNotification(chat.getParticipant().getJID().hashCode(), notification);
+		String contactJid = chat.getParticipant().getJID();
+		Contact c = mService.getBind().getRoster().getContact(contactJid);
+		String contactName = contactJid;
+		if (c != null) {
+		    contactName = c.getName();
+		    Bitmap avatar = getAvatar(c);
+		    notif.setLargeIcon(avatar);
+		}
+		notif.setTicker(contactName).setContentTitle(contactName);
+		notif.setContentText(msgBody);
+		notif.setSmallIcon(R.drawable.beem_status_icon_gray);
+		notif.setNumber(chat.getUnreadMessageCount());
+		notif.setContentIntent(makeChatIntent(chat));
+		notif.setAutoCancel(true).setWhen(System.currentTimeMillis());
+		mService.sendNotification(chat.getParticipant().getJID().hashCode(), notif.getNotification());
 	    } catch (RemoteException e) {
 		Log.e(TAG, e.getMessage());
 	    }
 	}
 
 	/**
+	 * Get the avatar of a contact.
+	 * @param c the contact
+	 * @return the avatar of c or null if avatar is not defined
+	 */
+	private Bitmap getAvatar(Contact c) {
+	    String id = c.getAvatarId();
+	    if (id == null)
+		id = "";
+	    Uri uri = AvatarProvider.CONTENT_URI.buildUpon().appendPath(id).build();
+	    try {
+		InputStream in = mService.getContentResolver().openInputStream(uri);
+		return BitmapFactory.decodeStream(in);
+	    } catch (FileNotFoundException e) {
+		Log.d(TAG, "Error loading avatar id: " + id, e);
+		return null;
+	    }
+	}
+
+	/**
 	 * {@inheritDoc}
 	 */
 	@Override
--- a/src/com/beem/project/beem/service/ChatAdapter.java	Tue Jul 24 18:30:07 2012 +0200
+++ b/src/com/beem/project/beem/service/ChatAdapter.java	Fri Aug 10 05:38:39 2012 +0200
@@ -50,6 +50,15 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import android.os.Environment;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.beem.project.beem.otr.BeemOtrManager;
+import com.beem.project.beem.service.aidl.IChat;
+import com.beem.project.beem.service.aidl.IMessageListener;
+
 import net.java.otr4j.OtrException;
 import net.java.otr4j.session.SessionID;
 
@@ -59,15 +68,6 @@
 import org.jivesoftware.smackx.ChatState;
 import org.jivesoftware.smackx.ChatStateListener;
 
-import android.os.Environment;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.beem.project.beem.otr.BeemOtrManager;
-import com.beem.project.beem.service.aidl.IChat;
-import com.beem.project.beem.service.aidl.IMessageListener;
-
 /**
  * An adapter for smack's Chat class.
  * @author darisk
@@ -88,6 +88,7 @@
     private boolean mIsHistory;
     private File mHistoryPath;
     private String mAccountUser;
+    private int mUnreadMsgCount;
 
     /**
      * Constructor.
@@ -204,6 +205,8 @@
     @Override
     public void setOpen(boolean isOpen) {
 	this.mIsOpen = isOpen;
+	if (isOpen)
+		mUnreadMsgCount = 0;
     }
 
     /**
@@ -230,6 +233,8 @@
 	if (mMessages.size() == HISTORY_MAX_SIZE)
 	    mMessages.remove(0);
 	mMessages.add(msg);
+	if (!isOpen())
+	    mUnreadMsgCount++;
 	if (!"".equals(msg.getBody()) && msg.getBody() != null) {
 	    logMessage(msg);
 	}
@@ -327,7 +332,8 @@
 
 	if (mOtrSessionId != null && unencrypted != null && unencrypted.getBody() != null) {
 	    try {
-		String body = BeemOtrManager.getInstance().getOtrManager().transformSending(mOtrSessionId, unencrypted.getBody());
+		String body = BeemOtrManager.getInstance().getOtrManager()
+		    .transformSending(mOtrSessionId, unencrypted.getBody());
 		Message result = new Message(unencrypted.getTo(), unencrypted.getType());
 		result.setBody(body);
 		return result;
@@ -339,67 +345,6 @@
     }
 
     /**
-     * Listener.
-     */
-    private class MsgListener implements ChatStateListener {
-	/**
-	 * Constructor.
-	 */
-	public MsgListener() {
-	}
-
-	@Override
-	public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
-	    Message msg = new Message(message);
-	    Log.d(TAG, "new msg " + msg.getBody());
-	    String body;
-
-	    if (mOtrSessionId != null) {
-		try {
-		    body = BeemOtrManager.getInstance().getOtrManager()
-			.transformReceiving(mOtrSessionId, msg.getBody());
-		    msg.setBody(body);
-		} catch (OtrException e) {
-		    Log.w(TAG, "Unable to decrypt OTR message", e);
-		}
-	    }
-	    //TODO add que les message pas de type errors
-	    ChatAdapter.this.addMessage(msg);
-	    final int n = mRemoteListeners.beginBroadcast();
-	    for (int i = 0; i < n; i++) {
-		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
-		try {
-		    if (listener != null)
-			listener.processMessage(ChatAdapter.this, msg);
-		} catch (RemoteException e) {
-		    Log.w(TAG, "Error while diffusing message to listener", e);
-		}
-	    }
-	    mRemoteListeners.finishBroadcast();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public void stateChanged(Chat chat, ChatState state) {
-	    mState = state.name();
-	    final int n = mRemoteListeners.beginBroadcast();
-
-	    for (int i = 0; i < n; i++) {
-		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
-		try {
-		    listener.stateChanged(ChatAdapter.this);
-		} catch (RemoteException e) {
-		    Log.w(TAG, e.getMessage());
-		}
-	    }
-	    mRemoteListeners.finishBroadcast();
-	}
-
-    }
-
-    /**
      * This method is executed when the otr session status change.
      * @param otrState the new state of otr session.
      */
@@ -462,6 +407,9 @@
 	return true;
     }
 
+    /**
+     * Start listenning to an OTR session.
+     */
     public void listenOtrSession() {
 	if (mOtrSessionId != null)
 	    return;
@@ -504,4 +452,71 @@
 	    return null;
 	return BeemOtrManager.getInstance().getOtrManager().getSessionStatus(mOtrSessionId).toString();
     }
+
+    @Override
+    public int getUnreadMessageCount() throws RemoteException {
+	return mUnreadMsgCount;
+    }
+
+    /**
+     * Listener.
+     */
+    private class MsgListener implements ChatStateListener {
+	/**
+	 * Constructor.
+	 */
+	public MsgListener() {
+	}
+
+	@Override
+	public void processMessage(Chat chat, org.jivesoftware.smack.packet.Message message) {
+	    Message msg = new Message(message);
+	    Log.d(TAG, "new msg " + msg.getBody());
+	    String body;
+
+	    if (mOtrSessionId != null) {
+		try {
+		    body = BeemOtrManager.getInstance().getOtrManager()
+			.transformReceiving(mOtrSessionId, msg.getBody());
+		    msg.setBody(body);
+		} catch (OtrException e) {
+		    Log.w(TAG, "Unable to decrypt OTR message", e);
+		}
+	    }
+	    //TODO add que les message pas de type errors
+	    ChatAdapter.this.addMessage(msg);
+	    final int n = mRemoteListeners.beginBroadcast();
+	    for (int i = 0; i < n; i++) {
+		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
+		try {
+		    if (listener != null)
+			listener.processMessage(ChatAdapter.this, msg);
+		} catch (RemoteException e) {
+		    Log.w(TAG, "Error while diffusing message to listener", e);
+		}
+	    }
+	    mRemoteListeners.finishBroadcast();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void stateChanged(Chat chat, ChatState state) {
+	    mState = state.name();
+	    final int n = mRemoteListeners.beginBroadcast();
+
+	    for (int i = 0; i < n; i++) {
+		IMessageListener listener = mRemoteListeners.getBroadcastItem(i);
+		try {
+		    listener.stateChanged(ChatAdapter.this);
+		} catch (RemoteException e) {
+		    Log.w(TAG, e.getMessage());
+		}
+	    }
+	    mRemoteListeners.finishBroadcast();
+	}
+
+    }
+
 }
--- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Tue Jul 24 18:30:07 2012 +0200
+++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Fri Aug 10 05:38:39 2012 +0200
@@ -53,6 +53,7 @@
 import android.content.SharedPreferences;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.support.v4.app.NotificationCompat;
 import android.util.Log;
 
 import com.beem.project.beem.BeemApplication;
@@ -119,7 +120,8 @@
     private BeemAvatarManager mAvatarManager;
     private PepSubManager mPepManager;
     private SharedPreferences mPref;
-    private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners = new RemoteCallbackList<IBeemConnectionListener>();
+    private final RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners =
+	new RemoteCallbackList<IBeemConnectionListener>();
     private final SubscribePacketListener mSubscribePacketListener = new SubscribePacketListener();
     private final PingListener mPingListener = new PingListener();
 
@@ -665,25 +667,7 @@
 		}
 	    };
 
-	    mAdaptee.addPacketListener(new PacketListener() {
-
-		@Override
-		public void processPacket(Packet packet) {
-		    String from = packet.getFrom();
-		    Notification notif = new Notification(android.R.drawable.stat_notify_more, mService.getString(
-			R.string.AcceptContactRequest, from), System.currentTimeMillis());
-		    notif.flags = Notification.FLAG_AUTO_CANCEL;
-		    Intent intent = new Intent(mService, Subscription.class);
-		    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).putExtra("from", from);
-		    notif.setLatestEventInfo(mService, from,
-			mService.getString(R.string.AcceptContactRequestFrom, from),
-			PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT));
-		    int id = packet.hashCode();
-		    mService.sendNotification(id, notif);
-		    Presence p = (Presence) packet;
-		    updateNotification(Status.getStatusFromPresence(p), p.getStatus());
-		}
-	    }, filter);
+	    mAdaptee.addPacketListener(mSubscribePacketListener, filter);
 
 	    final int n = mRemoteConnListeners.beginBroadcast();
 
@@ -716,22 +700,24 @@
 
 	@Override
 	public void processPacket(Packet packet) {
-	    if (!(packet instanceof Presence))
-		return;
-	    Presence p = (Presence) packet;
-	    if (p.getType() != Presence.Type.subscribe)
-		return;
-	    String from = p.getFrom();
-	    Notification notification = new Notification(android.R.drawable.stat_notify_more, mService.getString(
-		R.string.AcceptContactRequest, from), System.currentTimeMillis());
-	    notification.flags = Notification.FLAG_AUTO_CANCEL;
+	    String from = packet.getFrom();
+
+	    NotificationCompat.Builder notif = new NotificationCompat.Builder(mService);
+	    String title = mService.getString(R.string.AcceptContactRequest, from);
+	    String text = mService.getString(R.string.AcceptContactRequestFrom, from);
+	    notif.setTicker(title).setContentTitle(title);
+	    notif.setContentText(text);
+	    notif.setSmallIcon(R.drawable.beem_status_icon_gray);
+	    notif.setAutoCancel(true).setWhen(System.currentTimeMillis());
+
 	    Intent intent = new Intent(mService, Subscription.class);
 	    intent.setData(Contact.makeXmppUri(from));
-	    notification.setLatestEventInfo(mService, from,
-		mService.getString(R.string.AcceptContactRequestFrom, from),
-		PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT));
-	    int id = p.hashCode();
-	    mService.sendNotification(id, notification);
+	    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+	    PendingIntent notifIntent = PendingIntent.getActivity(mService, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+	    notif.setContentIntent(notifIntent);
+
+	    int id = packet.hashCode();
+	    mService.sendNotification(id, notif.getNotification());
 	}
     }
 
--- a/src/com/beem/project/beem/service/aidl/IChat.aidl	Tue Jul 24 18:30:07 2012 +0200
+++ b/src/com/beem/project/beem/service/aidl/IChat.aidl	Fri Aug 10 05:38:39 2012 +0200
@@ -82,38 +82,40 @@
 
 	boolean isOpen();
 
+	int getUnreadMessageCount();
+
 	void setState(in String state);
 
 	List<Message> getMessages();
-	
+
 	/**
 	 * Try to start an OTR session.
 	 */
 	void startOtrSession();
-	
+
 	/**
 	 * Stop the OTR session.
 	 */
 	void endOtrSession();
-	
+
 	/**
 	 * get local OTR key fingerprints.
 	 */
 	String getLocalOtrFingerprint();
-	
-	
+
+
 	/**
 	 * get remote OTR key fingerprints.
 	 */
 	String getRemoteOtrFingerprint();
-	
+
 	void verifyRemoteFingerprint(in boolean ok);
-	
-	
+
+
 	/**
 	 * get current OTR status.
 	 */
 	String getOtrStatus();
-	
+
 
 }