org.thoughtcrime.securesms.service.MessageNotifier.java Source code

Java tutorial

Introduction

Here is the source code for org.thoughtcrime.securesms.service.MessageNotifier.java

Source

/**
 * Copyright (C) 2011 Whisper Systems
 *
 * 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.
 *
 * 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.Bitmap;
import android.graphics.Color;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;

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;

/**
 * Handles posting system notifications for new messages.
 *
 *
 * @author Moxie Marlinspike
 */

public class MessageNotifier {

    public static final int NOTIFICATION_ID = 1338;

    private static Bitmap buildContactPhoto(Recipients recipients) {
        Recipient recipient = recipients.getPrimaryRecipient();

        if (recipient == null) {
            return null;
        } else {
            return recipient.getContactPhoto();
        }
    }

    private static String buildTickerMessage(Context context, int count, Recipients recipients) {
        Recipient recipient = recipients.getPrimaryRecipient();

        if (recipient == null) {
            return String.format(context.getString(R.string.MessageNotifier_d_new_messages), count);
        } else {
            return String.format(context.getString(R.string.MessageNotifier_d_new_messages_most_recent_from_s),
                    count, recipient.getName() == null ? recipient.getNumber() : recipient.getName());
        }
    }

    private static String buildTitleMessage(Context context, int count) {
        return String.format(context.getString(R.string.MessageNotifier_d_new_messages), count);
    }

    private static String buildSubtitleMessage(Context context, Recipients recipients) {
        Recipient recipient = recipients.getPrimaryRecipient();

        if (recipient != null) {
            return String.format(context.getString(R.string.MessageNotifier_most_recent_from_s),
                    (recipient.getName() == null ? recipient.getNumber() : recipient.getName()));
        }

        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);
    }

    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);
    }

    private static Recipients getMostRecentRecipients(Context context, Cursor c) {
        if (c != null && c.moveToLast()) {
            try {
                String type = c.getString(c.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));

                if (type.equals("sms"))
                    return getSmsRecipient(context, c);
                else
                    return getMmsRecipient(context, c);

            } catch (RecipientFormattingException e) {
                return new Recipients(new LinkedList<Recipient>());
            }
        }

        return null;
    }

    private static PendingIntent buildPendingIntent(Context context, Cursor c, Recipients recipients) {
        Intent intent = new Intent(context, ConversationListActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        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);

            if (recipients.getPrimaryRecipient() != null) {
                intent.putExtra("recipients", recipients);
                intent.putExtra("thread_id", threadId);
            }

            intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
        }

        return PendingIntent.getActivity(context, 0, intent, 0);
    }

    private static void sendNotification(Context context, NotificationManager manager, PendingIntent launchIntent,
            Bitmap contactPhoto, String ticker, String title, String subtitle, boolean signal) {
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
        if (!sp.getBoolean(ApplicationPreferencesActivity.NOTIFICATION_PREF, true))
            return;

        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);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setSmallIcon(R.drawable.icon_notification);
        builder.setLargeIcon(contactPhoto);
        builder.setTicker(ticker);
        builder.setContentTitle(title);
        builder.setContentText(subtitle);
        builder.setContentIntent(launchIntent);
        builder.setSound(TextUtils.isEmpty(ringtone) || !signal ? null : Uri.parse(ringtone));

        if (signal && vibrate)
            builder.setDefaults(Notification.DEFAULT_VIBRATE);

        builder.setLights(Color.parseColor(ledColor), Integer.parseInt(blinkPatternArray[0]),
                Integer.parseInt(blinkPatternArray[1]));

        manager.notify(NOTIFICATION_ID, builder.build());
    }

    private static void flashNotification(Context context, NotificationManager manager) {
        sendNotification(context, manager, buildPendingIntent(context, null, null), null, "(1) New Messages",
                "(1) New Messages", null, true);
    }

    public static void updateNotification(Context context, boolean signal) {
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        manager.cancel(NOTIFICATION_ID);

        Cursor c = null;

        try {
            c = DatabaseFactory.getMmsSmsDatabase(context).getUnread();

            if ((c == null && signal) || (!c.moveToFirst() && signal)) {
                flashNotification(context, manager);
                return;
            } else if (c == null || !c.moveToFirst())
                return;

            Recipients recipients = getMostRecentRecipients(context, c);
            String ticker = buildTickerMessage(context, c.getCount(), recipients);
            String title = buildTitleMessage(context, c.getCount());
            String subtitle = buildSubtitleMessage(context, recipients);
            PendingIntent launchIntent = buildPendingIntent(context, c, recipients);
            Bitmap contactPhoto = buildContactPhoto(recipients);

            sendNotification(context, manager, launchIntent, contactPhoto, ticker, title, subtitle, signal);
        } finally {
            if (c != null)
                c.close();
        }
    }

    private static String[] parseBlinkPattern(String blinkPattern, String blinkPatternCustom) {
        if (blinkPattern.equals("custom"))
            blinkPattern = blinkPatternCustom;

        return blinkPattern.split(",");
    }
}