Added back the sync mechanism for contacts

This commit is contained in:
Sylvain Berfini 2016-07-13 15:42:13 +02:00
parent 5a40d15e1b
commit 182888f824
7 changed files with 173 additions and 164 deletions

View file

@ -78,7 +78,7 @@
</intent-filter> </intent-filter>
<intent-filter> <intent-filter>
<data android:mimeType="vnd.android.cursor.item/org.linphone.profile" /> <!-- Change package ! --> <data android:mimeType="@string/sync_mimetype" /> <!-- Change package in res/values/non_localizable_custom.xml ! -->
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />

View file

@ -6,7 +6,7 @@
<string name="default_stun">stun.linphone.org</string> <string name="default_stun">stun.linphone.org</string>
<string name="sync_account_type">org.linphone</string> <!-- Change package ! --> <string name="sync_account_type">org.linphone</string> <!-- Change package ! -->
<string name="sync_mimetype">vnd.android.cursor.item/org.linphone.profile</string> <!-- Change package, leave .profile at the end ! --> <string name="sync_mimetype">vnd.android.cursor.item/org.linphone.profile</string> <!-- Change package, leave .profile at the end. Also change res/xml/contacts.xml ! -->
<bool name="assistant_use_linphone_login_as_first_fragment">false</bool> <bool name="assistant_use_linphone_login_as_first_fragment">false</bool>
<bool name="hide_in_call_stats">false</bool> <bool name="hide_in_call_stats">false</bool>

View file

@ -174,7 +174,7 @@ public class ContactsManager extends ContentObserver {
} }
public void initializeSyncAccount(Context context, ContentResolver contentResolver) { public void initializeSyncAccount(Context context, ContentResolver contentResolver) {
initializeContactManager(context,contentResolver); initializeContactManager(context, contentResolver);
AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); AccountManager accountManager = (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
Account[] accounts = accountManager.getAccountsByType(context.getPackageName()); Account[] accounts = accountManager.getAccountsByType(context.getPackageName());
@ -330,6 +330,7 @@ public class ContactsManager extends ContentObserver {
Log.e(e); Log.e(e);
} }
} }
public String getString(int resourceID) { public String getString(int resourceID) {
return context.getString(resourceID); return context.getString(resourceID);
} }

View file

@ -103,13 +103,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
private static final int FIRST_LOGIN_ACTIVITY = 101; private static final int FIRST_LOGIN_ACTIVITY = 101;
private static final int REMOTE_PROVISIONING_LOGIN_ACTIVITY = 102; private static final int REMOTE_PROVISIONING_LOGIN_ACTIVITY = 102;
private static final int CALL_ACTIVITY = 19; private static final int CALL_ACTIVITY = 19;
private static final int PERMISSIONS_REQUEST_CONTACTS = 200;
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201; private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 201;
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL = 203; private static final int PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL = 203;
private static final int PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE_WRITE = 204;
private static final int PERMISSIONS_REQUEST_CAMERA = 205;
private static final int PERMISSIONS_REQUEST_OVERLAY = 206; private static final int PERMISSIONS_REQUEST_OVERLAY = 206;
private static final int PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE_READ = 207; private static final int PERMISSIONS_REQUEST_SYNC = 207;
private static LinphoneActivity instance; private static LinphoneActivity instance;
@ -174,9 +171,12 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
} }
} }
//TODO rework if (getResources().getBoolean(R.bool.use_linphone_tag)) {
if (getResources().getBoolean(R.bool.use_linphone_tag) && getPackageManager().checkPermission(Manifest.permission.WRITE_SYNC_SETTINGS, getPackageName()) == PackageManager.PERMISSION_GRANTED) { if (getPackageManager().checkPermission(Manifest.permission.WRITE_SYNC_SETTINGS, getPackageName()) != PackageManager.PERMISSION_GRANTED) {
ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver()); checkSyncPermission();
} else {
ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver());
}
} else { } else {
ContactsManager.getInstance().initializeContactManager(getApplicationContext(), getContentResolver()); ContactsManager.getInstance().initializeContactManager(getApplicationContext(), getContentResolver());
} }
@ -1167,23 +1167,23 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
} }
public void checkAndRequestReadExternalStoragePermission() { public void checkAndRequestReadExternalStoragePermission() {
checkAndRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE_READ); checkAndRequestPermission(Manifest.permission.READ_EXTERNAL_STORAGE, 0);
} }
public void checkAndRequestExternalStoragePermission() { public void checkAndRequestExternalStoragePermission() {
checkAndRequestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, PERMISSIONS_REQUEST_EXTERNAL_FILE_STORAGE_WRITE); checkAndRequestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 0);
} }
public void checkAndRequestCameraPermission() { public void checkAndRequestCameraPermission() {
checkAndRequestPermission(Manifest.permission.CAMERA, PERMISSIONS_REQUEST_CAMERA); checkAndRequestPermission(Manifest.permission.CAMERA, 0);
} }
public void checkAndRequestReadContactsPermission() { public void checkAndRequestReadContactsPermission() {
checkAndRequestPermission(Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_CONTACTS); checkAndRequestPermission(Manifest.permission.READ_CONTACTS, 0);
} }
public void checkAndRequestWriteContactsPermission() { public void checkAndRequestWriteContactsPermission() {
checkAndRequestPermission(Manifest.permission.WRITE_CONTACTS, PERMISSIONS_REQUEST_CONTACTS); checkAndRequestPermission(Manifest.permission.WRITE_CONTACTS, 0);
} }
public void checkAndRequestCallPermissions(boolean isIncomingCall) { public void checkAndRequestCallPermissions(boolean isIncomingCall) {
@ -1217,6 +1217,10 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
ActivityCompat.requestPermissions(this, permissions, 0); ActivityCompat.requestPermissions(this, permissions, 0);
} }
} }
private void checkSyncPermission() {
checkAndRequestPermission(Manifest.permission.WRITE_SYNC_SETTINGS, PERMISSIONS_REQUEST_SYNC);
}
public void checkAndRequestPermission(String permission, int result) { public void checkAndRequestPermission(String permission, int result) {
if (getPackageManager().checkPermission(permission, getPackageName()) != PackageManager.PERMISSION_GRANTED) { if (getPackageManager().checkPermission(permission, getPackageName()) != PackageManager.PERMISSION_GRANTED) {
@ -1233,6 +1237,13 @@ public class LinphoneActivity extends Activity implements OnClickListener, Conta
case PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL: case PERMISSIONS_REQUEST_RECORD_AUDIO_INCOMING_CALL:
startActivity(new Intent(this, CallIncomingActivity.class)); startActivity(new Intent(this, CallIncomingActivity.class));
break; break;
case PERMISSIONS_REQUEST_SYNC:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver());
} else {
ContactsManager.getInstance().initializeContactManager(getApplicationContext(), getContentResolver());
}
break;
} }
} }

View file

@ -48,10 +48,11 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
private static final long serialVersionUID = 9015568163905205244L; private static final long serialVersionUID = 9015568163905205244L;
private transient LinphoneFriend friend; private transient LinphoneFriend friend;
private String fullName, firstName, lastName, androidId; private String fullName, firstName, lastName, androidId, androidRawId, androidTagId;
private transient Uri photoUri, thumbnailUri; private transient Uri photoUri, thumbnailUri;
private List<LinphoneNumberOrAddress> addresses; private List<LinphoneNumberOrAddress> addresses;
private transient ArrayList<ContentProviderOperation> changesToCommit; private transient ArrayList<ContentProviderOperation> changesToCommit;
private transient ArrayList<ContentProviderOperation> changesToCommit2;
private boolean hasSipAddress; private boolean hasSipAddress;
public LinphoneContact() { public LinphoneContact() {
@ -60,6 +61,7 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
thumbnailUri = null; thumbnailUri = null;
photoUri = null; photoUri = null;
changesToCommit = new ArrayList<ContentProviderOperation>(); changesToCommit = new ArrayList<ContentProviderOperation>();
changesToCommit2 = new ArrayList<ContentProviderOperation>();
hasSipAddress = false; hasSipAddress = false;
} }
@ -138,10 +140,9 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
public void setPhoto(byte[] photo) { public void setPhoto(byte[] photo) {
if (photo != null) { if (photo != null) {
if (isAndroidContact()) { if (isAndroidContact()) {
String rawContactId = findRawContactID(getAndroidId()); if (androidRawId != null) {
if (rawContactId != null) {
changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) .withValue(ContactsContract.Data.RAW_CONTACT_ID, androidRawId)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo) .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photo)
.withValue(ContactsContract.Data.IS_PRIMARY, 1) .withValue(ContactsContract.Data.IS_PRIMARY, 1)
@ -200,6 +201,15 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
changesToCommit.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI) changesToCommit.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args) .withSelection(select, args)
.build()); .build());
if (androidTagId != null && noa.isSIPAddress()) {
select = ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.DATA1 + "=?";
args = new String[] { androidTagId, noa.getOldValue() };
changesToCommit.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.build());
}
} }
if (isLinphoneFriend()) { if (isLinphoneFriend()) {
@ -238,19 +248,37 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM); values.put(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM);
values.put(ContactsContract.CommonDataKinds.Phone.LABEL, ContactsManager.getInstance().getString(R.string.addressbook_label)); values.put(ContactsContract.CommonDataKinds.Phone.LABEL, ContactsManager.getInstance().getString(R.string.addressbook_label));
} }
if (androidRawId != null) {
String rawContactId = findRawContactID(getAndroidId());
if (rawContactId != null) {
changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) .withValue(ContactsContract.Data.RAW_CONTACT_ID, androidRawId)
.withValues(values) .withValues(values)
.build()); .build());
} else { } else {
changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValues(values) .withValues(values)
.build()); .build());
} }
if (noa.isSIPAddress() && LinphoneManager.getInstance().getContext().getResources().getBoolean(R.bool.use_linphone_tag)) {
if (androidTagId != null) {
changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, androidTagId)
.withValue(ContactsContract.Data.MIMETYPE, ContactsManager.getInstance().getString(R.string.sync_mimetype))
.withValue(ContactsContract.Data.DATA1, noa.getValue())
.withValue(ContactsContract.Data.DATA2, ContactsManager.getInstance().getString(R.string.app_name))
.withValue(ContactsContract.Data.DATA3, noa.getValue())
.build());
} else {
changesToCommit2.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsManager.getInstance().getString(R.string.sync_mimetype))
.withValue(ContactsContract.Data.DATA1, noa.getValue())
.withValue(ContactsContract.Data.DATA2, ContactsManager.getInstance().getString(R.string.app_name))
.withValue(ContactsContract.Data.DATA3, noa.getValue())
.build());
}
}
} else { } else {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
String select; String select;
@ -265,13 +293,28 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, noa.getValue()); values.put(ContactsContract.CommonDataKinds.Phone.NUMBER, noa.getValue());
} }
changesToCommit.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.withValues(values)
.build());
String rawContactId = findRawContactID(getAndroidId()); if (noa.isSIPAddress() && LinphoneManager.getInstance().getContext().getResources().getBoolean(R.bool.use_linphone_tag)) {
if (rawContactId != null) { if (androidTagId != null) {
changesToCommit.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI) changesToCommit.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args) .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.DATA1 + "=? ", new String[] { androidTagId, noa.getOldValue() })
.withValues(values) .withValue(ContactsContract.Data.DATA1, noa.getValue())
.build()); .withValue(ContactsContract.Data.DATA2, ContactsManager.getInstance().getString(R.string.app_name))
.withValue(ContactsContract.Data.DATA3, noa.getValue())
.build());
} else {
changesToCommit2.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsManager.getInstance().getString(R.string.sync_mimetype))
.withValue(ContactsContract.Data.DATA1, noa.getValue())
.withValue(ContactsContract.Data.DATA2, ContactsManager.getInstance().getString(R.string.app_name))
.withValue(ContactsContract.Data.DATA3, noa.getValue())
.build());
}
} }
} }
} }
@ -308,16 +351,19 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
return androidId; return androidId;
} }
public void save() { public void save() {
if (isAndroidContact() && ContactsManager.getInstance().hasContactsAccess() && changesToCommit.size() > 0) { if (isAndroidContact() && ContactsManager.getInstance().hasContactsAccess() && changesToCommit.size() > 0) {
try { try {
ContactsManager.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, changesToCommit); ContactsManager.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, changesToCommit);
createLinphoneTagIfNeeded();
} catch (Exception e) { } catch (Exception e) {
Log.e(e); Log.e(e);
} finally { } finally {
changesToCommit = new ArrayList<ContentProviderOperation>(); changesToCommit = new ArrayList<ContentProviderOperation>();
changesToCommit2 = new ArrayList<ContentProviderOperation>();
} }
} }
if (isLinphoneFriend()) { if (isLinphoneFriend()) {
boolean hasAddr = false; boolean hasAddr = false;
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
@ -386,17 +432,22 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
hasSipAddress = false; hasSipAddress = false;
if (isAndroidContact()) { if (isAndroidContact()) {
String id = getAndroidId(); getContactNames();
getContactNames(id); setThumbnailUri(getContactPictureUri());
setThumbnailUri(getContactPictureUri(id)); setPhotoUri(getContactPhotoUri());
setPhotoUri(getContactPhotoUri(id)); androidRawId = findRawContactID();
for (LinphoneNumberOrAddress noa : getAddressesAndNumbersForAndroidContact(id)) {
if (LinphoneManager.getInstance().getContext().getResources().getBoolean(R.bool.use_linphone_tag)) {
androidTagId = findLinphoneRawContactId();
}
for (LinphoneNumberOrAddress noa : getAddressesAndNumbersForAndroidContact()) {
addNumberOrAddress(noa); addNumberOrAddress(noa);
} }
if (friend == null) { if (friend == null) {
friend = LinphoneCoreFactory.instance().createLinphoneFriend(); friend = LinphoneCoreFactory.instance().createLinphoneFriend();
friend.setRefKey(id); friend.setRefKey(getAndroidId());
// Disable subscribes for now // Disable subscribes for now
friend.enableSubscribes(false); friend.enableSubscribes(false);
friend.setIncSubscribePolicy(SubscribePolicy.SPDeny); friend.setIncSubscribePolicy(SubscribePolicy.SPDeny);
@ -470,21 +521,21 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
return firstLetter.compareTo(contactfirstLetter); return firstLetter.compareTo(contactfirstLetter);
} }
private Uri getContactPictureUri(String id) { private Uri getContactPictureUri() {
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id)); Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(getAndroidId()));
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY); return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
} }
private Uri getContactPhotoUri(String id) { private Uri getContactPhotoUri() {
Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(id)); Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, Long.parseLong(getAndroidId()));
return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.DISPLAY_PHOTO); return Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.DISPLAY_PHOTO);
} }
private void getContactNames(String id) { private void getContactNames() {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver(); ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String[] proj = new String[]{ ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, ContactsContract.Contacts.DISPLAY_NAME }; String[] proj = new String[]{ ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, ContactsContract.Contacts.DISPLAY_NAME };
String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?"; String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?";
String[] args = new String[]{ id, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }; String[] args = new String[]{ getAndroidId(), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE };
Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, proj, select, args, null); Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, proj, select, args, null);
if (c != null) { if (c != null) {
if (c.moveToFirst()) { if (c.moveToFirst()) {
@ -496,13 +547,13 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
} }
} }
private String findRawContactID(String id) { private String findRawContactID() {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver(); ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String result = null; String result = null;
String[] projection = { ContactsContract.RawContacts._ID }; String[] projection = { ContactsContract.RawContacts._ID };
String selection = ContactsContract.RawContacts.CONTACT_ID + "=?"; String selection = ContactsContract.RawContacts.CONTACT_ID + "=?";
Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, new String[]{ id }, null); Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, new String[]{ getAndroidId() }, null);
if (c != null) { if (c != null) {
if (c.moveToFirst()) { if (c.moveToFirst()) {
result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID)); result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID));
@ -512,13 +563,13 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
return result; return result;
} }
private List<LinphoneNumberOrAddress> getAddressesAndNumbersForAndroidContact(String id) { private List<LinphoneNumberOrAddress> getAddressesAndNumbersForAndroidContact() {
List<LinphoneNumberOrAddress> result = new ArrayList<LinphoneNumberOrAddress>(); List<LinphoneNumberOrAddress> result = new ArrayList<LinphoneNumberOrAddress>();
ContentResolver resolver = ContactsManager.getInstance().getContentResolver(); ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String select = ContactsContract.Data.CONTACT_ID + " =? AND (" + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=?)"; String select = ContactsContract.Data.CONTACT_ID + " =? AND (" + ContactsContract.Data.MIMETYPE + "=? OR " + ContactsContract.Data.MIMETYPE + "=?)";
String[] projection = new String[] { ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, ContactsContract.Data.MIMETYPE }; // PHONE_NUMBER == SIP_ADDRESS == "data1"... String[] projection = new String[] { ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, ContactsContract.Data.MIMETYPE }; // PHONE_NUMBER == SIP_ADDRESS == "data1"...
Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, projection, select, new String[]{ id, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE }, null); Cursor c = resolver.query(ContactsContract.Data.CONTENT_URI, projection, select, new String[]{ getAndroidId(), ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE }, null);
if (c != null) { if (c != null) {
while (c.moveToNext()) { while (c.moveToNext()) {
String mime = c.getString(c.getColumnIndex(ContactsContract.Data.MIMETYPE)); String mime = c.getString(c.getColumnIndex(ContactsContract.Data.MIMETYPE));
@ -551,12 +602,14 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
private static LinphoneContact createAndroidContact() { private static LinphoneContact createAndroidContact() {
LinphoneContact contact = new LinphoneContact(); LinphoneContact contact = new LinphoneContact();
contact.changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) contact.changesToCommit.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT) .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.build()); .build());
contact.setAndroidId("0"); contact.setAndroidId("0");
return contact; return contact;
} }
@ -569,4 +622,63 @@ public class LinphoneContact implements Serializable, Comparable<LinphoneContact
contact.friend = friend; contact.friend = friend;
return contact; return contact;
} }
private String findLinphoneRawContactId() {
ContentResolver resolver = ContactsManager.getInstance().getContentResolver();
String result = null;
String[] projection = { ContactsContract.RawContacts._ID };
String selection = ContactsContract.RawContacts.CONTACT_ID + "=? AND " + ContactsContract.RawContacts.ACCOUNT_TYPE + "=?";
Cursor c = resolver.query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, new String[] { getAndroidId(), ContactsManager.getInstance().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 void createLinphoneTagIfNeeded() {
if (LinphoneManager.getInstance().getContext().getResources().getBoolean(R.bool.use_linphone_tag)) {
if (androidTagId == null && findLinphoneRawContactId() == null) {
createLinphoneContactTag();
}
}
}
private void createLinphoneContactTag() {
ArrayList<ContentProviderOperation> batch = new ArrayList<ContentProviderOperation>();
batch.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, ContactsManager.getInstance().getString(R.string.sync_account_type))
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, ContactsManager.getInstance().getString(R.string.sync_account_name))
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.build());
batch.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, getFullName())
.build());
batch.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI)
.withValue(ContactsContract.AggregationExceptions.TYPE, ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER)
.withValue(ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, androidRawId)
.withValueBackReference(ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, 0)
.build());
if (changesToCommit2.size() > 0) {
for(ContentProviderOperation cpo : changesToCommit2) {
batch.add(cpo);
}
}
try {
ContactsManager.getInstance().getContentResolver().applyBatch(ContactsContract.AUTHORITY, batch);
androidTagId = findLinphoneRawContactId();
} catch (Exception e) {
Log.e(e);
}
}
} }

View file

@ -3,12 +3,9 @@ package org.linphone.compatibility;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.linphone.Contact;
import org.linphone.LinphoneContact; import org.linphone.LinphoneContact;
import org.linphone.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneAddress;
import org.linphone.mediastream.Log;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
@ -195,89 +192,4 @@ public class ApiNinePlus {
cursor.close(); cursor.close();
return null; return null;
} }
//Linphone Contacts Tag
public static void addLinphoneContactTag(Context context, ArrayList<ContentProviderOperation> 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<ContentProviderOperation> 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<ContentProviderOperation> ops , String oldAddress, String rawContactId){
if(rawContactId != null) {
String select = ContactsContract.Data.RAW_CONTACT_ID + "=? AND "
+ ContactsContract.Data.DATA1 + "= ?";
String[] args = new String[]{rawContactId, oldAddress};
ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.build());
}
}
public static void createLinphoneContactTag(Context context, ContentResolver contentResolver, Contact contact, String rawContactId){
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
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<String> 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) {
Log.e(e);
}
}
}
} }

View file

@ -21,7 +21,6 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.linphone.Contact;
import org.linphone.LinphoneContact; import org.linphone.LinphoneContact;
import org.linphone.core.LinphoneAddress; import org.linphone.core.LinphoneAddress;
import org.linphone.mediastream.Version; import org.linphone.mediastream.Version;
@ -301,32 +300,6 @@ public class Compatibility {
ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID); ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
} }
//Linphone Contacts Tag
public static void addLinphoneContactTag(Context context, ArrayList<ContentProviderOperation> 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<ContentProviderOperation> 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<ContentProviderOperation> 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) { public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) { if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
ApiSixteenPlus.removeGlobalLayoutListener(viewTreeObserver, keyboardListener); ApiSixteenPlus.removeGlobalLayoutListener(viewTreeObserver, keyboardListener);