diff --git a/build.gradle b/build.gradle
index 662d32a6ca..596a14fae4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -132,7 +132,7 @@ android {
defaultConfig {
minSdkVersion 9
- targetSdkVersion 19
+ targetSdkVersion 22
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
diff --git a/res/drawable-hdpi-v11/icon_notification.png b/res/drawable-hdpi-v11/icon_notification.png
index e0cea95c3e..aa31bf571b 100644
Binary files a/res/drawable-hdpi-v11/icon_notification.png and b/res/drawable-hdpi-v11/icon_notification.png differ
diff --git a/res/drawable-hdpi-v9/icon_notification.png b/res/drawable-hdpi-v9/icon_notification.png
index 14840b3663..ffa5235e2a 100644
Binary files a/res/drawable-hdpi-v9/icon_notification.png and b/res/drawable-hdpi-v9/icon_notification.png differ
diff --git a/res/drawable-mdpi-v11/icon_notification.png b/res/drawable-mdpi-v11/icon_notification.png
index fab48d4c50..01f9abda43 100644
Binary files a/res/drawable-mdpi-v11/icon_notification.png and b/res/drawable-mdpi-v11/icon_notification.png differ
diff --git a/res/drawable-mdpi-v9/icon_notification.png b/res/drawable-mdpi-v9/icon_notification.png
index 5886aa8400..6153b25c42 100644
Binary files a/res/drawable-mdpi-v9/icon_notification.png and b/res/drawable-mdpi-v9/icon_notification.png differ
diff --git a/res/drawable-xhdpi-v11/icon_notification.png b/res/drawable-xhdpi-v11/icon_notification.png
index 6cccf186a0..fb57ee4460 100644
Binary files a/res/drawable-xhdpi-v11/icon_notification.png and b/res/drawable-xhdpi-v11/icon_notification.png differ
diff --git a/res/drawable-xxhdpi-v11/icon_notification.png b/res/drawable-xxhdpi-v11/icon_notification.png
index 3f15308559..eef8f802c1 100644
Binary files a/res/drawable-xxhdpi-v11/icon_notification.png and b/res/drawable-xxhdpi-v11/icon_notification.png differ
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index c926c1f826..dbcaf72ee6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -9,6 +9,7 @@
200sp
0dp
1dp
+ 64dp
50dp
230dp
8dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 18e909b185..a8fd663fb0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -435,8 +435,8 @@
Lock with passphrase
- %d new messages
- Most recent from: %s
+ %1$d messages in %2$d conversations
+ Most recent from: %1$s
Encrypted message...
Media message: %s
(No subject)
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java b/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java
index c41d3bbe38..1ea3606023 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java
@@ -5,11 +5,16 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
+import android.util.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.BitmapDecodingException;
+import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.LRUCache;
import java.io.InputStream;
@@ -17,6 +22,7 @@ import java.util.Collections;
import java.util.Map;
public class ContactPhotoFactory {
+ private static final String TAG = ContactPhotoFactory.class.getSimpleName();
private static final Object defaultPhotoLock = new Object();
private static final Object defaultGroupPhotoLock = new Object();
@@ -86,12 +92,31 @@ public class ContactPhotoFactory {
}
public static Bitmap getContactPhoto(Context context, Uri uri) {
- InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
-
- final Bitmap contactPhoto;
- if (inputStream == null) contactPhoto = ContactPhotoFactory.getDefaultContactPhoto(context);
- else contactPhoto = BitmapFactory.decodeStream(inputStream);
+ final InputStream inputStream = getContactPhotoStream(context, uri);
+ final int targetSize = context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size);
+ Bitmap contactPhoto = null;
+ if (inputStream != null) {
+ try {
+ contactPhoto = BitmapUtil.createScaledBitmap(inputStream,
+ getContactPhotoStream(context, uri),
+ targetSize,
+ targetSize);
+ } catch (BitmapDecodingException bde) {
+ Log.w(TAG, bde);
+ }
+ }
+ if (contactPhoto == null) {
+ contactPhoto = ContactPhotoFactory.getDefaultContactPhoto(context);
+ }
return contactPhoto;
}
+
+ private static InputStream getContactPhotoStream(Context context, Uri uri) {
+ if (VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH) {
+ return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri, true);
+ } else {
+ return ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
index 123cee1fd9..e13f6ece7e 100644
--- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
+++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
@@ -53,6 +53,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.KeyCachingService;
+import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
@@ -181,14 +182,18 @@ public class MessageNotifier {
Recipient recipient = notifications.get(0).getIndividualRecipient();
Bitmap recipientPhoto = recipient.getContactPhoto();
+ if (recipientPhoto != null) builder.setLargeIcon(BitmapUtil.getCircleBitmap(recipientPhoto));
builder.setSmallIcon(R.drawable.icon_notification);
- if (recipientPhoto != null) builder.setLargeIcon(recipientPhoto);
+ builder.setColor(context.getResources().getColor(R.color.textsecure_primary));
builder.setContentTitle(recipient.toShortString());
builder.setContentText(notifications.get(0).getText());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
+ builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setNumber(notificationState.getMessageCount());
+ builder.setCategory(NotificationCompat.CATEGORY_MESSAGE);
builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
+ if (recipient.getContactUri() != null) builder.addPerson(recipient.getContactUri().toString());
if (masterSecret != null) {
builder.addAction(R.drawable.check, context.getString(R.string.MessageNotifier_mark_as_read),
@@ -224,17 +229,19 @@ public class MessageNotifier {
List notifications = notificationState.getNotifications();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ builder.setColor(context.getResources().getColor(R.color.textsecure_primary));
builder.setSmallIcon(R.drawable.icon_notification);
- builder.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
- R.drawable.icon_notification));
- builder.setContentTitle(String.format(context.getString(R.string.MessageNotifier_d_new_messages),
- notificationState.getMessageCount()));
- builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s),
- notifications.get(0).getIndividualRecipientName()));
+ builder.setContentTitle(context.getString(R.string.app_name));
+ builder.setSubText(context.getString(R.string.MessageNotifier_d_messages_in_d_conversations,
+ notificationState.getMessageCount(),
+ notificationState.getThreadCount()));
+ builder.setContentText(context.getString(R.string.MessageNotifier_most_recent_from_s,
+ notifications.get(0).getIndividualRecipientName()));
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
builder.setNumber(notificationState.getMessageCount());
+ builder.setCategory(NotificationCompat.CATEGORY_MESSAGE);
builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
@@ -249,6 +256,9 @@ public class MessageNotifier {
while(iterator.hasPrevious()) {
NotificationItem item = iterator.previous();
style.addLine(item.getTickerText());
+ if (item.getIndividualRecipient().getContactUri() != null) {
+ builder.addPerson(item.getIndividualRecipient().getContactUri().toString());
+ }
}
builder.setStyle(style);
diff --git a/src/org/thoughtcrime/securesms/notifications/NotificationState.java b/src/org/thoughtcrime/securesms/notifications/NotificationState.java
index 36db7a9f38..f0d51eec11 100644
--- a/src/org/thoughtcrime/securesms/notifications/NotificationState.java
+++ b/src/org/thoughtcrime/securesms/notifications/NotificationState.java
@@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.notifications;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@@ -30,6 +29,10 @@ public class NotificationState {
return threads.size() > 1;
}
+ public int getThreadCount() {
+ return threads.size();
+ }
+
public int getMessageCount() {
return notificationCount;
}
@@ -38,10 +41,6 @@ public class NotificationState {
return notifications;
}
- public Bitmap getContactPhoto() {
- return notifications.get(0).getIndividualRecipient().getContactPhoto();
- }
-
public PendingIntent getMarkAsReadIntent(Context context, MasterSecret masterSecret) {
long[] threadArray = new long[threads.size()];
int index = 0;
diff --git a/src/org/thoughtcrime/securesms/util/BitmapUtil.java b/src/org/thoughtcrime/securesms/util/BitmapUtil.java
index 0a1c1a38bb..0b189f6ef3 100644
--- a/src/org/thoughtcrime/securesms/util/BitmapUtil.java
+++ b/src/org/thoughtcrime/securesms/util/BitmapUtil.java
@@ -5,27 +5,28 @@ import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.net.Uri;
import android.util.Log;
import android.util.Pair;
+import com.android.gallery3d.data.Exif;
+
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.mms.PartAuthority;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
-import com.android.gallery3d.data.Exif;
-
public class BitmapUtil {
private static final String TAG = BitmapUtil.class.getSimpleName();
@@ -230,4 +231,26 @@ public class BitmapUtil {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
+
+ public static Bitmap getCircleBitmap(Bitmap bitmap) {
+ final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
+ bitmap.getHeight(), Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(output);
+
+ final int color = Color.RED;
+ final Paint paint = new Paint();
+ final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ final RectF rectF = new RectF(rect);
+
+ paint.setAntiAlias(true);
+ canvas.drawARGB(0, 0, 0, 0);
+ paint.setColor(color);
+ canvas.drawOval(rectF, paint);
+
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+ canvas.drawBitmap(bitmap, rect, rect, paint);
+
+ return output;
+ }
+
}