diff --git a/build.gradle b/build.gradle index e86b4947a..c341bf0f5 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ dependencies { } android { - compileSdkVersion 19 + compileSdkVersion 22 buildToolsVersion "20.0.0" sourceSets { diff --git a/liblinphone_tester/custom_rules.xml b/liblinphone_tester/custom_rules.xml index 6f643e8e6..0f2e0d9c0 100644 --- a/liblinphone_tester/custom_rules.xml +++ b/liblinphone_tester/custom_rules.xml @@ -55,7 +55,7 @@ - + @@ -73,6 +73,6 @@ - + diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 57cd2d29b..d328d0d43 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -393,7 +393,7 @@ Cet assistant va télécharger une configuration existante. addresse où télécharger la configuration La configuration téléchargée ne contient pas votre compte. Veuillez le remplir. - Votre nom d\'utilisateur sera %s (les majuscules sont interdites). Acceptez-vous ? + Votre nom d\'utilisateur sera %s.\r\n\r\nIl peut différer de celui que vous avez choisi afin de remplir certains critères nécessaires.\r\nAcceptez-vous ? Assistant de création de compte Accepter Refuser diff --git a/res/values/non_localizable_custom.xml b/res/values/non_localizable_custom.xml index 16fe84ca0..655403e73 100644 --- a/res/values/non_localizable_custom.xml +++ b/res/values/non_localizable_custom.xml @@ -33,6 +33,7 @@ false true true + true false diff --git a/res/values/strings.xml b/res/values/strings.xml index 863a82ac8..b55f1c215 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -396,7 +396,7 @@ This assistant will download an existing configuration. provisioning url The configuration you downloaded doesn\'t include your account. Please fill it in. - Your username will be %s (uppercase characters are not allowed). Do you accept ? + Your username will be %s.\r\n\r\nIt may differ from what you entered to match some requierements.\r\nDo you accept ? Account setup assistant Accept Deny diff --git a/src/org/linphone/ChatActivity.java b/src/org/linphone/ChatActivity.java index f37ec58cb..b486f4901 100644 --- a/src/org/linphone/ChatActivity.java +++ b/src/org/linphone/ChatActivity.java @@ -34,6 +34,7 @@ public class ChatActivity extends FragmentActivity { extras.putString("SipUri", getIntent().getExtras().getString("SipUri")); extras.putString("DisplayName", getIntent().getExtras().getString("DisplayName")); extras.putString("PictureUri", getIntent().getExtras().getString("PictureUri")); + extras.putString("ThumbnailUri", getIntent().getExtras().getString("ThumbnailUri")); ChatFragment fragment = new ChatFragment(); fragment.setArguments(extras); diff --git a/src/org/linphone/ChatFragment.java b/src/org/linphone/ChatFragment.java index 2820c6705..10ef4ac92 100644 --- a/src/org/linphone/ChatFragment.java +++ b/src/org/linphone/ChatFragment.java @@ -20,24 +20,29 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Calendar; import java.util.List; + import org.linphone.compatibility.Compatibility; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneBuffer; import org.linphone.core.LinphoneChatMessage; import org.linphone.core.LinphoneChatMessage.LinphoneChatMessageListener; -import org.linphone.core.LinphoneChatMessage.State; import org.linphone.core.LinphoneChatRoom; import org.linphone.core.LinphoneContent; import org.linphone.core.LinphoneCore; +import org.linphone.core.LinphoneChatMessage.State; +import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.LinphoneCoreListenerBase; import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithShadow; import org.linphone.ui.BubbleChat; +import android.support.v4.content.CursorLoader; import android.annotation.SuppressLint; import android.app.Activity; @@ -52,10 +57,10 @@ import android.graphics.Rect; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Environment; import android.os.Parcelable; import android.provider.MediaStore; import android.support.v4.app.Fragment; -import android.support.v4.content.CursorLoader; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; @@ -84,6 +89,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC private static final int MENU_DELETE_MESSAGE = 0; private static final int MENU_COPY_TEXT = 6; private static final int MENU_RESEND_MESSAGE = 7; + private static final int SIZE_MAX = 2048; private LinphoneChatRoom chatRoom; private String sipUri; @@ -334,6 +340,20 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC } private void displayChatHeader(String displayName, String pictureUri) { + LinphoneAddress lAddress; + try { + lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), lAddress); + if (contact != null) { + LinphoneUtils.setImagePictureFromUri(getActivity(), contactPicture.getView(), contact.getPhotoUri(), contact.getThumbnailUri(), R.drawable.unknown_small); + + } else { + contactPicture.setImageResource(R.drawable.unknown_small); + } + } catch (LinphoneCoreException e) { + e.printStackTrace(); + } + if (displayName == null && getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) { contactName.setText(LinphoneUtils.getUsernameFromAddress(sipUri)); } else if (displayName == null) { @@ -342,11 +362,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC contactName.setText(displayName); } - if (pictureUri != null) { - LinphoneUtils.setImagePictureFromUri(getActivity(), contactPicture.getView(), Uri.parse(pictureUri), R.drawable.unknown_small); - } else { - contactPicture.setImageResource(R.drawable.unknown_small); - } } public void changeDisplayedChat(String newSipUri, String displayName, String pictureUri) { @@ -526,6 +541,14 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC @Override protected byte[] doInBackground(Bitmap... params) { Bitmap bm = params[0]; + + if (bm.getWidth() > bm.getHeight() && bm.getWidth() > SIZE_MAX) { + bm = Bitmap.createScaledBitmap(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth(), false); + } else if (bm.getHeight() > bm.getWidth() && bm.getHeight() > SIZE_MAX) { + + bm = Bitmap.createScaledBitmap(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX, false); + } + ByteArrayOutputStream stream = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, stream); byte[] byteArray = stream.toByteArray(); @@ -601,6 +624,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC private void pickImage() { List cameraIntents = new ArrayList(); Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name) + Calendar.getInstance().getTime()); + imageToUploadUri = Uri.fromFile(file); + captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri); cameraIntents.add(captureIntent); Intent galleryIntent = new Intent(); diff --git a/src/org/linphone/ChatListFragment.java b/src/org/linphone/ChatListFragment.java index 9b9dc6116..e6a8b7e8d 100644 --- a/src/org/linphone/ChatListFragment.java +++ b/src/org/linphone/ChatListFragment.java @@ -356,7 +356,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte Log.e("Chat view cannot parse address",e); return view; } - Contact lContact = ContactsManager.getInstance().findContactWithAddress(address); + Contact lContact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address); String message = ""; if (useNativeAPI) { @@ -365,7 +365,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte if (history != null && history.length > 0) { for (int i = history.length - 1; i >= 0; i--) { LinphoneChatMessage msg = history[i]; - if (msg.getText() != null && msg.getText().length() > 0) { + if (msg.getText() != null && msg.getText().length() > 0 && msg.getFileTransferInformation() == null) { message = msg.getText(); break; } diff --git a/src/org/linphone/Contact.java b/src/org/linphone/Contact.java index 4352bc21d..bbb4ebf13 100644 --- a/src/org/linphone/Contact.java +++ b/src/org/linphone/Contact.java @@ -37,6 +37,7 @@ public class Contact implements Serializable { private String id; private String name; private transient Uri photoUri; + private transient Uri thumbnailUri; private transient Bitmap photo; private List numbersOrAddresses; private boolean hasFriends; @@ -46,23 +47,26 @@ public class Contact implements Serializable { this.id = id; this.name = name; this.photoUri = null; + this.thumbnailUri = null; this.hasFriends = false; } - public Contact(String id, String name, Uri photo) { + public Contact(String id, String name, Uri photo, Uri thumbnail) { super(); this.id = id; this.name = name; this.photoUri = photo; + this.thumbnailUri = thumbnail; this.photo = null; this.hasFriends = false; } - public Contact(String id, String name, Uri photo, Bitmap picture) { + public Contact(String id, String name, Uri photo, Uri thumbnail, Bitmap picture) { super(); this.id = id; this.name = name; this.photoUri = photo; + this.thumbnailUri = thumbnail; this.photo = picture; this.hasFriends = false; } @@ -83,6 +87,10 @@ public class Contact implements Serializable { public Uri getPhotoUri() { return photoUri; } + + public Uri getThumbnailUri() { + return thumbnailUri; + } public Bitmap getPhoto() { return photo; @@ -96,7 +104,7 @@ public class Contact implements Serializable { public void refresh(ContentResolver cr) { this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr); - for(LinphoneFriend friend : LinphoneManager.getLc().getFriendList()) { + for(LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) { if (friend.getRefKey().equals(id)) { hasFriends = true; this.numbersOrAddresses.add(friend.getAddress().asStringUriOnly()); diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java index bdfb75f2f..9fbc50d84 100644 --- a/src/org/linphone/ContactsManager.java +++ b/src/org/linphone/ContactsManager.java @@ -26,11 +26,14 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; + import org.linphone.compatibility.Compatibility; import org.linphone.core.LinphoneAddress; +import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.LinphoneFriend; +import org.linphone.core.LinphoneProxyConfig; import org.linphone.mediastream.Log; import java.util.ArrayList; @@ -101,7 +104,7 @@ public class ContactsManager { } //Contacts - public void createNewContact(ArrayList ops, String firstName, String lastName){ + public void createNewContact(ArrayList ops, String firstName, String lastName) { int contactID = 0; ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) @@ -117,7 +120,7 @@ public class ContactsManager { .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName) .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, getDisplayName(firstName,lastName)) + .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, getDisplayName(firstName, lastName)) .build() ); } @@ -125,8 +128,8 @@ public class ContactsManager { public void updateExistingContact(ArrayList ops, Contact contact, String firstName, String lastName) { if (getDisplayName(firstName, lastName) != null) { - String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'" ; - String[] args = new String[] { String.valueOf(contact.getID()) }; + String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'"; + String[] args = new String[]{String.valueOf(contact.getID())}; ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) .withSelection(select, args) @@ -145,12 +148,13 @@ public class ContactsManager { } LinphoneFriend friend = LinphoneCoreFactory.instance().createLinphoneFriend(sipUri); - if(friend != null) { + if (friend != null) { friend.edit(); + friend.enableSubscribes(false); friend.setRefKey(contact.getID()); friend.done(); try { - LinphoneManager.getLc().addFriend(friend); + LinphoneManager.getLcIfManagerNotDestroyedOrNull().addFriend(friend); return true; } catch (LinphoneCoreException e) { e.printStackTrace(); @@ -170,8 +174,8 @@ public class ContactsManager { oldSipUri = "sip:" + oldSipUri; } - LinphoneFriend friend = LinphoneManager.getLc().findFriendByAddress(oldSipUri); - if(friend != null) { + LinphoneFriend friend = LinphoneManager.getLcIfManagerNotDestroyedOrNull().findFriendByAddress(oldSipUri); + if (friend != null) { friend.edit(); try { friend.setAddress(LinphoneCoreFactory.instance().createLinphoneAddress(newSipUri)); @@ -187,36 +191,59 @@ public class ContactsManager { sipUri = "sip:" + sipUri; } - LinphoneFriend friend = LinphoneManager.getLc().findFriendByAddress(sipUri); + LinphoneFriend friend = LinphoneManager.getLcIfManagerNotDestroyedOrNull().findFriendByAddress(sipUri); if (friend != null) { - LinphoneManager.getLc().removeFriend(friend); + LinphoneManager.getLcIfManagerNotDestroyedOrNull().removeFriend(friend); return true; } return false; } public void removeAllFriends(Contact contact) { - for(LinphoneFriend friend : LinphoneManager.getLc().getFriendList()){ - if(friend.getRefKey().equals(contact.getID())) { - LinphoneManager.getLc().removeFriend(friend); + for (LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) { + if (friend.getRefKey().equals(contact.getID())) { + LinphoneManager.getLcIfManagerNotDestroyedOrNull().removeFriend(friend); } } } public Contact findContactWithDisplayName(String displayName) { - String[] projection = { ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME }; + String[] projection = {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME}; String selection = new StringBuilder() .append(ContactsContract.Data.DISPLAY_NAME) .append(" = ?").toString(); - Cursor c = contentResolver.query(ContactsContract.Data.CONTENT_URI,projection,selection, + Cursor c = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, new String[]{displayName}, null); if (c != null) { if (c.moveToFirst()) { - Contact contact = Compatibility.getContact(contentResolver,c,c.getPosition()); + Contact contact = Compatibility.getContact(contentResolver, c, c.getPosition()); c.close(); - if(contact != null) { + if (contact != null) { + return contact; + } else { + return null; + } + } + c.close(); + } + return null; + } + + public Contact getContact(String id, ContentResolver contentResolver){ + String[] projection = {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME}; + String selection = new StringBuilder() + .append(ContactsContract.Data.CONTACT_ID) + .append(" = ?").toString(); + + Cursor c = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, new String[]{id}, null); + if(c!=null){ + if (c.moveToFirst()) { + Contact contact = Compatibility.getContact(contentResolver, c, c.getPosition()); + c.close(); + + if (contact != null) { return contact; } else { return null; @@ -229,8 +256,11 @@ public class ContactsManager { public List getContactsId(){ List ids = new ArrayList(); - if(LinphoneManager.getLc().getFriendList() == null) return null; - for(LinphoneFriend friend : LinphoneManager.getLc().getFriendList()) { + if(LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList() == null) return null; + for(LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) { + friend.edit(); + friend.enableSubscribes(false); + friend.done(); if(!ids.contains(friend.getRefKey())){ ids.add(friend.getRefKey()); } @@ -241,15 +271,18 @@ public class ContactsManager { //End linphone Friend public boolean removeContactTagIsNeeded(Contact contact){ - contact.refresh(contentResolver); - boolean onlyNumbers = true; - for(String address: contact.getNumbersOrAddresses()){ - if(LinphoneUtils.isSipAddress(address)){ - onlyNumbers = false; + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + LinphoneProxyConfig lpc = lc.createProxyConfig(); + contact.refresh(contentResolver); + for (String address : contact.getNumbersOrAddresses()) { + if (!lpc.isPhoneNumber(address)) { + return false; + } } + return true; } - - return onlyNumbers; + return false; } public void removeLinphoneContactTag(Contact contact){ @@ -270,12 +303,84 @@ public class ContactsManager { } } - public Contact findContactWithAddress(LinphoneAddress address){ - for(Contact contact : contactList){ - if(contact.getNumbersOrAddresses().contains(address.asStringUriOnly()) || contact.getNumbersOrAddresses().contains(address.getUserName())){ - return contact; + private Contact checkPhoneQueryResult(ContentResolver contentResolver, Cursor c, String columnPhone, String columnId, String username) { + boolean contactFound = false; + + if (c != null) { + while (!contactFound && c.moveToNext()) { + String phone = c.getString(c.getColumnIndex(columnPhone)); + if (phone.equals(username)) { + contactFound = true; + } else { + String normalizedUsername = null; + LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); + if (lc != null) { + LinphoneProxyConfig lpc = lc.getDefaultProxyConfig(); + if (lpc != null) { + normalizedUsername = lpc.normalizePhoneNumber(phone); + } + } + + if (normalizedUsername != null && normalizedUsername.equals(username)) { + contactFound = true; + } + } + + if(contactFound){ + Contact contact = getContact(c.getString(c.getColumnIndex(columnId)), contentResolver); + c.close(); + return contact; + } + } + c.close(); + } + return null; + } + + public Contact findContactWithAddress(ContentResolver contentResolver, LinphoneAddress address){ + String sipUri = address.asStringUriOnly(); + if (sipUri.startsWith("sip:")) + sipUri = sipUri.substring(4); + + if(LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList() != null && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList().length > 0) { + for (LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) { + if (friend.getAddress().equals(address)) { + return getContact(friend.getRefKey(), contentResolver); + } } } + + //Find Sip address + Contact contact; + String [] projection = new String[] {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME}; + String selection = new StringBuilder() + .append(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS) + .append(" = ?").toString(); + + Cursor cur = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, + new String[]{sipUri}, null); + if (cur != null) { + if (cur.moveToFirst()) { + contact = Compatibility.getContact(contentResolver, cur, cur.getPosition()); + cur.close(); + + if (contact != null) { + return contact; + } + } + cur.close(); + } + + //Find number + Uri lookupUri = Uri.withAppendedPath(android.provider.ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.getUserName())); + projection = new String[] {ContactsContract.PhoneLookup._ID,ContactsContract.PhoneLookup.NUMBER,ContactsContract.PhoneLookup.DISPLAY_NAME }; + Cursor c = contentResolver.query(lookupUri, projection, null, null, null); + contact = checkPhoneQueryResult(contentResolver, c, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup._ID, address.getUserName()); + + if (contact != null) { + return contact; + } + return null; } @@ -425,7 +530,7 @@ public class ContactsManager { contact.refresh(contentResolver); //Add tag to Linphone contact if it not existed - if (LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) { + if (LinphoneActivity.isInstanciated() && LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) { if (!isContactHasLinphoneTag(contact, contentResolver)) { Compatibility.createLinphoneContactTag(context, contentResolver, contact, findRawContactID(contentResolver, String.valueOf(contact.getID()))); @@ -438,13 +543,12 @@ public class ContactsManager { if (contactCursor != null) { for (int i = 0; i < contactCursor.getCount(); i++) { Contact contact = Compatibility.getContact(contentResolver, contactCursor, i); - if (contact == null) continue; //Remove linphone contact tag if the contact has no sip address - if (LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) { - if (removeContactTagIsNeeded(contact) && isContactHasLinphoneTag(contact, contentResolver)) { + if (LinphoneActivity.isInstanciated() && LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) { + if (removeContactTagIsNeeded(contact) && findRawLinphoneContactID(contact.getID()) != null) { removeLinphoneContactTag(contact); } } diff --git a/src/org/linphone/EditContactFragment.java b/src/org/linphone/EditContactFragment.java index eed7b0f70..b63bd5cad 100644 --- a/src/org/linphone/EditContactFragment.java +++ b/src/org/linphone/EditContactFragment.java @@ -102,6 +102,7 @@ public class EditContactFragment extends Fragment { try { getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); addLinphoneFriendIfNeeded(); + removeLinphoneTagIfNeeded(); contactsManager.prepareContactsInBackground(); } catch (Exception e) { e.printStackTrace(); @@ -415,6 +416,21 @@ public class EditContactFragment extends Fragment { } } } + + private void removeLinphoneTagIfNeeded(){ + if(!isNewContact) { + boolean areAllSipFielsEmpty = true; + for (NewOrUpdatedNumberOrAddress nounoa : numbersAndAddresses) { + if (!nounoa.isSipAddress && (nounoa.oldNumberOrAddress != null && !nounoa.oldNumberOrAddress.equals("") || nounoa.newNumberOrAddress != null && !nounoa.newNumberOrAddress.equals(""))) { + areAllSipFielsEmpty = false; + break; + } + } + if (areAllSipFielsEmpty && contactsManager.findRawLinphoneContactID(contact.getID()) != null) { + contactsManager.removeLinphoneContactTag(contact); + } + } + } class NewOrUpdatedNumberOrAddress { private String oldNumberOrAddress; diff --git a/src/org/linphone/HistoryDetailFragment.java b/src/org/linphone/HistoryDetailFragment.java index 7d0eae6d8..ceea76b21 100644 --- a/src/org/linphone/HistoryDetailFragment.java +++ b/src/org/linphone/HistoryDetailFragment.java @@ -23,6 +23,7 @@ import java.util.Calendar; import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneCoreException; import org.linphone.core.LinphoneCoreFactory; +import org.linphone.mediastream.Log; import org.linphone.ui.AvatarWithShadow; import android.annotation.SuppressLint; @@ -112,12 +113,12 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { LinphoneAddress lAddress; try { lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); - Contact contact = ContactsManager.getInstance().findContactWithAddress(lAddress); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), lAddress); if (contact != null) { - LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),contact.getPhotoUri(), R.drawable.unknown_small); + LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),contact.getPhotoUri(), contact.getThumbnailUri(), R.drawable.unknown_small); view.findViewById(R.id.addContactRow).setVisibility(View.GONE); } else { - LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),null ,R.drawable.unknown_small); + LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),null, null ,R.drawable.unknown_small); } } catch (LinphoneCoreException e) { e.printStackTrace(); diff --git a/src/org/linphone/HistoryFragment.java b/src/org/linphone/HistoryFragment.java index 6f7c2ee97..3a3b87ddc 100644 --- a/src/org/linphone/HistoryFragment.java +++ b/src/org/linphone/HistoryFragment.java @@ -178,7 +178,7 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil address = log.getTo(); } - Contact contact = ContactsManager.getInstance().findContactWithAddress(address); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address); String sipUri = address.asStringUriOnly(); if (contact == null) { if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) { diff --git a/src/org/linphone/HistorySimpleFragment.java b/src/org/linphone/HistorySimpleFragment.java index 266a84d78..aa5abdeff 100644 --- a/src/org/linphone/HistorySimpleFragment.java +++ b/src/org/linphone/HistorySimpleFragment.java @@ -392,7 +392,7 @@ public class HistorySimpleFragment extends Fragment implements OnClickListener, callDirection.setImageBitmap(outgoingCall); } - Contact c = ContactsManager.getInstance().findContactWithAddress(address); + Contact c = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address); String displayName = null; final String sipUri = address.asStringUriOnly(); if(c != null){ diff --git a/src/org/linphone/InCallActivity.java b/src/org/linphone/InCallActivity.java index 052cfd18c..181d1e677 100644 --- a/src/org/linphone/InCallActivity.java +++ b/src/org/linphone/InCallActivity.java @@ -1299,11 +1299,11 @@ public class InCallActivity extends FragmentActivity implements OnClickListener // Image Row LinearLayout imageView = (LinearLayout) inflater.inflate(R.layout.active_call_image_row, container, false); - Contact contact = ContactsManager.getInstance().findContactWithAddress(lAddress); + Contact contact = ContactsManager.getInstance().findContactWithAddress(imageView.getContext().getContentResolver(), lAddress); if(contact != null) { - displayOrHideContactPicture(imageView, contact.getPhotoUri(), false); + displayOrHideContactPicture(imageView, contact.getPhotoUri(), contact.getThumbnailUri(), false); } else { - displayOrHideContactPicture(imageView, null, false); + displayOrHideContactPicture(imageView, null, null, false); } callsList.addView(imageView); @@ -1326,7 +1326,7 @@ public class InCallActivity extends FragmentActivity implements OnClickListener private void setContactName(LinearLayout callView, LinphoneAddress lAddress, String sipUri, Resources resources) { TextView contact = (TextView) callView.findViewById(R.id.contactNameOrNumber); - Contact lContact = ContactsManager.getInstance().findContactWithAddress(lAddress); + Contact lContact = ContactsManager.getInstance().findContactWithAddress(callView.getContext().getContentResolver(), lAddress); if (lContact == null) { if (resources.getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) { contact.setText(lAddress.getUserName()); @@ -1366,10 +1366,10 @@ public class InCallActivity extends FragmentActivity implements OnClickListener return isCallPaused || isInConference; } - private void displayOrHideContactPicture(LinearLayout callView, Uri pictureUri, boolean hide) { + private void displayOrHideContactPicture(LinearLayout callView, Uri pictureUri, Uri thumbnailUri, boolean hide) { AvatarWithShadow contactPicture = (AvatarWithShadow) callView.findViewById(R.id.contactPicture); if (pictureUri != null) { - LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture.getView(), Uri.parse(pictureUri.toString()), R.drawable.unknown_small); + LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture.getView(), Uri.parse(pictureUri.toString()), thumbnailUri, R.drawable.unknown_small); } callView.setVisibility(hide ? View.GONE : View.VISIBLE); } diff --git a/src/org/linphone/IncomingCallActivity.java b/src/org/linphone/IncomingCallActivity.java index fa04b0ad9..713c009d0 100644 --- a/src/org/linphone/IncomingCallActivity.java +++ b/src/org/linphone/IncomingCallActivity.java @@ -124,8 +124,9 @@ public class IncomingCallActivity extends Activity implements LinphoneSliderTrig } LinphoneAddress address = mCall.getRemoteAddress(); // May be greatly sped up using a drawable cache - Contact contact = ContactsManager.getInstance().findContactWithAddress(address); - LinphoneUtils.setImagePictureFromUri(this, mPictureView.getView(), contact != null ? contact.getPhotoUri() : null, R.drawable.unknown_small); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), address); + LinphoneUtils.setImagePictureFromUri(this, mPictureView.getView(), contact != null ? contact.getPhotoUri() : null, + contact != null ? contact.getThumbnailUri() : null, R.drawable.unknown_small); // To be done after findUriPictureOfContactAndSetDisplayName called mNameView.setText(contact != null ? contact.getName() : ""); diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index 3f3990067..2b0e8bf18 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -518,7 +518,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene Log.e("Cannot display history details",e); return; } - Contact c = ContactsManager.getInstance().findContactWithAddress(lAddress); + Contact c = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), lAddress); String displayName = c != null ? c.getName() : null; String pictureUri = c != null && c.getPhotoUri() != null ? c.getPhotoUri().toString() : null; @@ -611,9 +611,15 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene Log.e("Cannot display chat",e); return; } - Contact contact = ContactsManager.getInstance().findContactWithAddress(lAddress); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), lAddress); String displayName = contact != null ? contact.getName() : null; - String pictureUri = contact != null && contact.getPhotoUri() != null ? contact.getPhotoUri().toString() : null; + + String pictureUri = null; + String thumbnailUri = null; + if(contact != null && contact.getPhotoUri() != null){ + pictureUri = contact.getPhotoUri().toString(); + thumbnailUri = contact.getThumbnailUri().toString(); + } if (isTablet()){ if (currentFragment == FragmentsAvailable.CHATLIST || currentFragment == FragmentsAvailable.CHAT){ @@ -624,9 +630,10 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene } else { Bundle extras = new Bundle(); extras.putString("SipUri", sipUri); - if (lAddress.getDisplayName() != null) { + if (contact != null) { extras.putString("DisplayName", displayName); extras.putString("PictureUri", pictureUri); + extras.putString("ThumbnailUri", thumbnailUri); } changeCurrentFragment(FragmentsAvailable.CHAT, extras); } @@ -639,7 +646,8 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene intent.putExtra("SipUri", sipUri); if (contact != null) { intent.putExtra("DisplayName", contact.getName()); - intent.putExtra("PictureUri", contact.getPhotoUri()); + intent.putExtra("PictureUri", pictureUri); + intent.putExtra("ThumbnailUri", thumbnailUri); } startOrientationSensor(); startActivityForResult(intent, CHAT_ACTIVITY); diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 78e9ec489..3ebd4d8c8 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -715,7 +715,7 @@ public class LinphoneManager implements LinphoneCoreListener { } try { - Contact contact = ContactsManager.getInstance().findContactWithAddress(from); + Contact contact = ContactsManager.getInstance().findContactWithAddress(mServiceContext.getContentResolver(),from); if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat__message_notification)) { if(contact != null) { LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), contact.getName(), textMessage); diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java index 9d9c93110..45284019d 100644 --- a/src/org/linphone/LinphoneService.java +++ b/src/org/linphone/LinphoneService.java @@ -312,7 +312,7 @@ public final class LinphoneService extends Service { LinphoneAddress address = LinphoneCoreFactory.instance().createLinphoneAddress(userName,domain,null); address.setDisplayName(displayName); - Contact contact = ContactsManager.getInstance().findContactWithAddress(address); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), address); Uri pictureUri = contact != null ? contact.getPhotoUri() : null; Bitmap bm = null; try { @@ -390,7 +390,7 @@ public final class LinphoneService extends Service { Uri pictureUri = null; try { - Contact contact = ContactsManager.getInstance().findContactWithAddress(LinphoneCoreFactory.instance().createLinphoneAddress(fromSipUri)); + Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), LinphoneCoreFactory.instance().createLinphoneAddress(fromSipUri)); if (contact != null) pictureUri = contact.getPhotoUri(); } catch (LinphoneCoreException e1) { diff --git a/src/org/linphone/LinphoneUtils.java b/src/org/linphone/LinphoneUtils.java index be4e956dd..e0491885f 100644 --- a/src/org/linphone/LinphoneUtils.java +++ b/src/org/linphone/LinphoneUtils.java @@ -56,6 +56,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; +import android.provider.MediaStore; import android.telephony.TelephonyManager; import android.util.TypedValue; import android.view.KeyEvent; @@ -156,7 +157,7 @@ public final class LinphoneUtils { } - public static void setImagePictureFromUri(Context c, ImageView view, Uri uri, int notFoundResource) { + public static void setImagePictureFromUri(Context c, ImageView view, Uri uri, Uri tUri, int notFoundResource) { if (uri == null) { view.setImageResource(notFoundResource); return; @@ -167,7 +168,17 @@ public final class LinphoneUtils { view.setImageBitmap(bm); } else { if (Version.sdkAboveOrEqual(Version.API06_ECLAIR_201)) { - view.setImageURI(uri); + Bitmap bm = null; + try { + bm = MediaStore.Images.Media.getBitmap(c.getContentResolver(),uri); + } catch (IOException e) { + if(tUri != null){ + view.setImageURI(tUri); + } + } + if(bm != null) { + view.setImageBitmap(bm); + } } else { @SuppressWarnings("deprecation") Bitmap bitmap = android.provider.Contacts.People.loadContactPhoto(c, uri, notFoundResource, null); diff --git a/src/org/linphone/compatibility/ApiFivePlus.java b/src/org/linphone/compatibility/ApiFivePlus.java index 5fcc12100..11ce8f0db 100644 --- a/src/org/linphone/compatibility/ApiFivePlus.java +++ b/src/org/linphone/compatibility/ApiFivePlus.java @@ -216,7 +216,8 @@ public class ApiFivePlus { String id = cursor.getString(cursor.getColumnIndex(Data.CONTACT_ID)); String name = getContactDisplayName(cursor); - Uri photo = getContactPictureUri(id); + Uri thumbnail = getContactPictureUri(id); + Uri photo = getContactPhotoUri(id); InputStream input = getContactPictureInputStream(cr, id); Contact contact; @@ -228,7 +229,7 @@ public class ApiFivePlus { try { bm = BitmapFactory.decodeStream(input); } catch (OutOfMemoryError oome) {} - contact = new Contact(id, name, photo, bm); + contact = new Contact(id, name, photo, thumbnail, bm); } return contact; @@ -248,6 +249,11 @@ public class ApiFivePlus { } private static Uri getContactPictureUri(String id) { + Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id)); + return Uri.withAppendedPath(person, Contacts.Photo.CONTENT_DIRECTORY); + } + + private static Uri getContactPhotoUri(String id) { Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id)); return Uri.withAppendedPath(person, Contacts.Photo.DISPLAY_PHOTO); } diff --git a/src/org/linphone/setup/WizardFragment.java b/src/org/linphone/setup/WizardFragment.java index 271206504..571f56bdb 100644 --- a/src/org/linphone/setup/WizardFragment.java +++ b/src/org/linphone/setup/WizardFragment.java @@ -24,6 +24,7 @@ import java.util.regex.Pattern; import org.linphone.LinphoneManager; import org.linphone.LinphoneService; import org.linphone.R; +import org.linphone.core.LinphoneProxyConfig; import android.accounts.Account; import android.accounts.AccountManager; @@ -65,6 +66,17 @@ public class WizardFragment extends Fragment { private char[] acceptedChars = new char[]{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '_', '-' }; + private char[] acceptedCharsForPhoneNumbers = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+' }; + private String inputFilterCharacters; + + private String getUsername() { + String username = this.username.getText().toString(); + if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) { + LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig(); + username = lpc.normalizePhoneNumber(username); + } + return username.toLowerCase(Locale.getDefault()); + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -73,12 +85,17 @@ public class WizardFragment extends Fragment { username = (EditText) view.findViewById(R.id.setup_username); ImageView usernameOkIV = (ImageView) view.findViewById(R.id.setup_username_ok); addXMLRPCUsernameHandler(username, usernameOkIV); + + inputFilterCharacters = new String(acceptedChars); + if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) { + inputFilterCharacters = new String(acceptedCharsForPhoneNumbers); + } InputFilter filter = new InputFilter(){ @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { if (end > start) { for (int index = start; index < end; index++) { - if (!new String(acceptedChars).contains(String.valueOf(source.charAt(index)))) { + if (!inputFilterCharacters.contains(String.valueOf(source.charAt(index)))) { return ""; } } @@ -110,20 +127,16 @@ public class WizardFragment extends Fragment { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { - createAccount(username.getText().toString().toLowerCase(Locale.getDefault()), password.getText().toString(), email.getText().toString(), false); + createAccount(getUsername(), password.getText().toString(), email.getText().toString(), false); } }); builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { } }); - if(!username.getText().toString().equals(username.getText().toString().toLowerCase(Locale.getDefault()))){ - builder.setMessage(getString(R.string.setup_confirm_username).replace("%s", username.getText().toString().toLowerCase(Locale.getDefault()))); - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - createAccount(username.getText().toString().toLowerCase(Locale.getDefault()), password.getText().toString(), email.getText().toString(), false); - } + builder.setMessage(getString(R.string.setup_confirm_username).replace("%s", getUsername())); + AlertDialog dialog = builder.create(); + dialog.show(); } }); @@ -143,7 +156,11 @@ public class WizardFragment extends Fragment { } private boolean isUsernameCorrect(String username) { - return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$"); + if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) { + return username.matches("^(\\+)?(\\d-)?(\\d{3}-)?(\\d{3}-)?\\d{4,}$"); + } else { + return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$"); + } } private void isUsernameRegistred(String username, final ImageView icon) { @@ -278,6 +295,10 @@ public class WizardFragment extends Fragment { usernameOk = false; String username = field.getText().toString().toLowerCase(Locale.getDefault()); if (isUsernameCorrect(username)) { + if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) { + LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig(); + username = lpc.normalizePhoneNumber(username); + } isUsernameRegistred(username, icon); } else { errorMessage.setText(R.string.wizard_username_incorrect); diff --git a/src/org/linphone/ui/BubbleChat.java b/src/org/linphone/ui/BubbleChat.java index 0c768fea2..b75169fd7 100644 --- a/src/org/linphone/ui/BubbleChat.java +++ b/src/org/linphone/ui/BubbleChat.java @@ -95,6 +95,7 @@ public class BubbleChat { private ImageView statusView; private LinphoneChatMessage nativeMessage; private LinphoneChatMessage.LinphoneChatMessageListener fileTransferListener; + private static final int SIZE_MAX = 2048; @SuppressLint("InflateParams") public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneChatMessage.LinphoneChatMessageListener listener) { @@ -173,6 +174,13 @@ public class BubbleChat { bm = BitmapFactory.decodeFile(appData); appData = "file://" + appData; } + + if (bm.getWidth() > bm.getHeight() && bm.getWidth() > SIZE_MAX) { + bm = Bitmap.createScaledBitmap(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth(), false); + } else if (bm.getHeight() > bm.getWidth() && bm.getHeight() > SIZE_MAX) { + + bm = Bitmap.createScaledBitmap(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX, false); + } if (bm != null) { imageView.setImageBitmap(bm); diff --git a/submodules/belle-sip b/submodules/belle-sip index b3fcd2a85..7d27eb87c 160000 --- a/submodules/belle-sip +++ b/submodules/belle-sip @@ -1 +1 @@ -Subproject commit b3fcd2a8503069a9e9b0d15cc872e55c0eb48cf3 +Subproject commit 7d27eb87c5dbd530e1c0a95cd0da2e233fb4d6b5 diff --git a/submodules/linphone b/submodules/linphone index 5913eff7a..5a0c92bac 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 5913eff7a5ff4516c745669b6bedb87f367a84fa +Subproject commit 5a0c92bac32d086e176e2b10d13c7fd5bb4c1032 diff --git a/tests/custom_rules.xml b/tests/custom_rules.xml index a6e0af289..5a23506fc 100644 --- a/tests/custom_rules.xml +++ b/tests/custom_rules.xml @@ -48,7 +48,7 @@ - + @@ -65,6 +65,6 @@ - +