2012-07-18 15:35:13 -07:00
|
|
|
/**
|
2011-12-20 10:20:44 -08:00
|
|
|
* Copyright (C) 2011 Whisper Systems
|
2012-07-18 15:35:13 -07:00
|
|
|
*
|
2011-12-20 10:20:44 -08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2012-07-18 15:35:13 -07:00
|
|
|
*
|
2011-12-20 10:20:44 -08:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
package org.thoughtcrime.securesms.service;
|
|
|
|
|
|
|
|
import android.app.Notification;
|
|
|
|
import android.app.NotificationManager;
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
import android.database.Cursor;
|
|
|
|
import android.graphics.Color;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
import android.text.TextUtils;
|
|
|
|
import android.util.Log;
|
|
|
|
|
2012-07-18 15:35:13 -07:00
|
|
|
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
|
|
|
import org.thoughtcrime.securesms.ConversationListActivity;
|
|
|
|
import org.thoughtcrime.securesms.R;
|
|
|
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
|
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
|
|
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
|
|
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
|
|
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
|
|
|
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
|
|
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
|
|
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
/**
|
|
|
|
* Handles posting system notifications for new messages.
|
2012-07-18 15:35:13 -07:00
|
|
|
*
|
|
|
|
*
|
2011-12-20 10:20:44 -08:00
|
|
|
* @author Moxie Marlinspike
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class MessageNotifier {
|
|
|
|
|
|
|
|
public static final int NOTIFICATION_ID = 1338;
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-09-07 20:03:23 -07:00
|
|
|
private static String buildTickerMessage(Context context, int count, Recipients recipients) {
|
2011-12-20 10:20:44 -08:00
|
|
|
Recipient recipient = recipients.getPrimaryRecipient();
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-09-07 20:03:23 -07:00
|
|
|
if (recipient == null) {
|
|
|
|
return String.format(context.getString(R.string._d_new_messages), count);
|
|
|
|
} else {
|
|
|
|
return String.format(context.getString(R.string._d_new_messages_most_recent_from_s), count,
|
|
|
|
recipient.getName() == null ? recipient.getNumber() : recipient.getName());
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-09-07 20:03:23 -07:00
|
|
|
private static String buildTitleMessage(Context context, int count) {
|
|
|
|
return String.format(context.getString(R.string._d_new_messages), count);
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-09-07 20:03:23 -07:00
|
|
|
private static String buildSubtitleMessage(Context context, Recipients recipients) {
|
2011-12-20 10:20:44 -08:00
|
|
|
Recipient recipient = recipients.getPrimaryRecipient();
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
if (recipient != null) {
|
2012-09-07 20:03:23 -07:00
|
|
|
return String.format(context.getString(R.string.most_recent_from_s),
|
|
|
|
(recipient.getName() == null ? recipient.getNumber() : recipient.getName()));
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static Recipients getSmsRecipient(Context context, Cursor c) throws RecipientFormattingException {
|
|
|
|
String address = c.getString(c.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
|
|
|
|
return RecipientFactory.getRecipientsFromString(context, address);
|
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static Recipients getMmsRecipient(Context context, Cursor c) throws RecipientFormattingException {
|
|
|
|
long messageId = c.getLong(c.getColumnIndexOrThrow(MmsDatabase.ID));
|
|
|
|
String address = DatabaseFactory.getMmsDatabase(context).getMessageRecipient(messageId);
|
|
|
|
return RecipientFactory.getRecipientsFromString(context, address);
|
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static Recipients getMostRecentRecipients(Context context, Cursor c) {
|
|
|
|
if (c != null && c.moveToLast()) {
|
|
|
|
try {
|
2012-09-07 20:03:23 -07:00
|
|
|
String type = c.getString(c.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-09-07 20:03:23 -07:00
|
|
|
if (type.equals("sms"))
|
|
|
|
return getSmsRecipient(context, c);
|
|
|
|
else
|
|
|
|
return getMmsRecipient(context, c);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
} catch (RecipientFormattingException e) {
|
2012-09-07 20:03:23 -07:00
|
|
|
return new Recipients(new LinkedList<Recipient>());
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static PendingIntent buildPendingIntent(Context context, Cursor c, Recipients recipients) {
|
2012-07-18 15:35:13 -07:00
|
|
|
Intent intent = new Intent(context, ConversationListActivity.class);
|
2011-12-20 10:20:44 -08:00
|
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
Log.w("SMSNotifier", "Building pending intent...");
|
|
|
|
if (c != null && c.getCount() == 1) {
|
|
|
|
Log.w("SMSNotifier", "Adding extras...");
|
|
|
|
c.moveToLast();
|
|
|
|
long threadId = c.getLong(c.getColumnIndexOrThrow(SmsDatabase.THREAD_ID));
|
|
|
|
Log.w("SmsNotifier", "Adding thread_id to pending intent: " + threadId);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
if (recipients.getPrimaryRecipient() != null) {
|
2012-09-07 20:03:23 -07:00
|
|
|
intent.putExtra("recipients", recipients);
|
|
|
|
intent.putExtra("thread_id", threadId);
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
|
|
|
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
return PendingIntent.getActivity(context, 0, intent, 0);
|
|
|
|
}
|
|
|
|
|
2012-07-18 15:35:13 -07:00
|
|
|
private static void sendNotification(Context context, NotificationManager manager, PendingIntent launchIntent,
|
|
|
|
String ticker, String title, String subtitle, boolean signal)
|
2011-12-20 10:20:44 -08:00
|
|
|
{
|
2012-07-18 15:35:13 -07:00
|
|
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
2011-12-20 10:20:44 -08:00
|
|
|
if (!sp.getBoolean(ApplicationPreferencesActivity.NOTIFICATION_PREF, true)) return;
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2012-07-31 13:17:06 -07:00
|
|
|
Notification notification = new Notification(R.drawable.icon_notification, ticker, System.currentTimeMillis());
|
2011-12-20 10:20:44 -08:00
|
|
|
String ringtone = sp.getString(ApplicationPreferencesActivity.RINGTONE_PREF, null);
|
|
|
|
boolean vibrate = sp.getBoolean(ApplicationPreferencesActivity.VIBRATE_PREF, true);
|
|
|
|
String ledColor = sp.getString(ApplicationPreferencesActivity.LED_COLOR_PREF, "green");
|
|
|
|
String ledBlinkPattern = sp.getString(ApplicationPreferencesActivity.LED_BLINK_PREF, "500,2000");
|
|
|
|
String ledBlinkPatternCustom = sp.getString(ApplicationPreferencesActivity.LED_BLINK_PREF_CUSTOM, "500,2000");
|
|
|
|
String[] blinkPatternArray = parseBlinkPattern(ledBlinkPattern, ledBlinkPatternCustom);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
notification.setLatestEventInfo(context, title, subtitle, launchIntent);
|
|
|
|
notification.sound = TextUtils.isEmpty(ringtone) || !signal ? null : Uri.parse(ringtone);
|
|
|
|
if (signal && vibrate)
|
|
|
|
notification.defaults |= Notification.DEFAULT_VIBRATE;
|
|
|
|
|
|
|
|
notification.flags |= Notification.FLAG_SHOW_LIGHTS;
|
|
|
|
notification.ledARGB = Color.parseColor(ledColor);//0xff00ff00;
|
|
|
|
notification.ledOnMS = Integer.parseInt(blinkPatternArray[0]);
|
|
|
|
notification.ledOffMS = Integer.parseInt(blinkPatternArray[1]);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
|
|
|
manager.notify(NOTIFICATION_ID, notification);
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static void flashNotification(Context context, NotificationManager manager) {
|
|
|
|
sendNotification(context, manager, buildPendingIntent(context, null, null), "(1) New Messages", "(1) New Messages", null, true);
|
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
public static void updateNotification(Context context, boolean signal) {
|
|
|
|
NotificationManager manager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
2012-07-18 15:35:13 -07:00
|
|
|
manager.cancel(NOTIFICATION_ID);
|
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
Cursor c = null;
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
try {
|
|
|
|
c = DatabaseFactory.getMmsSmsDatabase(context).getUnread();
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
if ((c == null && signal) || (!c.moveToFirst() && signal)) {flashNotification(context, manager); return;}
|
|
|
|
else if (c == null || !c.moveToFirst()) return;
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
Recipients recipients = getMostRecentRecipients(context, c);
|
2012-09-07 20:03:23 -07:00
|
|
|
String ticker = buildTickerMessage(context, c.getCount(), recipients);
|
|
|
|
String title = buildTitleMessage(context, c.getCount());
|
|
|
|
String subtitle = buildSubtitleMessage(context, recipients);
|
2011-12-20 10:20:44 -08:00
|
|
|
PendingIntent launchIntent = buildPendingIntent(context, c, recipients);
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
sendNotification(context, manager, launchIntent, ticker, title, subtitle, signal);
|
|
|
|
} finally {
|
|
|
|
if (c != null)
|
2012-07-18 15:35:13 -07:00
|
|
|
c.close();
|
2011-12-20 10:20:44 -08:00
|
|
|
}
|
2012-07-18 15:35:13 -07:00
|
|
|
}
|
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
private static String[] parseBlinkPattern(String blinkPattern, String blinkPatternCustom) {
|
|
|
|
if (blinkPattern.equals("custom"))
|
|
|
|
blinkPattern = blinkPatternCustom;
|
2012-07-18 15:35:13 -07:00
|
|
|
|
2011-12-20 10:20:44 -08:00
|
|
|
return blinkPattern.split(",");
|
|
|
|
}
|
|
|
|
}
|