Contacts App modifications for large photos.
Most of the work is on the provider side - essentially, the
provider will now deal with any size photo, downsizing it as
necessary to fit in a display size and thumbnail size. So
on the client we just need to pass in a larger photo to get a
hi-res display image for the contact.
Also switched a few spots to use the PHOTO_URI (with
openAssetFile) instead of PHOTO_THUMB_URI - more likely
remain.
Change-Id: I6ff8dd5453a9ff787907ab113d6e8aa6a71fcae1
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index 7ed9d86..f10e6b8 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -28,6 +28,7 @@
import android.content.Loader;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
@@ -45,6 +46,8 @@
import android.util.Log;
import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -673,6 +676,33 @@
* not found, returns null
*/
private void loadPhotoBinaryData(Result contactData) {
+
+ // If we have a photo URI, try loading that first.
+ String photoUri = contactData.getPhotoUri();
+ if (photoUri != null) {
+ try {
+ AssetFileDescriptor fd = getContext().getContentResolver()
+ .openAssetFileDescriptor(Uri.parse(photoUri), "r");
+ byte[] buffer = new byte[16 * 1024];
+ FileInputStream fis = fd.createInputStream();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ int size;
+ while ((size = fis.read(buffer)) != -1) {
+ baos.write(buffer, 0, size);
+ }
+ contactData.setPhotoBinaryData(baos.toByteArray());
+ } finally {
+ fis.close();
+ fd.close();
+ }
+ return;
+ } catch (IOException ioe) {
+ // Just fall back to the case below.
+ }
+ }
+
+ // If we couldn't load from a file, fall back to the data blob.
final long photoId = contactData.getPhotoId();
if (photoId <= 0) {
// No photo ID
diff --git a/src/com/android/contacts/GroupMemberLoader.java b/src/com/android/contacts/GroupMemberLoader.java
index 13edff0..e2945f6 100644
--- a/src/com/android/contacts/GroupMemberLoader.java
+++ b/src/com/android/contacts/GroupMemberLoader.java
@@ -48,10 +48,11 @@
Data.CONTACT_PRESENCE, // 6
Data.CONTACT_CHAT_CAPABILITY, // 7
Data.PHOTO_ID, // 8
- Data.PHOTO_THUMBNAIL_URI, // 9
- Data.LOOKUP_KEY, // 10
- Data.PHONETIC_NAME, // 11
- Data.HAS_PHONE_NUMBER, // 12
+ Data.PHOTO_URI, // 9
+ Data.PHOTO_THUMBNAIL_URI, // 10
+ Data.LOOKUP_KEY, // 11
+ Data.PHONETIC_NAME, // 12
+ Data.HAS_PHONE_NUMBER, // 13
};
private final long mGroupId;
@@ -66,6 +67,7 @@
public static final int CONTACT_CHAT_CAPABILITY_COLUMN_INDEX = 7;
public static final int CONTACT_PHOTO_ID_COLUMN_INDEX = 8;
public static final int CONTACT_PHOTO_URI_COLUMN_INDEX = 9;
+ public static final int CONTACT_PHOTO_THUMBNAIL_URI_COLUMN_INDEX = 10;
public static final int CONTACT_LOOKUP_KEY_COLUMN_INDEX = 10;
public static final int CONTACT_PHONETIC_NAME_COLUMN_INDEX = 11;
public static final int CONTACT_HAS_PHONE_COLUMN_INDEX = 12;
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 65d24c3..1eabaf7 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -35,6 +35,7 @@
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.DisplayPhoto;
import android.provider.ContactsContract.RawContacts;
import android.widget.Toast;
@@ -57,6 +58,9 @@
private ContentResolver mContentResolver;
+ // Height/width (in pixels) to request for the photo - queried from the provider.
+ private static int mPhotoDim;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -70,6 +74,16 @@
}
mContentResolver = getContentResolver();
+
+ // Load the photo dimension to request.
+ Cursor c = mContentResolver.query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
+ new String[]{DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null);
+ try {
+ c.moveToFirst();
+ mPhotoDim = c.getInt(0);
+ } finally {
+ c.close();
+ }
}
@Override
@@ -121,8 +135,8 @@
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", 96);
- intent.putExtra("outputY", 96);
+ intent.putExtra("outputX", mPhotoDim);
+ intent.putExtra("outputY", mPhotoDim);
intent.putExtra("return-data", true);
startActivityForResult(intent, REQUEST_CROP_PHOTO);
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index ece2a29..4d116d1 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -66,6 +66,7 @@
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.DisplayPhoto;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.RawContacts;
@@ -196,8 +197,6 @@
private final EntityDeltaComparator mComparator = new EntityDeltaComparator();
- private static final int ICON_SIZE = 96;
-
private static final File PHOTO_DIR = new File(
Environment.getExternalStorageDirectory() + "/DCIM/Camera");
@@ -216,6 +215,9 @@
private File mCurrentPhotoFile;
+ // Height/width (in pixels) to request for the photo - queried from the provider.
+ private int mPhotoPickSize;
+
private Context mContext;
private String mAction;
private Uri mLookupUri;
@@ -265,6 +267,7 @@
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext = activity;
+ loadPhotoPickSize();
}
@Override
@@ -774,17 +777,28 @@
return save(SaveMode.JOIN);
}
+ private void loadPhotoPickSize() {
+ Cursor c = mContext.getContentResolver().query(DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
+ new String[]{DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null);
+ try {
+ c.moveToFirst();
+ mPhotoPickSize = c.getInt(0);
+ } finally {
+ c.close();
+ }
+ }
+
/**
* Constructs an intent for picking a photo from Gallery, cropping it and returning the bitmap.
*/
- public static Intent getPhotoPickIntent() {
+ public Intent getPhotoPickIntent() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", ICON_SIZE);
- intent.putExtra("outputY", ICON_SIZE);
+ intent.putExtra("outputX", mPhotoPickSize);
+ intent.putExtra("outputY", mPhotoPickSize);
intent.putExtra("return-data", true);
return intent;
}
@@ -840,14 +854,14 @@
/**
* Constructs an intent for image cropping.
*/
- public static Intent getCropImageIntent(Uri photoUri) {
+ public Intent getCropImageIntent(Uri photoUri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(photoUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", ICON_SIZE);
- intent.putExtra("outputY", ICON_SIZE);
+ intent.putExtra("outputX", mPhotoPickSize);
+ intent.putExtra("outputY", mPhotoPickSize);
intent.putExtra("return-data", true);
return intent;
}