diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 53d5f3619..84c05cc03 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -37,7 +37,10 @@
-
+
+
+
+
@@ -45,6 +48,7 @@
@@ -56,7 +60,7 @@
-
+ />
@@ -64,14 +68,16 @@
+
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -182,8 +207,8 @@
-
-
diff --git a/res/layout-small/status.xml b/res/layout-small/status.xml
index 13203f9d0..c79638cbb 100644
--- a/res/layout-small/status.xml
+++ b/res/layout-small/status.xml
@@ -241,6 +241,19 @@
android:adjustViewBounds="true"
android:visibility="gone"
android:layout_alignParentRight="true" />
+
+
-
d MMM
EEEE MMM d HH:mm
HH:mm d MMM
HH:mm
linphone-mms-%s.jpg
-
+
Linphone
Linphone Service
Linphone
+ org.linphone
+ linphone contacts
+ vnd.android.cursor.item/org.linphone.profile
Linphone
Starting up
- Registered to %s
+ Registered to %s
Fails to register to %s
Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2
http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications
-
+
This assistant will help you to use a SIP account for your calls.
Create an account on linphone.org
I already have a linphone.org account
I already have a SIP account
Enter your linphone.org username and password
Enter your SIP account username, password and domain
-
- username
+ username
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 79551c89c..863a82ac8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -353,6 +353,7 @@
Sharing server
Remote provisioning
Delete
+ This contact will be deleted.
SIP address
Phone number
First name
diff --git a/res/xml/authenticator.xml b/res/xml/authenticator.xml
new file mode 100644
index 000000000..885948b88
--- /dev/null
+++ b/res/xml/authenticator.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/res/xml/contacts.xml b/res/xml/contacts.xml
new file mode 100644
index 000000000..f05076c82
--- /dev/null
+++ b/res/xml/contacts.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/syncadapter.xml b/res/xml/syncadapter.xml
new file mode 100644
index 000000000..0b7795d77
--- /dev/null
+++ b/res/xml/syncadapter.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/src/org/linphone/Contact.java b/src/org/linphone/Contact.java
index 14d434808..764ed95cc 100644
--- a/src/org/linphone/Contact.java
+++ b/src/org/linphone/Contact.java
@@ -38,7 +38,7 @@ public class Contact implements Serializable {
private String name;
private transient Uri photoUri;
private transient Bitmap photo;
- private List numerosOrAddresses;
+ private List numbersOrAddresses;
private LinphoneFriend friend;
public Contact(String id, String name) {
@@ -88,14 +88,14 @@ public class Contact implements Serializable {
return photo;
}
- public List getNumerosOrAddresses() {
- if (numerosOrAddresses == null)
- numerosOrAddresses = new ArrayList();
- return numerosOrAddresses;
+ public List getNumbersOrAddresses() {
+ if (numbersOrAddresses == null)
+ numbersOrAddresses = new ArrayList();
+ return numbersOrAddresses;
}
public void refresh(ContentResolver cr) {
- this.numerosOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
+ this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
this.name = Compatibility.refreshContactName(cr, id);
}
}
diff --git a/src/org/linphone/ContactFragment.java b/src/org/linphone/ContactFragment.java
index 8de8ef76a..cfaacea61 100644
--- a/src/org/linphone/ContactFragment.java
+++ b/src/org/linphone/ContactFragment.java
@@ -27,7 +27,9 @@ import org.linphone.mediastream.Log;
import org.linphone.ui.AvatarWithShadow;
import android.annotation.SuppressLint;
+import android.app.AlertDialog;
import android.content.ContentProviderOperation;
+import android.content.DialogInterface;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.ContactsContract;
@@ -122,7 +124,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
TableLayout controls = (TableLayout) view.findViewById(R.id.controls);
controls.removeAllViews();
- for (String numberOrAddress : contact.getNumerosOrAddresses()) {
+ for (String numberOrAddress : contact.getNumbersOrAddresses()) {
View v = inflater.inflate(R.layout.contact_control_row, null);
String displayednumberOrAddress = numberOrAddress;
@@ -221,9 +223,17 @@ public class ContactFragment extends Fragment implements OnClickListener {
if (id == R.id.editContact) {
LinphoneActivity.instance().editContact(contact);
} else if (id == R.id.deleteContact) {
- deleteExistingContact();
- LinphoneActivity.instance().removeContactFromLists(contact);
- LinphoneActivity.instance().displayContacts(false);
+ AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
+ alertDialog.setMessage(getString(R.string.delete_contact_dialog));
+ alertDialog.setPositiveButton(getString(R.string.button_ok),new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ deleteExistingContact();
+ LinphoneActivity.instance().removeContactFromLists(contact);
+ LinphoneActivity.instance().displayContacts(false);
+ }
+ });
+ alertDialog.setNegativeButton(getString(R.string.button_cancel),null);
+ alertDialog.show();
}
}
diff --git a/src/org/linphone/ContactHelper.java b/src/org/linphone/ContactHelper.java
index eb33caa98..e6df72e82 100644
--- a/src/org/linphone/ContactHelper.java
+++ b/src/org/linphone/ContactHelper.java
@@ -29,6 +29,7 @@ import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
@@ -97,6 +98,35 @@ public final class ContactHelper {
Cursor cursor = resolver.query(photoUriToTest, new String[]{photoCol}, null, null, null);
return testPhotoUriAndCloseCursor(cursor);
}
+
+ public static String queryAddressOrNumber(ContentResolver resolver, Uri contactUri) {
+ // Phone Numbers
+ String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
+ Cursor c = resolver.query(contactUri, projection, null, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
+ String number = c.getString(numberIndex);
+ c.close();
+ return number;
+ }
+ }
+
+ // SIP addresses
+ projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
+ c = resolver.query(contactUri, projection, null, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
+ String address = c.getString(numberIndex);
+ c.close();
+ return address;
+ }
+ }
+
+ c.close();
+ return null;
+ }
private void checkPhotosUris(ContentResolver resolver, Cursor c, String idCol, String nameCol) {
displayName = c.getString(c.getColumnIndex(nameCol));
@@ -179,13 +209,51 @@ public final class ContactHelper {
return contactFound;
}
-
+
+ static boolean isContactHasLinphoneTag(Contact contact, ContentResolver cr) {
+ String select = ContactsContract.Data.CONTACT_ID + " = ?";
+ String[] args = new String[] { contact.getID() };
+
+ String[] projection = new String[] {ContactsContract.Data.MIMETYPE };
+
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, projection, select, args, null);
+
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ if(cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals("vnd.android.cursor.item/org.linphone.profile")){
+ cursor.close();
+ return true;
+ }
+ }
+ }
+ cursor.close();
+ return false;
+ }
+
+ public static String findRawContactID(ContentResolver cr, String contactID) {
+ Cursor c = cr.query(ContactsContract.RawContacts.CONTENT_URI,
+ new String[]{ContactsContract.RawContacts._ID},
+ ContactsContract.RawContacts.CONTACT_ID + "=?",
+ new String[]{contactID}, null);
+ if (c != null) {
+ String result = null;
+ if (c.moveToFirst()) {
+ result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID));
+ }
+
+ c.close();
+ return result;
+ }
+ return null;
+ }
+
@SuppressLint("InlinedApi")
private final boolean queryContact() {
boolean contactFound = false;
Uri uri = android.provider.ContactsContract.Data.CONTENT_URI;
- String[] projection = { android.provider.ContactsContract.Data.CONTACT_ID, android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, android.provider.ContactsContract.CommonDataKinds.Im.DATA };
+ String[] projection = { android.provider.ContactsContract.Data.CONTACT_ID, android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
+ android.provider.ContactsContract.CommonDataKinds.Im.DATA };
String selection = new StringBuilder()
.append(android.provider.ContactsContract.Data.MIMETYPE)
@@ -211,6 +279,7 @@ public final class ContactHelper {
c = resolver.query(uri, projection, selection, null, null);
contactFound = checkSIPQueryResult(c, android.provider.ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
if (contactFound) {
+ c.close();
return true;
}
}
@@ -222,7 +291,7 @@ public final class ContactHelper {
android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME };
c = resolver.query(lookupUri, projection, null, null, null);
contactFound = checkPhoneQueryResult(c, android.provider.ContactsContract.PhoneLookup.NUMBER);
-
+ c.close();
return contactFound;
}
}
\ No newline at end of file
diff --git a/src/org/linphone/ContactsFragment.java b/src/org/linphone/ContactsFragment.java
index a013fceb7..418702d80 100644
--- a/src/org/linphone/ContactsFragment.java
+++ b/src/org/linphone/ContactsFragment.java
@@ -127,7 +127,7 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
searchContacts(searchField.getText().toString());
}
});
-
+
return view;
}
diff --git a/src/org/linphone/DialerFragment.java b/src/org/linphone/DialerFragment.java
index 279ee6c61..166ffe482 100644
--- a/src/org/linphone/DialerFragment.java
+++ b/src/org/linphone/DialerFragment.java
@@ -198,8 +198,14 @@ public class DialerFragment extends Fragment {
} else if (scheme.startsWith("call") || scheme.startsWith("sip")) {
mAddress.setText(intent.getData().getSchemeSpecificPart());
} else {
- Log.e("Unknown scheme: ",scheme);
- mAddress.setText(intent.getData().getSchemeSpecificPart());
+ Uri contactUri = intent.getData();
+ String address = ContactHelper.queryAddressOrNumber(getActivity().getContentResolver(),contactUri);
+ if(address != null) {
+ mAddress.setText(address);
+ } else {
+ Log.e("Unknown scheme: ", scheme);
+ mAddress.setText(intent.getData().getSchemeSpecificPart());
+ }
}
mAddress.clearDisplayedName();
diff --git a/src/org/linphone/EditContactFragment.java b/src/org/linphone/EditContactFragment.java
index 1eb37daa9..1ca6aa8cc 100644
--- a/src/org/linphone/EditContactFragment.java
+++ b/src/org/linphone/EditContactFragment.java
@@ -41,7 +41,7 @@ public class EditContactFragment extends Fragment {
private ArrayList ops;
private int firstSipAddressIndex = -1;
private String newSipOrNumberToAdd;
-
+
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.inflater = inflater;
@@ -97,12 +97,12 @@ public class EditContactFragment extends Fragment {
}
try {
- getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
- LinphoneActivity.instance().prepareContactsInBackground();
+ getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+ LinphoneActivity.instance().prepareContactsInBackground();
} catch (Exception e) {
e.printStackTrace();
}
-
+
getFragmentManager().popBackStackImmediate();
}
});
@@ -156,7 +156,7 @@ public class EditContactFragment extends Fragment {
public void afterTextChanged(Editable s) {
}
});
-
+
if (!isNewContact) {
String fn = findContactFirstName(String.valueOf(contactID));
String ln = findContactLastName(String.valueOf(contactID));
@@ -201,7 +201,7 @@ public class EditContactFragment extends Fragment {
numbersAndAddresses = new ArrayList();
if (contact != null) {
- for (String numberOrAddress : contact.getNumerosOrAddresses()) {
+ for (String numberOrAddress : contact.getNumbersOrAddresses()) {
View view = displayNumberOrAddress(controls, numberOrAddress);
if (view != null)
controls.addView(view);
@@ -288,6 +288,7 @@ public class EditContactFragment extends Fragment {
nounoa.delete();
numbersAndAddresses.remove(nounoa);
view.setVisibility(View.GONE);
+
}
});
return view;
@@ -358,11 +359,14 @@ public class EditContactFragment extends Fragment {
contactID = 0;
ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
- .withValue(RawContacts.ACCOUNT_TYPE, null)
- .withValue(RawContacts.ACCOUNT_NAME, null).build());
-
+ .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
+ .withValue(RawContacts.ACCOUNT_TYPE, null)
+ .withValue(RawContacts.ACCOUNT_NAME, null)
+ .build()
+ );
+
if (getDisplayName() != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName.getText().toString())
@@ -377,7 +381,7 @@ public class EditContactFragment extends Fragment {
String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'" ;
String[] args = new String[] { String.valueOf(contactID) };
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName.getText().toString())
@@ -386,7 +390,7 @@ public class EditContactFragment extends Fragment {
);
}
}
-
+
private String getDisplayName() {
String displayName = null;
if (firstName.getText().length() > 0 && lastName.getText().length() > 0)
@@ -400,9 +404,8 @@ public class EditContactFragment extends Fragment {
private String findRawContactID(String contactID) {
Cursor c = getActivity().getContentResolver().query(RawContacts.CONTENT_URI,
- new String[]{RawContacts._ID},
- RawContacts.CONTACT_ID + "=?",
- new String[]{contactID}, null);
+ new String[]{RawContacts._ID},RawContacts.CONTACT_ID + "=?",
+ new String[]{contactID}, null);
if (c != null) {
String result = null;
if (c.moveToFirst()) {
@@ -413,6 +416,24 @@ public class EditContactFragment extends Fragment {
}
return null;
}
+
+ private String findRawLinphoneContactID(String contactID) {
+ String result = null;
+ String[] projection = { RawContacts._ID };
+
+ String selection = RawContacts.CONTACT_ID + "=? AND "
+ + RawContacts.ACCOUNT_TYPE + "=? ";
+
+ Cursor c = getActivity().getContentResolver().query(RawContacts.CONTENT_URI, projection,
+ selection, new String[]{contactID, getString(R.string.sync_account_type)}, null);
+ if (c != null) {
+ if (c.moveToFirst()) {
+ result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID));
+ }
+ }
+ c.close();
+ return result;
+ }
private String findContactFirstName(String contactID) {
Cursor c = getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
@@ -495,6 +516,7 @@ public class EditContactFragment extends Fragment {
public void delete() {
if (isSipAddress) {
Compatibility.deleteSipAddressFromContact(ops, oldNumberOrAddress, String.valueOf(contactID));
+ Compatibility.deleteLinphoneContactTag(ops, oldNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID)));
} else {
String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "
@@ -521,24 +543,25 @@ public class EditContactFragment extends Fragment {
newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress);
} else {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label))
+ .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label))
.build()
);
}
} else {
String rawContactId = findRawContactID(String.valueOf(contactID));
-
if (isSipAddress) {
if (newNumberOrAddress.startsWith("sip:"))
newNumberOrAddress = newNumberOrAddress.substring(4);
if(!newNumberOrAddress.contains("@"))
newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
- Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress, rawContactId);
+ Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress, rawContactId);
+ Compatibility.addLinphoneContactTag(getActivity(), ops, newNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID)));
+
} else {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
@@ -563,6 +586,7 @@ public class EditContactFragment extends Fragment {
if(!newNumberOrAddress.contains("@"))
newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
Compatibility.updateSipAddressForContact(ops, oldNumberOrAddress, newNumberOrAddress, String.valueOf(contactID));
+ Compatibility.updateLinphoneContactTag(getActivity(), ops, newNumberOrAddress, oldNumberOrAddress, findRawLinphoneContactID(String.valueOf(contactID)));
} else {
String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "
@@ -578,4 +602,4 @@ public class EditContactFragment extends Fragment {
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java
index 9f91481ea..594885511 100644
--- a/src/org/linphone/LinphoneActivity.java
+++ b/src/org/linphone/LinphoneActivity.java
@@ -49,9 +49,13 @@ import org.linphone.setup.RemoteProvisioningLoginActivity;
import org.linphone.setup.SetupActivity;
import org.linphone.ui.AddressText;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -59,6 +63,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.ContactsContract;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.Fragment.SavedState;
@@ -110,6 +115,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
private Cursor contactCursor, sipContactCursor;
private OrientationEventListener mOrientationHelper;
private LinphoneCoreListenerBase mListener;
+ private Account mAccount;
static final boolean isInstanciated() {
return instance != null;
@@ -153,6 +159,12 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
}
+
+ /*if(!LinphonePreferences.instance().isContactsMigrationDone()){
+ migrateContacts(this);
+ LinphonePreferences.instance().contactsMigrationDone();
+ }*/
+
setContentView(R.layout.main);
instance = this;
fragmentsHistory = new ArrayList();
@@ -169,6 +181,8 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
}
+ mAccount = initializeSyncAccount(this);
+
mListener = new LinphoneCoreListenerBase(){
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
@@ -248,6 +262,13 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
updateAnimationsState();
}
+ private Account initializeSyncAccount(Context context) {
+ Account newAccount = new Account(context.getString(R.string.sync_account_name), context.getString(R.string.sync_account_type));
+ AccountManager accountManager = (AccountManager) context.getSystemService(ACCOUNT_SERVICE);
+ accountManager.addAccountExplicitly(newAccount, null, null);
+ return newAccount;
+ }
+
private void initButtons() {
menu = (LinearLayout) findViewById(R.id.menu);
mark = (LinearLayout) findViewById(R.id.mark);
@@ -1007,7 +1028,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
for (Contact contact : sipContactList) {
- for (String addr : contact.getNumerosOrAddresses()) {
+ for (String addr : contact.getNumbersOrAddresses()) {
if (addr.equals(sipUri)) {
return contact;
}
@@ -1055,11 +1076,11 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
private void searchFriendAndAddToContact(Contact contact) {
- if (contact == null || contact.getNumerosOrAddresses() == null) {
+ if (contact == null || contact.getNumbersOrAddresses() == null) {
return;
}
- for (String sipUri : contact.getNumerosOrAddresses()) {
+ for (String sipUri : contact.getNumbersOrAddresses()) {
if (LinphoneUtils.isSipAddress(sipUri)) {
LinphoneFriend friend = LinphoneManager.getLc().findFriendByAddress(sipUri);
if (friend != null) {
@@ -1090,6 +1111,46 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
}
}
+ public void migrateContacts(Context context) {
+ ContentResolver cr = getContentResolver();
+ Cursor oldContacts = Compatibility.getImContactsCursor(cr);
+ ArrayList ops = new ArrayList();
+
+ if(oldContacts != null){
+ for (int i = 0; i < oldContacts.getCount(); i++) {
+ Contact c = Compatibility.getContact(cr, oldContacts, i);
+ for (String address : Compatibility.extractContactImAddresses(c.getID(), cr)) {
+ if (LinphoneUtils.isSipAddress(address)) {
+ if (address.startsWith("sip:")) {
+ address = address.substring(4);
+ }
+ Compatibility.addSipAddressToContact(context, ops, address, ContactHelper.findRawContactID(cr,c.getID()));
+ try {
+ cr.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ ops.clear();
+ c.refresh(cr);
+ if(c.getNumbersOrAddresses().contains("sip:"+address)){
+ Compatibility.deleteImAddressFromContact(ops, address, c.getID());
+ try {
+ cr.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.w("Cannot migrate this contact " + c.getName());
+ }
+ }
+ }
+ ops.clear();
+ }
+ }
+ }
+
+
public synchronized void prepareContactsInBackground() {
if (contactCursor != null) {
contactCursor.close();
@@ -1104,35 +1165,44 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
Thread sipContactsHandler = new Thread(new Runnable() {
@Override
public void run() {
- if(sipContactCursor != null) {
- for (int i = 0; i < sipContactCursor.getCount(); i++) {
- Contact contact = Compatibility.getContact(getContentResolver(), sipContactCursor, i);
- if (contact == null)
- continue;
+ if(sipContactCursor != null) {
+ Log.w(sipContactCursor.getCount());
+ for (int i = 0; i < sipContactCursor.getCount(); i++) {
+ Contact contact = Compatibility.getContact(getContentResolver(), sipContactCursor, i);
+ if (contact == null)
+ continue;
- contact.refresh(getContentResolver());
- if (!isContactPresenceDisabled) {
- searchFriendAndAddToContact(contact);
- }
- sipContactList.add(contact);
+ contact.refresh(getContentResolver());
+ //Add tag to Linphone contact if it not existed
+ if(!ContactHelper.isContactHasLinphoneTag(contact,getContentResolver())){
+ Compatibility.createLinphoneContactTag(getApplicationContext(),getContentResolver(),contact,
+ ContactHelper.findRawContactID(getContentResolver(),String.valueOf(contact.getID())));
}
- }
- if(contactCursor != null) {
- for (int i = 0; i < contactCursor.getCount(); i++) {
- Contact contact = Compatibility.getContact(getContentResolver(), contactCursor, i);
- if (contact == null)
- continue;
- for (Contact c : sipContactList) {
- if (c != null && c.getID().equals(contact.getID())) {
- contact = c;
- break;
- }
- }
- contactList.add(contact);
+ if (!isContactPresenceDisabled) {
+ searchFriendAndAddToContact(contact);
}
+ sipContactList.add(contact);
}
}
+ if(contactCursor != null){
+ for (int i = 0; i < contactCursor.getCount(); i++) {
+ Contact contact = Compatibility.getContact(getContentResolver(), contactCursor, i);
+
+ if (contact == null)
+ continue;
+
+ for (Contact c : sipContactList) {
+ if (c != null && c.getID().equals(contact.getID())) {
+ contact = c;
+ break;
+ }
+ }
+ contactList.add(contact);
+ }
+ }
+ getContentResolver().requestSync(mAccount, ContactsContract.AUTHORITY, new Bundle());
+ }
});
contactList = new ArrayList();
@@ -1195,6 +1265,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
extras.putSerializable("Contact", contact);
changeCurrentFragment(FragmentsAvailable.EDIT_CONTACT, extras);
}
+
}
public void editContact(Contact contact, String sipAddress)
diff --git a/src/org/linphone/LinphonePreferences.java b/src/org/linphone/LinphonePreferences.java
index 17fed12c1..bdb89344a 100644
--- a/src/org/linphone/LinphonePreferences.java
+++ b/src/org/linphone/LinphonePreferences.java
@@ -1143,4 +1143,12 @@ public class LinphonePreferences {
public void setCodecBitrateLimit(int bitrate) {
getConfig().setInt("audio", "codec_bitrate_limit", bitrate);
}
+
+ public void contactsMigrationDone(){
+ getConfig().setBool("app", "contacts_migration_done",true);
+ }
+
+ public boolean isContactsMigrationDone(){
+ return getConfig().getBool("app", "contacts_migration_done",false);
+ }
}
diff --git a/src/org/linphone/PreferencesMigrator.java b/src/org/linphone/PreferencesMigrator.java
index 85d4c0f4b..f6cae93c4 100644
--- a/src/org/linphone/PreferencesMigrator.java
+++ b/src/org/linphone/PreferencesMigrator.java
@@ -19,7 +19,6 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-import org.linphone.LinphoneManager;
import org.linphone.LinphonePreferences.AccountBuilder;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
@@ -28,6 +27,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.res.Resources;
+
import android.preference.PreferenceManager;
/**
@@ -120,7 +120,7 @@ public class PreferencesMigrator {
doAccountMigration(i, i == getPrefInt(R.string.pref_default_account_key, 0));
}
}
-
+
private void doAccountMigration(int index, boolean isDefaultAccount) {
String key = index == 0 ? "" : String.valueOf(index);
@@ -163,7 +163,7 @@ public class PreferencesMigrator {
}
}
}
-
+
private void deleteAllOldPreferences() {
Editor editor = mOldPrefs.edit();
editor.clear();
diff --git a/src/org/linphone/StatusFragment.java b/src/org/linphone/StatusFragment.java
index 7a3862829..e6f997b2c 100644
--- a/src/org/linphone/StatusFragment.java
+++ b/src/org/linphone/StatusFragment.java
@@ -134,7 +134,6 @@ public class StatusFragment extends Fragment {
});
}
// setMiniLedsForEachAccount();
- populateSliderContent();
populateSliderContent();
sliderContentAccounts.invalidate();
} catch (IllegalStateException ise) {}
@@ -163,11 +162,10 @@ public class StatusFragment extends Fragment {
}
};
-
+
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
lc.addListener(mListener);
-
LinphoneProxyConfig lpc = lc.getDefaultProxyConfig();
if (lpc != null) {
mListener.registrationState(lc, lpc, lpc.getState(), null);
diff --git a/src/org/linphone/compatibility/ApiElevenPlus.java b/src/org/linphone/compatibility/ApiElevenPlus.java
index d252c3985..1fc9b8409 100644
--- a/src/org/linphone/compatibility/ApiElevenPlus.java
+++ b/src/org/linphone/compatibility/ApiElevenPlus.java
@@ -18,7 +18,7 @@ import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents.Insert;
@@ -144,9 +144,8 @@ public class ApiElevenPlus {
ArrayList data = new ArrayList();
ContentValues sipAddressRow = new ContentValues();
- sipAddressRow.put(Contacts.Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
- sipAddressRow.put(Im.DATA, sipUri);
- sipAddressRow.put(Im.CUSTOM_PROTOCOL,"Sip");
+ sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
+ sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
data.add(sipAddressRow);
intent.putParcelableArrayListExtra(Insert.DATA, data);
@@ -160,10 +159,8 @@ public class ApiElevenPlus {
ArrayList data = new ArrayList();
ContentValues sipAddressRow = new ContentValues();
- sipAddressRow.put(Contacts.Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
- sipAddressRow.put(Im.DATA, sipUri);
- sipAddressRow.put(Im.CUSTOM_PROTOCOL,"Sip");
- data.add(sipAddressRow);
+ sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
+ sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
data.add(sipAddressRow);
intent.putParcelableArrayListExtra(Insert.DATA, data);
diff --git a/src/org/linphone/compatibility/ApiFivePlus.java b/src/org/linphone/compatibility/ApiFivePlus.java
index 02a86c282..18a77a4c9 100644
--- a/src/org/linphone/compatibility/ApiFivePlus.java
+++ b/src/org/linphone/compatibility/ApiFivePlus.java
@@ -111,7 +111,7 @@ public class ApiFivePlus {
c.close();
}
- // SIP addresses
+ // IM addresses
String selection = new StringBuilder()
.append(Data.CONTACT_ID).append(" = ? AND ")
.append(Data.MIMETYPE).append(" = '")
@@ -246,7 +246,7 @@ public class ApiFivePlus {
Cursor cursor = getSIPContactCursor(cr, sipUri);
Contact contact = getContact(cr, cursor, 0);
- if (contact != null && contact.getNumerosOrAddresses().contains(sipUri)) {
+ if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
address.setDisplayName(contact.getName());
cursor.close();
return contact.getPhotoUri();
diff --git a/src/org/linphone/compatibility/ApiNinePlus.java b/src/org/linphone/compatibility/ApiNinePlus.java
index cd83f47ea..a52373ebe 100644
--- a/src/org/linphone/compatibility/ApiNinePlus.java
+++ b/src/org/linphone/compatibility/ApiNinePlus.java
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.linphone.Contact;
+import org.linphone.LinphoneUtils;
import org.linphone.R;
import org.linphone.core.LinphoneAddress;
@@ -42,52 +43,48 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@TargetApi(9)
public class ApiNinePlus {
-
+
public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, ContactsContract.CommonDataKinds.Im.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL,"Sip")
- .withValue(ContactsContract.CommonDataKinds.Im.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
+ .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
+ .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
+ .build()
+ );
}
public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress, String rawContactID) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, ContactsContract.CommonDataKinds.Im.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL,"Sip")
- .withValue(ContactsContract.CommonDataKinds.Im.LABEL, context.getString(R.string.addressbook_label))
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
+ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
+ .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
+ .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
.build()
);
}
- public static void updateSipAddressForContact(ArrayList ops, String oldIm, String newIm, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.Im.DATA + "=? AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'";
- String[] args = new String[] { String.valueOf(contactID), oldIm };
+ public static void updateSipAddressForContact(ArrayList ops, String oldSipAddress, String newSipAddress, String contactID) {
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
+ + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?";
+ String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, newIm)
+ .withSelection(select, args)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newSipAddress)
.build()
);
}
- public static void deleteSipAddressFromContact(ArrayList ops, String oldIm, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.Im.DATA + "=? AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'";
- String[] args = new String[] { String.valueOf(contactID), oldIm };
+ public static void deleteSipAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
+ + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=? ";
+ String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
@@ -99,7 +96,7 @@ public class ApiNinePlus {
List list = new ArrayList();
Uri uri = Data.CONTENT_URI;
- String[] projection = {ContactsContract.CommonDataKinds.Im.DATA};
+ String[] projection;
// Phone Numbers
Cursor c = cr.query(Phone.CONTENT_URI, new String[] { Phone.NUMBER }, Phone.CONTACT_ID + " = " + id, null, null);
@@ -110,28 +107,7 @@ public class ApiNinePlus {
}
c.close();
}
-
- // IM addresses
- String selection = new StringBuilder()
- .append(Data.CONTACT_ID)
- .append(" = ? AND ")
- .append(Data.MIMETYPE)
- .append(" = '")
- .append(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .append("' AND lower(")
- .append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
- .append(") = 'sip'")
- .toString();
- projection = new String[] {ContactsContract.CommonDataKinds.Im.DATA};
- c = cr.query(uri, projection, selection, new String[]{id}, null);
- if (c != null) {
- int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA);
- while (c.moveToNext()) {
- list.add("sip:" + c.getString(nbId));
- }
- c.close();
- }
-
+
// SIP addresses
String selection2 = new StringBuilder()
.append(Data.CONTACT_ID)
@@ -155,13 +131,10 @@ public class ApiNinePlus {
}
public static Cursor getContactsCursor(ContentResolver cr, String search) {
- String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+ String req = Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+ "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL OR ("
- + Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'"
- + " AND " + ContactsContract.CommonDataKinds.Im.DATA + " IS NOT NULL"
- + ") OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
+ + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL)";
if (search != null) {
req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
@@ -172,11 +145,8 @@ public class ApiNinePlus {
public static Cursor getSIPContactsCursor(ContentResolver cr, String search) {
String req = null;
- req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'"
- + " AND " + ContactsContract.CommonDataKinds.Im.DATA + " IS NOT NULL"
- + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
+ req = Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL";
if (search != null) {
req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
@@ -184,18 +154,14 @@ public class ApiNinePlus {
return ApiFivePlus.getGeneralContactCursor(cr, req, true);
}
-
+
private static Cursor getSIPContactCursor(ContentResolver cr, String id) {
String req = null;
- req = "(" + Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + " AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip' AND "
- + android.provider.ContactsContract.CommonDataKinds.Im.DATA + " LIKE '" + id + "' "
- + " OR " + Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + " AND " + android.provider.ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " LIKE '" + id + "'";
+ req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " LIKE '" + id + "'";
return ApiFivePlus.getGeneralContactCursor(cr, req, false);
}
-
public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
String username = address.getUserName();
String domain = address.getDomain();
@@ -203,7 +169,7 @@ public class ApiNinePlus {
Cursor cursor = getSIPContactCursor(cr, sipUri);
Contact contact = ApiFivePlus.getContact(cr, cursor, 0);
- if (contact != null && contact.getNumerosOrAddresses().contains(sipUri)) {
+ if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
address.setDisplayName(contact.getName());
cursor.close();
return contact.getPhotoUri();
@@ -212,4 +178,85 @@ public class ApiNinePlus {
cursor.close();
return null;
}
+
+ //Linphone Contacts Tag
+ public static void addLinphoneContactTag(Context context, ArrayList ops, String newAddress, String rawContactId){
+ if(rawContactId != null) {
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
+ .withValue(ContactsContract.Data.MIMETYPE, context.getString(R.string.sync_mimetype))
+ .withValue(ContactsContract.Data.DATA1, newAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, newAddress)
+ .build()
+ );
+ }
+ }
+ public static void updateLinphoneContactTag(Context context, ArrayList ops, String newAddress, String oldAddress, String rawContactId){
+ if(rawContactId != null) {
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
+ .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.DATA1 + "=? ", new String[]{rawContactId, oldAddress})
+ .withValue(ContactsContract.Data.DATA1, newAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, newAddress)
+ .build());
+ }
+ }
+
+ public static void deleteLinphoneContactTag(ArrayList ops , String oldAddress, String rawContactId){
+ if(rawContactId != null) {
+ ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
+ .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.DATA1 + "=? ", new String[]{rawContactId, oldAddress})
+ .build());
+ }
+ }
+
+ public static void createLinphoneContactTag(Context context, ContentResolver contentResolver, Contact contact, String rawContactId){
+ ArrayList ops = new ArrayList();
+
+ if (contact != null) {
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+ .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, context.getString(R.string.sync_account_type))
+ .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, context.getString(R.string.sync_account_name))
+ .build()
+ );
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
+ .build()
+ );
+
+ List numbersOrAddresses = contact.getNumbersOrAddresses();
+ for (String numberOrAddress : numbersOrAddresses) {
+ if (LinphoneUtils.isSipAddress(numberOrAddress)) {
+ if (numberOrAddress.startsWith("sip:")){
+ numberOrAddress = numberOrAddress.substring(4);
+ }
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, context.getString(R.string.sync_mimetype))
+ .withValue(ContactsContract.Data.DATA1, numberOrAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, numberOrAddress)
+ .build()
+ );
+ }
+ }
+
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI)
+ .withValue(ContactsContract.AggregationExceptions.TYPE, ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER)
+ .withValue(ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, rawContactId)
+ .withValueBackReference(ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, 0).build());
+
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/src/org/linphone/compatibility/Compatibility.java b/src/org/linphone/compatibility/Compatibility.java
index 21ea8d89d..69fa40e80 100644
--- a/src/org/linphone/compatibility/Compatibility.java
+++ b/src/org/linphone/compatibility/Compatibility.java
@@ -79,6 +79,10 @@ public class Compatibility {
return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
}
}
+
+ public static List extractContactImAddresses(String id, ContentResolver cr) {
+ return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
+ }
public static Cursor getContactsCursor(ContentResolver cr) {
if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
@@ -111,6 +115,10 @@ public class Compatibility {
return ApiFivePlus.getSIPContactsCursor(cr);
}
}
+
+ public static Cursor getImContactsCursor(ContentResolver cr) {
+ return ApiFivePlus.getSIPContactsCursor(cr);
+ }
public static int getCursorDisplayNameColumnIndex(Cursor cursor) {
if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
@@ -261,7 +269,36 @@ public class Compatibility {
ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
}
}
-
+
+ public static void deleteImAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
+ ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
+ }
+
+ //Linphone Contacts Tag
+ public static void addLinphoneContactTag(Context context, ArrayList ops, String newSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.addLinphoneContactTag(context, ops, newSipAddress, rawContactId);
+ }
+ }
+
+ public static void updateLinphoneContactTag(Context context, ArrayList ops, String newSipAddress, String oldSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.updateLinphoneContactTag(context, ops, newSipAddress, oldSipAddress, rawContactId);
+ }
+ }
+
+ public static void deleteLinphoneContactTag(ArrayList ops, String oldSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.deleteLinphoneContactTag(ops, oldSipAddress, rawContactId);
+ }
+ }
+
+ public static void createLinphoneContactTag(Context context, ContentResolver contentResolver, Contact contact, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.createLinphoneContactTag(context, contentResolver, contact, rawContactId);
+ }
+ }
+ //End of Linphone Contact Tag
public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
diff --git a/src/org/linphone/sync/AuthenticationService.java b/src/org/linphone/sync/AuthenticationService.java
new file mode 100644
index 000000000..aec317e82
--- /dev/null
+++ b/src/org/linphone/sync/AuthenticationService.java
@@ -0,0 +1,39 @@
+package org.linphone.sync;
+
+/*
+AuthenticationService.java
+Copyright (C) 2015 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.
+*/
+
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AuthenticationService extends Service {
+
+ private Authenticator mAuthenticator;
+ @Override
+ public void onCreate() {
+ mAuthenticator = new Authenticator(this);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mAuthenticator.getIBinder();
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/sync/Authenticator.java b/src/org/linphone/sync/Authenticator.java
new file mode 100644
index 000000000..30f3e8065
--- /dev/null
+++ b/src/org/linphone/sync/Authenticator.java
@@ -0,0 +1,85 @@
+package org.linphone.sync;
+
+/*
+Authenticator.java
+Copyright (C) 2015 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.
+*/
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.*;
+import android.content.Context;
+import android.os.Bundle;
+
+public class Authenticator extends AbstractAccountAuthenticator {
+
+ public Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle editProperties(
+ AccountAuthenticatorResponse r, String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle addAccount(
+ AccountAuthenticatorResponse r,
+ String s,
+ String s2,
+ String[] strings,
+ Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle confirmCredentials(
+ AccountAuthenticatorResponse r,
+ Account account,
+ Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(
+ AccountAuthenticatorResponse r,
+ Account account,
+ String s,
+ Bundle bundle) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle updateCredentials(
+ AccountAuthenticatorResponse r,
+ Account account,
+ String s, Bundle bundle) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle hasFeatures(
+ AccountAuthenticatorResponse r,
+ Account account, String[] strings) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/sync/SyncAdapter.java b/src/org/linphone/sync/SyncAdapter.java
new file mode 100755
index 000000000..620adc861
--- /dev/null
+++ b/src/org/linphone/sync/SyncAdapter.java
@@ -0,0 +1,40 @@
+package org.linphone.sync;
+
+/*
+SyncAdapter.java
+Copyright (C) 2015 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.
+*/
+
+import android.accounts.Account;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.content.SyncResult;
+import android.os.Bundle;
+
+public class SyncAdapter extends AbstractThreadedSyncAdapter {
+
+ public SyncAdapter(Context context, boolean autoInitialize) {
+ super(context, autoInitialize);
+ }
+
+ @Override
+ public void onPerformSync(Account account, Bundle extras, String authority,
+ ContentProviderClient provider, SyncResult syncResult) {
+ }
+}
+
diff --git a/src/org/linphone/sync/SyncService.java b/src/org/linphone/sync/SyncService.java
new file mode 100755
index 000000000..fc9ee6638
--- /dev/null
+++ b/src/org/linphone/sync/SyncService.java
@@ -0,0 +1,45 @@
+package org.linphone.sync;
+
+/*
+SyncService.java
+Copyright (C) 2015 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.
+*/
+
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class SyncService extends Service {
+ private static SyncAdapter sSyncAdapter = null;
+ private static final Object sSyncAdapterLock = new Object();
+
+ @Override
+ public void onCreate() {
+
+ synchronized (sSyncAdapterLock) {
+ if (sSyncAdapter == null) {
+ sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
+ }
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return sSyncAdapter.getSyncAdapterBinder();
+ }
+}