diff --git a/src/org/linphone/ConferenceActivity.java b/src/org/linphone/ConferenceActivity.java index e1061359d..146d4a789 100644 --- a/src/org/linphone/ConferenceActivity.java +++ b/src/org/linphone/ConferenceActivity.java @@ -28,6 +28,7 @@ import java.util.List; import org.linphone.LinphoneManagerWaitHelper.LinphoneManagerReadyListener; import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener; +import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreException; @@ -176,10 +177,8 @@ public class ConferenceActivity extends ListActivity implements return; } - Uri picture = LinphoneUtils.findPictureOfContact( - getContentResolver(), - currentCall.getRemoteAddress().getUserName(), - currentCall.getRemoteAddress().getDomain()); + Uri picture = LinphoneUtils.findUriPictureOfContactAndSetDisplayName( + currentCall.getRemoteAddress(), getContentResolver()); LinphoneUtils.setImagePictureFromUri(this, view, picture, R.drawable.unknown_person); view.setVisibility(VISIBLE); } @@ -441,16 +440,22 @@ public class ConferenceActivity extends ListActivity implements final LinphoneCall call = linphoneCalls.get(position); final LinphoneCall.State state = call.getState(); - String mainText = call.getRemoteAddress().getDisplayName(); - String username = call.getRemoteAddress().getUserName(); + LinphoneAddress address = call.getRemoteAddress(); + String mainText = address.getDisplayName(); + String complText; + if ((getResources().getBoolean(R.bool.show_full_remote_address_on_incoming_call))) { + complText = address.getUserName() + "@" + address.getDomain(); + } else { + complText = address.getUserName(); + } TextView mainTextView = (TextView) v.findViewById(R.id.name); TextView complTextView = (TextView) v.findViewById(R.id.address); if (TextUtils.isEmpty(mainText)) { - mainTextView.setText(username); + mainTextView.setText(complText); complTextView.setVisibility(View.GONE); } else { mainTextView.setText(mainText); - complTextView.setText(username); + complTextView.setText(complText); complTextView.setVisibility(View.VISIBLE); } @@ -536,9 +541,8 @@ public class ConferenceActivity extends ListActivity implements ImageView pictureView = (ImageView) v.findViewById(R.id.picture); if (numberOfCalls != 1) { - String domain = call.getRemoteAddress().getDomain(); // May be greatly sped up using a drawable cache - Uri uri = LinphoneUtils.findPictureOfContact(getContentResolver(), username, domain); + Uri uri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(call.getRemoteAddress(), getContentResolver()); LinphoneUtils.setImagePictureFromUri(ConferenceActivity.this, pictureView, uri, R.drawable.unknown_person); pictureView.setVisibility(VISIBLE); } else { diff --git a/src/org/linphone/ContactHelper.java b/src/org/linphone/ContactHelper.java new file mode 100644 index 000000000..62a7b8717 --- /dev/null +++ b/src/org/linphone/ContactHelper.java @@ -0,0 +1,258 @@ +/* +ContactHelper.java +Copyright (C) 2011 Belledonne Communications, Grenoble, France + +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 2 +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, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +package org.linphone; + +import org.linphone.core.LinphoneAddress; +import org.linphone.mediastream.Version; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.database.Cursor; +import android.net.Uri; +import android.telephony.PhoneNumberUtils; +import android.text.TextUtils; + +public final class ContactHelper { + + private String username; + private String domain; + private ContentResolver resolver; + + + private Uri foundPhotoUri; + public Uri getUri() { + return foundPhotoUri; + } + + + private String displayName; +// public String getDisplayName() { +// return displayName; +// } + + private LinphoneAddress address; + public ContactHelper(LinphoneAddress address, ContentResolver resolver) { + username = address.getUserName(); + domain = address.getDomain(); + this.resolver = resolver; + this.address = address; + } + + public boolean query() { + boolean succeeded; + if (Version.sdkAboveOrEqual(Version.API06_ECLAIR_20)) { + ContactHelperNew helper = new ContactHelperNew(); + succeeded = helper.queryNewContactAPI(); + } else { + succeeded = queryOldContactAPI(); + } + if (succeeded && !TextUtils.isEmpty(displayName)) { + address.setDisplayName(displayName); + } + return succeeded; + } + + + + public static boolean testPhotoUri(Cursor c) { + if (c == null) return false; + if (!c.moveToNext()) { + return false; + } + byte[] data = c.getBlob(0); + if (data == null) { + // TODO: simplify all this stuff + // which is here only to check that the + // photoUri really points to some data. + // Not retrieving the data now would be better. + return false; + } + return true; + } + + public static boolean testPhotoUriAndCloseCursor(Cursor c) { + boolean valid = testPhotoUri(c); + if (c != null) c.close(); + return valid; + } + + public static boolean testPhotoUri(ContentResolver resolver, Uri photoUriToTest, String photoCol) { + Cursor cursor = resolver.query(photoUriToTest, new String[]{photoCol}, null, null, null); + return testPhotoUriAndCloseCursor(cursor); + } + + + // OLD API + @SuppressWarnings("deprecation") + private final boolean queryOldContactAPI() { + String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username); + if (TextUtils.isEmpty(normalizedNumber)) { + // non phone username + return false; + } + String[] projection = {android.provider.Contacts.Phones.PERSON_ID, android.provider.Contacts.Phones.DISPLAY_NAME}; + String selection = android.provider.Contacts.Phones.NUMBER_KEY + "=" + normalizedNumber; + Cursor c = resolver.query(android.provider.Contacts.Phones.CONTENT_URI, projection, selection, null, null); + if (c == null) return false; + + while (c.moveToNext()) { + long id = c.getLong(c.getColumnIndex(android.provider.Contacts.Phones.PERSON_ID)); + Uri personUri = ContentUris.withAppendedId(android.provider.Contacts.People.CONTENT_URI, id); + Uri potentialPictureUri = Uri.withAppendedPath(personUri, android.provider.Contacts.Photos.CONTENT_DIRECTORY); + boolean valid = testPhotoUri(resolver, potentialPictureUri, android.provider.Contacts.Photos.DATA); + if (valid) { + displayName = c.getString(c.getColumnIndex(android.provider.Contacts.Phones.DISPLAY_NAME)); + foundPhotoUri = personUri; // hack (not returning pictureUri as it crashes when reading from it) + c.close(); + return true; + } + } + c.close(); + return false; + } + + // END OLD API + + + + + + + + + + + + // START NEW CONTACT API + + private class ContactHelperNew { + + + + private final boolean checkPhotosUris(ContentResolver resolver, Cursor c, String idCol, String nameCol) { + if (c == null) return false; + while (c.moveToNext()) { + long id = c.getLong(c.getColumnIndex(idCol)); + Uri contactUri = ContentUris.withAppendedId(android.provider.ContactsContract.Contacts.CONTENT_URI, id); + Uri photoUri = Uri.withAppendedPath(contactUri, android.provider.ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); + if (photoUri == null) { + return false; + } + String[] projection = {android.provider.ContactsContract.CommonDataKinds.Photo.PHOTO}; + Cursor photoCursor = resolver.query(photoUri, projection, null, null, null); + boolean valid = testPhotoUriAndCloseCursor(photoCursor); + if (valid) { + foundPhotoUri = photoUri; + displayName = c.getString(c.getColumnIndex(nameCol)); + c.close(); + return true; + } + } + c.close(); + return false; + } + + private final boolean queryNewContactAPI() { + String sipUri = username + "@" + domain; + + // Try first using sip field + Uri uri = android.provider.ContactsContract.Data.CONTENT_URI; + String[] projection = { + android.provider.ContactsContract.Data.CONTACT_ID, + android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME}; + String selection = new StringBuilder() + .append(android.provider.ContactsContract.CommonDataKinds.Im.DATA).append(" = ? AND ") + .append(android.provider.ContactsContract.Data.MIMETYPE) + .append(" = '") + .append(android.provider.ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE) + .append("' AND lower(") + .append(android.provider.ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL) + .append(") = 'sip'").toString(); + Cursor c = resolver.query(uri, projection, selection, new String[] {sipUri}, null); + boolean valid = checkPhotosUris(resolver, c, + android.provider.ContactsContract.Data.CONTACT_ID, + android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); + if (valid) return true; + + + // Then using custom SIP field + if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { + selection = new StringBuilder() + .append(android.provider.ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS) + .append(" = ? AND ") + .append(android.provider.ContactsContract.Data.MIMETYPE) + .append(" = '") + .append(android.provider.ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) + .append("'") + .toString(); + c = resolver.query(uri, projection, selection, new String[] {sipUri}, null); + valid = checkPhotosUris(resolver, c, + android.provider.ContactsContract.Data.CONTACT_ID, + android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); + if (valid) return true; + } + + // Finally using phone number + String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username); + if (TextUtils.isEmpty(normalizedNumber)) { + // non phone username + return false; + } + Uri lookupUri = Uri.withAppendedPath(android.provider.ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(username)); + projection = new String[]{ + android.provider.ContactsContract.PhoneLookup._ID, + android.provider.ContactsContract.PhoneLookup.NUMBER, + android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME}; + c = resolver.query(lookupUri, projection, null, null, null); + while (c.moveToNext()) { + long id = c.getLong(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup._ID)); + String enteredNumber = c.getString(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup.NUMBER)); + if (!normalizedNumber.equals(PhoneNumberUtils.getStrippedReversed(enteredNumber))) { + continue; + } + + Uri contactUri = ContentUris.withAppendedId(android.provider.ContactsContract.Contacts.CONTENT_URI, id); + Uri photoUri = Uri.withAppendedPath(contactUri, android.provider.ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); + if (photoUri == null) { + continue; + } + String[] photoProj = {android.provider.ContactsContract.CommonDataKinds.Photo.PHOTO}; + Cursor cursor = resolver.query(photoUri, photoProj, null, null, null); + valid = testPhotoUriAndCloseCursor(cursor); + if (valid) { + displayName = c.getString(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME)); + foundPhotoUri = photoUri; + c.close(); + return true; + } + } + c.close(); + return false; + } + + + } + + + + + + + +} diff --git a/src/org/linphone/ContactPickerActivityNew.java b/src/org/linphone/ContactPickerActivityNew.java index d85a2c5aa..82eafbceb 100644 --- a/src/org/linphone/ContactPickerActivityNew.java +++ b/src/org/linphone/ContactPickerActivityNew.java @@ -30,8 +30,6 @@ import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.PhoneLookup; -import android.telephony.PhoneNumberUtils; import android.text.TextUtils; @@ -55,35 +53,19 @@ public class ContactPickerActivityNew extends AbstractContactPickerActivity { @Override public Uri getPhotoUri(String id) { - return retrievePhotoUri(getContentResolver(), Long.parseLong(id)); + return retrievePhotoUriAndSetDisplayName(getContentResolver(), Long.parseLong(id)); } - private static Uri retrievePhotoUri(ContentResolver resolver, long id) { + private static Uri retrievePhotoUriAndSetDisplayName(ContentResolver resolver, long id) { Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id); Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY); if (photoUri == null) { return null; } - String[] projection = {ContactsContract.CommonDataKinds.Photo.PHOTO}; - Cursor cursor = resolver.query(photoUri, projection, null, null, null); - try { - if (cursor == null || !cursor.moveToNext()) { - return null; - } - byte[] data = cursor.getBlob(0); - if (data == null) { - // TODO: simplify all this stuff - // which is here only to check that the - // photoUri really points to some data. - // Not retrieving the data now would be better. - return null; - } + if (ContactHelper.testPhotoUri(resolver, photoUri, ContactsContract.CommonDataKinds.Photo.PHOTO)) { return photoUri; - } finally { - if (cursor != null) { - cursor.close(); - } } + return null; } protected List extractPhones(String id) { @@ -218,76 +200,4 @@ public class ContactPickerActivityNew extends AbstractContactPickerActivity { } - private static Uri retrievePhotoUri(ContentResolver resolver, Cursor c, String column) { - if (c == null) return null; - while (c.moveToNext()) { - long id = c.getLong(c.getColumnIndex(column)); - Uri picture = retrievePhotoUri(resolver, id); - if (picture != null) { - c.close(); - return picture; - } - } - c.close(); - return null; - } - public static Uri findUriPictureOfContact(ContentResolver resolver, String username, String domain) { - Uri retrievedPictureUri = null; - String sipUri = username + "@" + domain; - - // Try first using sip field - Uri uri = ContactsContract.Data.CONTENT_URI; - String[] projection = {ContactsContract.Data.CONTACT_ID}; - String selection = new StringBuilder() - .append(ContactsContract.CommonDataKinds.Im.DATA).append(" = ? AND ") - .append(ContactsContract.Data.MIMETYPE) - .append(" = '") - .append(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE) - .append("' AND lower(") - .append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL) - .append(") = 'sip'").toString(); - Cursor c = resolver.query(uri, projection, selection, new String[] {sipUri}, null); - retrievedPictureUri = retrievePhotoUri(resolver, c, ContactsContract.Data.CONTACT_ID); - if (retrievedPictureUri != null) return retrievedPictureUri; - - - // Then using custom SIP field - if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) { - selection = new StringBuilder() - .append(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS) - .append(" = ? AND ") - .append(ContactsContract.Data.MIMETYPE) - .append(" = '") - .append(ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE) - .append("'") - .toString(); - c = resolver.query(uri, projection, selection, new String[] {sipUri}, null); - retrievedPictureUri = retrievePhotoUri(resolver, c, ContactsContract.Data.CONTACT_ID); - if (retrievedPictureUri != null) return retrievedPictureUri; - } - - // Finally using phone number - String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username); - if (TextUtils.isEmpty(normalizedNumber)) { - // non phone username - return null; - } - Uri lookupUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(username)); - projection = new String[]{PhoneLookup._ID, PhoneLookup.NUMBER}; - c = resolver.query(lookupUri, projection, null, null, null); - while (c.moveToNext()) { - long id = c.getLong(c.getColumnIndex(PhoneLookup._ID)); - String enteredNumber = c.getString(c.getColumnIndex(PhoneLookup.NUMBER)); - if (!normalizedNumber.equals(PhoneNumberUtils.getStrippedReversed(enteredNumber))) { - continue; - } - Uri picture = retrievePhotoUri(resolver, id); - if (picture != null) { - c.close(); - return picture; - } - } - c.close(); - return null; - } } diff --git a/src/org/linphone/ContactPickerActivityOld.java b/src/org/linphone/ContactPickerActivityOld.java index e4be622cf..56347519e 100644 --- a/src/org/linphone/ContactPickerActivityOld.java +++ b/src/org/linphone/ContactPickerActivityOld.java @@ -19,7 +19,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. package org.linphone; import android.app.Activity; -import android.content.ContentResolver; import android.content.ContentUris; import android.content.Intent; import android.database.Cursor; @@ -27,9 +26,6 @@ import android.net.Uri; import android.os.Bundle; import android.provider.Contacts; import android.provider.Contacts.People; -import android.provider.Contacts.Photos; -import android.telephony.PhoneNumberUtils; -import android.text.TextUtils; @SuppressWarnings("deprecation") public class ContactPickerActivityOld extends Activity { @@ -51,29 +47,6 @@ public class ContactPickerActivityOld extends Activity { } - private Uri getPhotoUri(Uri photoUriToTest) { - return retrievePhotoUri(getContentResolver(), photoUriToTest); - } - - private static Uri retrievePhotoUri(ContentResolver resolver, Uri photoUriToTest) { - Cursor cursor = resolver.query(photoUriToTest, new String[]{Photos.DATA}, null, null, null); - try { - if (cursor == null || !cursor.moveToNext()) { - return null; - } - byte[] data = cursor.getBlob(0); - if (data == null) { - // TODO: simplify all this stuff - // which is here only to check that the - // photoUri really points to some data. - // Not retrieving the data now would be better. - return null; - } - return photoUriToTest; - } finally { - if (cursor != null) cursor.close(); - } - } protected void onActivityResult(int requestCode, int resultCode, Intent data) { @@ -92,8 +65,10 @@ public class ContactPickerActivityOld extends Activity { String lPhoneNo = lCur.getString(lCur.getColumnIndex(People.NUMBER)); long id = lCur.getLong(lCur.getColumnIndex(People._ID)); Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, id); - Uri potentialPictureUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY); - Uri pictureUri = getPhotoUri(potentialPictureUri); + Uri pictureUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY); + if (!ContactHelper.testPhotoUri(getContentResolver(), pictureUri, Contacts.Photos.CONTENT_DIRECTORY)) { + pictureUri = null; + } // FIXME surprisingly all this picture stuff doesn't seem to work DialerActivity.instance().setContactAddress(lPhoneNo, lName, pictureUri); } @@ -103,32 +78,4 @@ public class ContactPickerActivityOld extends Activity { } } - private static Uri retrievePhotoUriAndCloseC(ContentResolver resolver, Cursor c, String column) { - if (c == null) return null; - while (c.moveToNext()) { - long id = c.getLong(c.getColumnIndex(column)); - Uri personUri = ContentUris.withAppendedId(People.CONTENT_URI, id); - Uri potentialPictureUri = Uri.withAppendedPath(personUri, Contacts.Photos.CONTENT_DIRECTORY); - Uri pictureUri = retrievePhotoUri(resolver, potentialPictureUri); - if (pictureUri != null) { - c.close(); - return personUri; // FIXME, see LinphoneUtils - } - } - c.close(); - return null; - } - - public static Uri findUriPictureOfContact(ContentResolver resolver, String username, String domain) { - String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username); - if (TextUtils.isEmpty(normalizedNumber)) { - // non phone username - return null; - } - String[] projection = {Contacts.Phones.PERSON_ID}; - String selection = Contacts.Phones.NUMBER_KEY + "=" + normalizedNumber; - Cursor c = resolver.query(Contacts.Phones.CONTENT_URI, projection, selection, null, null); - - return retrievePhotoUriAndCloseC(resolver, c, Contacts.Phones.PERSON_ID); - } } diff --git a/src/org/linphone/IncomingCallActivity.java b/src/org/linphone/IncomingCallActivity.java index 2ce2e12bf..5384f073a 100644 --- a/src/org/linphone/IncomingCallActivity.java +++ b/src/org/linphone/IncomingCallActivity.java @@ -84,14 +84,18 @@ public class IncomingCallActivity extends Activity implements OnClickListener { return; } LinphoneAddress address = mCall.getRemoteAddress(); - String from = LinphoneManager.extractADisplayName(getResources(), address); - mNameView.setText(from); - mNumberView.setText(address.asStringUriOnly()); - String username = address.getUserName(); - String domain = address.getDomain(); // May be greatly sped up using a drawable cache - Uri uri = LinphoneUtils.findPictureOfContact(getContentResolver(), username, domain); + Uri uri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getContentResolver()); LinphoneUtils.setImagePictureFromUri(this, mPictureView, uri, R.drawable.unknown_person); + + // To be done after findUriPictureOfContactAndSetDisplayName called + mNameView.setText(address.getDisplayName()); + if (getResources().getBoolean(R.bool.show_full_remote_address_on_incoming_call)) { + mNumberView.setText(address.asStringUriOnly()); + } else { + mNumberView.setText(""); + } + } @Override diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 7279897fb..045c1188e 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -917,7 +917,7 @@ public final class LinphoneManager implements LinphoneCoreListener { return extractADisplayName(r, linphoneAddress); if (linphoneAddress != null) - return linphoneAddress.toString(); + return linphoneAddress.asStringUriOnly(); return r.getString(R.string.unknown_incoming_call_name); } diff --git a/src/org/linphone/LinphoneUtils.java b/src/org/linphone/LinphoneUtils.java index 1a3022927..e3d6c628e 100644 --- a/src/org/linphone/LinphoneUtils.java +++ b/src/org/linphone/LinphoneUtils.java @@ -23,6 +23,7 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import org.linphone.core.LinphoneAddress; import org.linphone.core.Log; import org.linphone.mediastream.Version; import org.linphone.mediastream.video.capture.hwconf.Hacks; @@ -81,12 +82,10 @@ public final class LinphoneUtils { * @param contact sip uri * @return url/uri of the resource */ - public static Uri findPictureOfContact(ContentResolver resolver, String username, String domain) { - if (Version.sdkAboveOrEqual(Version.API06_ECLAIR_20)) { - return ContactPickerActivityNew.findUriPictureOfContact(resolver, username, domain); - } else { - return ContactPickerActivityOld.findUriPictureOfContact(resolver, username, domain); - } + public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver resolver) { + ContactHelper helper = new ContactHelper(address, resolver); + helper.query(); + return helper.getUri(); } public static Bitmap downloadBitmap(Uri uri) {