package org.yaxim.androidclient.service;
import java.util.HashMap;
import java.util.Map;
import org.yaxim.androidclient.chat.ChatWindow;
import org.yaxim.androidclient.data.YaximConfiguration;
import org.yaxim.androidclient.util.LogConstants;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
import org.yaxim.androidclient.R;
public abstract class GenericService extends Service {
private static final String TAG = "yaxim.Service";
private static final String APP_NAME = "yaxim";
private static final int MAX_TICKER_MSG_LEN = 50;
private NotificationManager mNotificationMGR;
private Notification mNotification;
private Vibrator mVibrator;
private Intent mNotificationIntent;
protected WakeLock mWakeLock;
//private int mNotificationCounter = 0;
private Map<String, Integer> notificationCount = new HashMap<String, Integer>(2);
private Map<String, Integer> notificationId = new HashMap<String, Integer>(2);
protected static int SERVICE_NOTIFICATION = 1;
private int lastNotificationId = 2;
protected YaximConfiguration mConfig;
@Override
public IBinder onBind(Intent arg0) {
Log.i(TAG, "called onBind()");
return null;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "called onUnbind()");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.i(TAG, "called onRebind()");
super.onRebind(intent);
}
@Override
public void onCreate() {
Log.i(TAG, "called onCreate()");
super.onCreate();
mConfig = org.yaxim.androidclient.YaximApplication.getConfig(this);
mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mWakeLock = ((PowerManager)getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, APP_NAME);
addNotificationMGR();
}
@Override
public void onDestroy() {
Log.i(TAG, "called onDestroy()");
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "called onStartCommand()");
return START_STICKY;
}
private void addNotificationMGR() {
mNotificationMGR = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationIntent = new Intent(this, ChatWindow.class);
}
protected void notifyClient(String fromJid, String fromUserName, String message,
boolean showNotification, boolean silent_notification, boolean is_error) {
if (!showNotification) {
if (is_error)
shortToastNotify(getString(R.string.notification_error) + " " + message);
// only play sound and return
try {
if (!silent_notification && !Uri.EMPTY.equals(mConfig.notifySound))
RingtoneManager.getRingtone(getApplicationContext(), mConfig.notifySound).play();
} catch (NullPointerException e) {
// ignore NPE when ringtone was not found
}
return;
}
mWakeLock.acquire();
// Override silence when notification is created initially
// if there is no open notification for that JID, and we get a "silent"
// one (i.e. caused by an incoming carbon message), we still ring/vibrate,
// but only once. As long as the user ignores the notifications, no more
// sounds are made. When the user opens the chat window, the counter is
// reset and a new sound can be made.
if (silent_notification && !notificationCount.containsKey(fromJid)) {
silent_notification = false;
}
setNotification(fromJid, fromUserName, message, is_error);
setLEDNotification();
if (!silent_notification)
mNotification.sound = mConfig.notifySound;
int notifyId = 0;
if (notificationId.containsKey(fromJid)) {
notifyId = notificationId.get(fromJid);
} else {
lastNotificationId++;
notifyId = lastNotificationId;
notificationId.put(fromJid, Integer.valueOf(notifyId));
}
// If vibration is set to "system default", add the vibration flag to the
// notification and let the system decide.
if(!silent_notification && "SYSTEM".equals(mConfig.vibraNotify)) {
mNotification.defaults |= Notification.DEFAULT_VIBRATE;
}
mNotificationMGR.notify(notifyId, mNotification);
// If vibration is forced, vibrate now.
if(!silent_notification && "ALWAYS".equals(mConfig.vibraNotify)) {
mVibrator.vibrate(400);
}
mWakeLock.release();
}
private void setNotification(String fromJid, String fromUserId, String message, boolean is_error) {
int mNotificationCounter = 0;
if (notificationCount.containsKey(fromJid)) {
mNotificationCounter = notificationCount.get(fromJid);
}
mNotificationCounter++;
notificationCount.put(fromJid, mNotificationCounter);
String author;
if (null == fromUserId || fromUserId.length() == 0) {
author = fromJid;
} else {
author = fromUserId;
}
String title = getString(R.string.notification_message, author);
String ticker;
if (is_error) {
title = getString(R.string.notification_error);
ticker = title;
message = author + ": " + message;
} else
if (mConfig.ticker) {
int newline = message.indexOf('\n');
int limit = 0;
String messageSummary = message;
if (newline >= 0)
limit = newline;
if (limit > MAX_TICKER_MSG_LEN || message.length() > MAX_TICKER_MSG_LEN)
limit = MAX_TICKER_MSG_LEN;
if (limit > 0)
messageSummary = message.substring(0, limit) + " [...]";
ticker = title + ":\n" + messageSummary;
} else
ticker = getString(R.string.notification_anonymous_message);
mNotification = new Notification(R.drawable.sb_message, ticker,
System.currentTimeMillis());
mNotification.defaults = 0;
Uri userNameUri = Uri.parse(fromJid);
mNotificationIntent.setData(userNameUri);
mNotificationIntent.putExtra(ChatWindow.INTENT_EXTRA_USERNAME, fromUserId);
mNotificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//need to set flag FLAG_UPDATE_CURRENT to get extras transferred
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
mNotificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mNotification.setLatestEventInfo(this, title, message, pendingIntent);
if (mNotificationCounter > 1)
mNotification.number = mNotificationCounter;
mNotification.flags = Notification.FLAG_AUTO_CANCEL;
}
private void setLEDNotification() {
if (mConfig.isLEDNotify) {
mNotification.ledARGB = Color.MAGENTA;
mNotification.ledOnMS = 300;
mNotification.ledOffMS = 1000;
mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
}
}
protected void shortToastNotify(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.show();
}
protected void shortToastNotify(Throwable e) {
e.printStackTrace();
while (e.getCause() != null)
e = e.getCause();
shortToastNotify(e.getMessage());
}
public void resetNotificationCounter(String userJid) {
notificationCount.remove(userJid);
}
protected void logError(String data) {
if (LogConstants.LOG_ERROR) {
Log.e(TAG, data);
}
}
protected void logInfo(String data) {
if (LogConstants.LOG_INFO) {
Log.i(TAG, data);
}
}
public void clearNotification(String Jid) {
int notifyId = 0;
if (notificationId.containsKey(Jid)) {
notifyId = notificationId.get(Jid);
mNotificationMGR.cancel(notifyId);
}
}
}