diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java
index edf7487697..d260668c31 100644
--- a/src/org/thoughtcrime/securesms/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationItem.java
@@ -27,6 +27,8 @@ import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
+import android.provider.Contacts.Intents;
+import android.provider.ContactsContract.QuickContact;
import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.format.DateUtils;
@@ -249,10 +251,24 @@ public class ConversationItem extends LinearLayout {
}
private void setBodyImage(MessageRecord messageRecord) {
- Recipient recipient = messageRecord.getMessageRecipient();
+ final Recipient recipient = messageRecord.getMessageRecipient();
- if (!messageRecord.isOutgoing()) contactPhoto.setImageBitmap(recipient.getContactPhoto());
- else setContactPhotoForUserIdentity();
+ if (!messageRecord.isOutgoing()) {
+ contactPhoto.setImageBitmap(recipient.getContactPhoto());
+ contactPhoto.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (recipient.getContactUri() != null) {
+ QuickContact.showQuickContact(context, contactPhoto, recipient.getContactUri(), QuickContact.MODE_LARGE, null);
+ } else {
+ Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null));
+ context.startActivity(intent);
+ }
+ }
+ });
+ } else {
+ setContactPhotoForUserIdentity();
+ }
contactPhoto.setVisibility(View.VISIBLE);
}
diff --git a/src/org/thoughtcrime/securesms/recipients/NewRecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/NewRecipientProvider.java
index 91491a05fc..9da563aefb 100644
--- a/src/org/thoughtcrime/securesms/recipients/NewRecipientProvider.java
+++ b/src/org/thoughtcrime/securesms/recipients/NewRecipientProvider.java
@@ -1,6 +1,6 @@
-/**
+/**
* 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
@@ -10,25 +10,23 @@
* 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 .
*/
package org.thoughtcrime.securesms.recipients;
-import java.io.InputStream;
-
-
-import android.content.ContentUris;
import android.content.Context;
-import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
+import java.io.InputStream;
+
public class NewRecipientProvider extends RecipientProvider {
private static final String[] CALLER_ID_PROJECTION = new String[] {
@@ -36,82 +34,67 @@ public class NewRecipientProvider extends RecipientProvider {
PhoneLookup.LOOKUP_KEY,
PhoneLookup._ID,
};
-
+
private static final String[] CONTENT_URI_PROJECTION = new String[] {
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
+ ContactsContract.Contacts.LOOKUP_KEY
};
-
+
@Override
- public Recipient getRecipient(Context context, Uri uri) {
+ public Recipient getRecipient(Context context, Uri uri) {
Cursor cursor = context.getContentResolver().query(uri, CONTENT_URI_PROJECTION, null, null, null);
-
+
try {
if (cursor.moveToFirst()) {
- long rowId = cursor.getLong(0);
- Uri photoLookupUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, rowId);
+ long rowId = cursor.getLong(0);
+ Uri contactUri = Contacts.getLookupUri(rowId, cursor.getString(2));
+ Bitmap contactPhoto = getContactPhoto(context, contactUri);
+ String displayName = cursor.getString(1);
+ cursor.close();
- Bitmap contactPhoto = getContactPhoto(context, photoLookupUri);
- String displayName = cursor.getString(1);
- cursor.close();
-
- cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER}, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[] {rowId+""}, null);
- if (cursor.moveToFirst())
- return new Recipient(displayName, cursor.getString(0), rowId, contactPhoto);
- else
- return new Recipient(displayName, null, rowId, contactPhoto);
+ cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Phone.NUMBER}, ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = ?", new String[] {rowId+""}, null);
+
+ if (cursor.moveToFirst())
+ return new Recipient(displayName, cursor.getString(0), contactUri, contactPhoto);
+ else
+ return new Recipient(displayName, null, contactUri, contactPhoto);
}
} finally {
cursor.close();
}
-
+
return null;
}
-
+
@Override
public Recipient getRecipient(Context context, String number) {
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
Cursor cursor = context.getContentResolver().query(uri, CALLER_ID_PROJECTION, null, null, null);
-
+
try {
if (cursor != null && cursor.moveToFirst()) {
- Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, cursor.getLong(2));
- Bitmap contactPhoto = getContactPhoto(context, contactUri);
-
- Recipient recipient = new Recipient(cursor.getString(0), number, cursor.getLong(2), contactPhoto);
- return recipient;
+ Uri contactUri = Contacts.getLookupUri(cursor.getLong(2), cursor.getString(1));
+ Bitmap contactPhoto = getContactPhoto(context, contactUri);
+
+ Recipient recipient = new Recipient(cursor.getString(0), number, contactUri, contactPhoto);
+ return recipient;
}
} finally {
if (cursor != null)
- cursor.close();
+ cursor.close();
}
return null;
}
-
+
private Bitmap getContactPhoto(Context context, Uri uri) {
InputStream inputStream = ContactsContract.Contacts.openContactPhotoInputStream(context.getContentResolver(), uri);
-
+
if (inputStream == null)
return getDefaultContactPhoto(context);
- // return BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture);
else
- return BitmapFactory.decodeStream(inputStream);
- }
-
- @Override
- public void viewContact(Context context, Recipient recipient) {
- Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, recipient.getPersonId());
- Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
- context.startActivity(intent);
- }
-
- @Override
- public void addContact(Context context, Recipient recipient) {
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
- intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getNumber());
- context.startActivity(intent);
+ return BitmapFactory.decodeStream(inputStream);
}
}
diff --git a/src/org/thoughtcrime/securesms/recipients/OldRecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/OldRecipientProvider.java
deleted file mode 100644
index 34af4c88ea..0000000000
--- a/src/org/thoughtcrime/securesms/recipients/OldRecipientProvider.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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 .
- */
-package org.thoughtcrime.securesms.recipients;
-
-import org.thoughtcrime.securesms.R;
-
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
-import android.provider.Contacts.Intents.Insert;
-import android.util.Log;
-
-public class OldRecipientProvider extends RecipientProvider {
-
- private static final String CALLER_ID_SELECTION = "PHONE_NUMBERS_EQUAL(" +Contacts.Phones.NUMBER + ",?)";
- @SuppressWarnings("deprecation")
- private static final String[] CALLER_ID_PROJECTION = new String[] {
- // Contacts.People.Phones.NUMBER, // 0
- // Contacts.People.Phones.LABEL, // 1
- Contacts.People.NAME, // 2
- Contacts.Phones.PERSON_ID, // 3
- Contacts.People.Phones.NUMBER,
- };
-
- @Override
- public Recipient getRecipient(Context context, Uri uri) {
- Cursor cursor = context.getContentResolver().query(uri, new String[] {Contacts.People.NAME, Contacts.People._ID, Contacts.People.NUMBER}, null, null, null);
-
- try {
- if (cursor.moveToNext()) {
- return new Recipient(cursor.getString(0), cursor.getString(2), cursor.getLong(1),
- Contacts.People.loadContactPhoto(context, uri, R.drawable.ic_contact_picture, null));
- }
- } finally {
- cursor.close();
- }
-
- return null;
- }
-
- @Override
- public Recipient getRecipient(Context context, String number) {
- String arguments[] = {number};
- Cursor cursor = context.getContentResolver().query(Contacts.Phones.CONTENT_URI, CALLER_ID_PROJECTION,
- CALLER_ID_SELECTION, arguments, null);
- try {
- if (cursor.moveToFirst()) {
- Uri personUri = Uri.withAppendedPath(Contacts.People.CONTENT_URI, cursor.getLong(1)+"");
- Recipient recipient = new Recipient(cursor.getString(0), number, cursor.getLong(1),
- Contacts.People.loadContactPhoto(context, personUri, R.drawable.ic_contact_picture, null));
- return recipient;
- }
- } finally {
- cursor.close();
- }
-
- return null;
- }
-
- @Override
- public void viewContact(Context context, Recipient recipient) {
- Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recipient.getPersonId());
- Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- context.startActivity(intent);
- }
-
- @Override
- public void addContact(Context context, Recipient recipient) {
- Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
- intent.setType(Contacts.People.CONTENT_ITEM_TYPE);
- intent.putExtra(Insert.PHONE, recipient.getNumber());
- context.startActivity(intent);
- }
-
-}
diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java
index f0568a74fc..88ed853d39 100644
--- a/src/org/thoughtcrime/securesms/recipients/Recipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java
@@ -1,6 +1,6 @@
-/**
+/**
* 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
@@ -10,13 +10,14 @@
* 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 .
*/
package org.thoughtcrime.securesms.recipients;
import android.graphics.Bitmap;
+import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,30 +32,31 @@ public class Recipient implements Parcelable {
return new Recipient[size];
}
};
-
+
private final String name;
private final String number;
- private long personId = -1;
+ private Uri contactUri;
private Bitmap contactPhoto;
-
- public Recipient(String name, String number, long personId, Bitmap contactPhoto) {
+
+ public Recipient(String name, String number, Uri contactUri, Bitmap contactPhoto) {
this(name, number, contactPhoto);
- this.personId = personId;
+ this.contactUri = contactUri;
}
-
+
public Recipient(String name, String number, Bitmap contactPhoto) {
this.name = name;
this.number = number;
this.contactPhoto = contactPhoto;
}
-
+
public Recipient(Parcel in) {
- this.name = in.readString();
- this.number = in.readString();
+ this.name = in.readString();
+ this.number = in.readString();
+ this.contactUri = in.readParcelable(null);
}
-
- public long getPersonId() {
- return personId;
+
+ public Uri getContactUri() {
+ return this.contactUri;
}
public String getName() {
@@ -64,24 +66,24 @@ public class Recipient implements Parcelable {
public String getNumber() {
return number;
}
-
+
public int describeContents() {
- // TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(number);
+ dest.writeParcelable(contactUri, 0);
}
-
+
public String toShortString() {
return (name == null ? number : name);
}
-
+
public Bitmap getContactPhoto() {
return contactPhoto;
}
-
-
+
+
}
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
index d8eaf1065c..cac6b3f76c 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientFactory.java
@@ -1,6 +1,6 @@
-/**
+/**
* 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
@@ -10,12 +10,22 @@
* 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 .
*/
package org.thoughtcrime.securesms.recipients;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.util.NumberUtil;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -23,115 +33,86 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.StringTokenizer;
-import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.database.DatabaseFactory;
-import org.thoughtcrime.securesms.util.NumberUtil;
-
-import android.content.Context;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Build;
-import android.telephony.PhoneNumberUtils;
-import android.util.Log;
-
public class RecipientFactory {
private static final Map recipientCache = Collections.synchronizedMap(new LRUHashMap());
private static final Map recipientIdCache = Collections.synchronizedMap(new LRUHashMap());
- private static final Map recipientUriCache = Collections.synchronizedMap(new HashMap());
-
- private static RecipientProvider provider;
-
- static {
- String className;
-
- int sdkVersion = Integer.parseInt(Build.VERSION.SDK);
-
- if (sdkVersion <= Build.VERSION_CODES.DONUT) className = "OldRecipientProvider";
- else className = "NewRecipientProvider";
+ private static final Map recipientUriCache = Collections.synchronizedMap(new HashMap());
+
+ private static final RecipientProvider provider = new NewRecipientProvider();
- try {
- Class extends RecipientProvider> clazz =
- Class.forName("org.thoughtcrime.securesms.recipients." + className)
- .asSubclass(RecipientProvider.class);
- provider = clazz.newInstance();
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
public static RecipientProvider getRecipientProvider() {
return provider;
}
-
+
public static Recipient getRecipientForUri(Context context, Uri uri) {
Recipient recipient = recipientUriCache.get(uri);
-
+
if (recipient == null)
recipient = getRecipientFromProvider(context, uri);
-
+
return recipient;
}
-
+
public static Recipients getRecipientsForIds(Context context, String recipientIds) {
ArrayList results = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(recipientIds.trim(), " ");
-
+
while (tokenizer.hasMoreTokens()) {
String recipientId = tokenizer.nextToken();
-
+
Recipient recipient = recipientIdCache.get(recipientId);
-
+
if (recipient == null)
recipient = getRecipientFromProviderId(context, recipientId);
-
+
if (recipient == null)
recipient = getNullIdRecipient(context, recipientId);
-
+
results.add(recipient);
}
-
+
return new Recipients(results);
}
-
+
private static Recipient getRecipientForNumber(Context context, String number) {
Recipient recipient = recipientCache.get(number);
-
+
if (recipient == null)
recipient = getRecipientFromProvider(context, number);
-
+
if (recipient == null)
recipient = getNullRecipient(context, number);
-
+
return recipient;
}
-
+
public static Recipients getRecipientsFromString(Context context, String rawText) throws RecipientFormattingException {
ArrayList results = new ArrayList();
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
while (tokenizer.hasMoreTokens()) {
Recipient recipient = parseRecipient(context, tokenizer.nextToken());
- if( recipient != null )
- results.add(recipient);
+ if( recipient != null )
+ results.add(recipient);
}
return new Recipients(results);
}
-
+
private static Recipient getNullIdRecipient(Context context, String recipientId) {
String address = DatabaseFactory.getAddressDatabase(context).getAddressFromId(recipientId);
Recipient recipient = getNullRecipient(context, address);
recipientIdCache.put(recipientId, recipient);
return recipient;
}
-
+
private static Recipient getNullRecipient(Context context, String number) {
Recipient nullRecipient = new Recipient(null, number, BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture));
recipientCache.put(number, nullRecipient);
return nullRecipient;
}
-
+
private static Recipient getRecipientFromProviderId(Context context, String recipientId) {
Log.w("RecipientFactory", "Hitting recipient provider [ID].");
@@ -144,37 +125,37 @@ public class RecipientFactory {
private static Recipient getRecipientFromProvider(Context context, Uri uri) {
Recipient recipient = provider.getRecipient(context, uri);
-
- if (recipient != null)
+
+ if (recipient != null)
recipientUriCache.put(uri, recipient);
-
+
return recipient;
}
private static Recipient getRecipientFromProvider(Context context, String number) {
Recipient recipient = provider.getRecipient(context, number);
-
+
if (recipient != null)
recipientCache.put(number, recipient);
return recipient;
}
-
+
private static String parseBracketedNumber(String recipient) throws RecipientFormattingException {
int begin = recipient.indexOf('<');
int end = recipient.indexOf('>');
String value = recipient.substring(begin + 1, end);
-
+
if (PhoneNumberUtils.isWellFormedSmsAddress(value))
return value;
else
throw new RecipientFormattingException("Bracketed value: " + value + " is not valid.");
}
-
+
private static Recipient parseRecipient(Context context, String recipient) throws RecipientFormattingException {
recipient = recipient.trim();
- if( recipient.length() == 0 )
+ if( recipient.length() == 0 )
return null;
if ((recipient.indexOf('<') != -1) && (recipient.indexOf('>') != -1))
@@ -182,7 +163,7 @@ public class RecipientFactory {
if (NumberUtil.isValidSmsOrEmail(recipient))
return getRecipientForNumber(context, recipient);
-
+
throw new RecipientFormattingException("Recipient: " + recipient + " is badly formatted.");
}
@@ -191,12 +172,12 @@ public class RecipientFactory {
recipientIdCache.clear();
recipientUriCache.clear();
}
-
+
private static class LRUHashMap extends LinkedHashMap {
private static final int MAX_SIZE = 1000;
- @Override
+ @Override
protected boolean removeEldestEntry (Map.Entry eldest) {
- return size() > MAX_SIZE;
+ return size() > MAX_SIZE;
}
}
}
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
index 3d2aadfb7a..783b947e57 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
@@ -1,6 +1,6 @@
-/**
+/**
* 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
@@ -10,34 +10,32 @@
* 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 .
*/
package org.thoughtcrime.securesms.recipients;
-import org.thoughtcrime.securesms.R;
-
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
+import org.thoughtcrime.securesms.R;
+
public abstract class RecipientProvider {
-
+
private static Bitmap defaultContactPhoto;
-
+
public abstract Recipient getRecipient(Context context, String number);
public abstract Recipient getRecipient(Context context, Uri uri);
- public abstract void viewContact(Context context, Recipient recipient);
- public abstract void addContact(Context context, Recipient recipient);
public Bitmap getDefaultContactPhoto(Context context) {
synchronized (this) {
if (defaultContactPhoto == null)
defaultContactPhoto = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_contact_picture);
}
-
+
return defaultContactPhoto;
}
}
\ No newline at end of file