package org.bbssh.notifications;
import java.util.Enumeration;
import net.rim.blackberry.api.homescreen.HomeScreen;
import net.rim.device.api.notification.NotificationsManager;
import net.rim.device.api.system.Alert;
import org.bbssh.model.ConnectionProperties;
import org.bbssh.model.SettingsManager;
import org.bbssh.session.RemoteSessionInstance;
import org.bbssh.session.SessionManager;
import org.bbssh.util.Tools;
import org.bbssh.util.Version;
/**
* Across versions, BBSSH supports many different notification indicators:
* <ul>
* <ul>
* <li>HSI connected + new (6.0) / connected_splat (<) if 1+ connections exist and 1+ sessions are notified.</li>
* <li>HSI disconnected + new (6.0) / disconnected_splat (<) if 0 connections exist and 1+ sessions are notified.</li>
* <li>HSI connected if at least one connection exists and none are notified.</li>
* <li>HSI disconnected if no n otifications exist and no connections exists.</li>
* </ul>
* </li> <li>Home screen: session shortcut icon state (6.0)</li>
* <ul>
* <li>Session Shortcut icon (SSI) is set to connected when session is connected</li>
* <li>SSI is set to connected + new when a connection exists and the session is in a notified state.</li>
* <li>SSI is set to default + new when a connection exists and the session is in a notified state.</li>
* <li>SSI is set to connected when a connection exists and the session is not in a notified state.</li>
* <li>SSI is set to disconnected when no connection exists and the session is not in a notified state.</li>
* </ul>
* </li> <li>Home screen: statusbar notification icon and count(4.6)
* <ul>
* <li>Icon is enabled when any session is in the notified state</li>
* <li>Icon count is the total number of session in the notified state.</li>
* <li>Icon is disabled when the number of sessions in the notified state is zero.</li>
* </ul>
* </li> <li>Home screen: statusbar notification icon new state (6.0)
* <ul>
* <li>State is new when message received while app does not have focus or is foreground but asleep.</li>
* <li>New state is cleared</li> when the app receives focus.</li> </ul> </li> <li>Message list: n/a</li> <li>Message
* list: statusbar integration: n/a</li> <li>Vibrate (ONLY if preference is on, and bell occurs in ACTIVE session)</li>
* <li>Profile-based notification(all).</li> <li>Main screen: set alert indicator(all)</li> <li>Main screen: set error
* indicator(all)</li> <li>Home screen: main app icon state (HSI)</li> </ul> This class (overridden appropriately or
* platform versions) manages of the state of these various notification behaviors
*/
public class NotificationManager {
private static NotificationManager me = null;
public synchronized static NotificationManager inst() {
if (me == null) {
String name = NotificationManager.class.getName();
me = (NotificationManager) Version.createOSObjectInstance(name);
}
return me;
}
public NotificationManager() {
}
/**
* Provides an icon filename usable for either the main app icon; or a shortcut icon. For OS 5 and earlie, the icon
* will reflect the notified and connected state; for 6.0+ it iwill reflect only the connected state; and the
* application must invoke the appropriate Homescreen method to toggle the notified state.
*
* @param connected
* for all versions this will provide a different icon based on its value.
* @param notified
* for 5.0 and earlier this will ensure that the icon reflects a notified state by using a "splat"
* indicator similar to the one BlackBerry uses on its messages app.
* @return bitmap icon meeting the required
*/
protected String getHomeScreenIconName(boolean connected, boolean notified) {
StringBuffer buf = new StringBuffer(32);
buf.append("shortcut");
if (connected)
buf.append("-connected");
if (notified)
buf.append("_splat");
buf.append(".png");
return buf.toString();
}
/**
* Resets the notified state of the overall application; and clears the new indicator from the current icon.
*/
public final synchronized void resetNotificationState() {
NotificationsManager.cancelImmediateEvent(Tools.NOTIFICATION_GUID, 1, null, null);
}
public synchronized void resetNotificationState(ConnectionProperties prop) {
}
public final synchronized void terminateAllNotifications() {
resetNotificationState();
resetHomeScreenIcons();
updateHomeScreenNotifications(0, false);
}
protected void resetHomeScreenIcons() {
HomeScreen.updateIcon(Tools.loadBitmap(getHomeScreenIconName(false, false)));
}
/**
* Refreshes all notification indicators based on application and terminal focus; and where possible updates
* notification indicators for the provided session.
*
* @param notificationOccurred
* @param rsi
*/
public final synchronized void updateNotificationIndicators(boolean notificationOccurred, RemoteSessionInstance rsi) {
// @todo we will need to detemrine how to do notification count
// differently once we implememnt message folders
int count = 0;
SessionManager mgr = SessionManager.getInstance();
// Active notifications first - porfile and terminal vibration.
if (notificationOccurred) {
if (SettingsManager.getSettings().isVibrateOnAlertEnabled()) {
if (mgr.isTerminalActive() && rsi == mgr.activeSession) {
// @todo alert options: vibrate, tone, none.
Alert.startVibrate(150);
}
}
// We're going to base this behavior on the BB messages app.
// BB messages will ALWAYS display this notification even if you're
// already in the app message list or reading an email. OUr
// difference in behavior will be only if you are actively in the
// session itself - then tehre's no reason to show the notification,
// as you've already got the vibrate and are looking at the screen.
if (!mgr.isTerminalActive() || rsi != mgr.activeSession) {
// The other thing the messenger app will do is NOT display a
// new notification
// if a notification has already occurred for the app.
if ((rsi != null && !rsi.state.suppressNotify)
&& NotificationsManager.isImmediateEventOccuring(Tools.NOTIFICATION_GUID)) {
NotificationsManager.triggerImmediateEvent(Tools.NOTIFICATION_GUID, 1, null, null);
}
}
}
// Now - update application and shortcut icons; and update the notification
// icon counters, visibility, an state.
Enumeration sessions = mgr.getAvailableSessions();
RemoteSessionInstance r;
boolean connected = false;
while (sessions.hasMoreElements()) {
r = (RemoteSessionInstance) sessions.nextElement();
connected = connected || r.isConnected();
if (r.state.notified) {
count++;
}
}
if (rsi != null) {
// a forced disconnect - don't send a notification that the user can't
// ever see (because the session is gone).
if (rsi.state.suppressNotify) {
notificationOccurred = false;
}
updateShortcutIcon(rsi.session.getProperties().getUIDAsString(), rsi.isConnected(), notificationOccurred);
}
updateMainIcon(connected, notificationOccurred);
updateHomeScreenNotifications(count, notificationOccurred);
}
/**
* Derived versions will perform updates to appearance and state of the shortcut icons on the home screen (6.0+)
*
* @param shortcutId
* @param newIcon
* @param notificationOccurred
*/
protected void updateShortcutIcon(String shortcutId, boolean connected, boolean notificationOccurred) {
}
/**
* Set the main application icon state to indicate whether or not a notification icon occurred.
*
* @param connected
* true if icon should reflect a connected state.
* @param notificationOccurred
* true if icon should be in "new" state.
*/
protected void updateMainIcon(boolean connected, boolean notificationOccurred) {
HomeScreen.updateIcon(Tools.loadBitmap(getHomeScreenIconName(connected, notificationOccurred)));
}
/**
* Updates the displayed number of notifications on the home screen, for versions which support it. This is
* available in 4.6, and so the base version has no implementation.
*
* @param newNotification
* true if a new notification has occurred.
*/
protected void updateHomeScreenNotifications(int count, boolean newNotification) {
}
}