bump sdk to 22, update notifications
Notification updates include: 1) Setting theme colors 2) Using high-res contact photos 3) Updating the notification icon to latest Closes #2935 Fixes #2923 Fixes #2732 Fixes #2548 // FREEBIE
|
@ -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"
|
||||
|
|
Before Width: | Height: | Size: 533 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 628 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 367 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 437 B After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 686 B After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -9,6 +9,7 @@
|
|||
<dimen name="transport_selection_popup_width">200sp</dimen>
|
||||
<dimen name="transport_selection_popup_xoff">0dp</dimen>
|
||||
<dimen name="transport_selection_popup_yoff">1dp</dimen>
|
||||
<dimen name="contact_photo_target_size">64dp</dimen>
|
||||
<dimen name="contact_selection_photo_size">50dp</dimen>
|
||||
<dimen name="thumbnail_max_size">230dp</dimen>
|
||||
<dimen name="preference_fragment_padding_side">8dp</dimen>
|
||||
|
|
|
@ -435,8 +435,8 @@
|
|||
<string name="KeyCachingService_lock">Lock with passphrase</string>
|
||||
|
||||
<!-- MessageNotifier -->
|
||||
<string name="MessageNotifier_d_new_messages">%d new messages</string>
|
||||
<string name="MessageNotifier_most_recent_from_s">Most recent from: %s</string>
|
||||
<string name="MessageNotifier_d_messages_in_d_conversations">%1$d messages in %2$d conversations</string>
|
||||
<string name="MessageNotifier_most_recent_from_s">Most recent from: %1$s</string>
|
||||
<string name="MessageNotifier_encrypted_message">Encrypted message...</string>
|
||||
<string name="MessageNotifier_media_message_with_text">Media message: %s</string>
|
||||
<string name="MessageNotifier_no_subject">(No subject)</string>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<NotificationItem> 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|