Re-add sip contact address
Add linphone tag in native contact app Add message to avoid delete contact too easily Migrate old contact with im to sipAddress
This commit is contained in:
parent
885743b8fe
commit
135361c563
25 changed files with 711 additions and 167 deletions
|
@ -37,6 +37,9 @@
|
|||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
|
||||
|
||||
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true"/>
|
||||
|
||||
|
@ -45,6 +48,7 @@
|
|||
<activity android:name="org.linphone.LinphoneLauncherActivity"
|
||||
android:label="@string/app_name"
|
||||
android:windowSoftInputMode="adjustPan|stateHidden"
|
||||
android:exported="true"
|
||||
android:theme="@style/NoTitle">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
@ -56,7 +60,7 @@
|
|||
<action android:name="android.intent.action.CALL_PRIVILEGED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="tel" />
|
||||
<data android:scheme="sip" />
|
||||
<data android:scheme="sip" /> />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
|
@ -64,14 +68,16 @@
|
|||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:scheme="sip" />
|
||||
<data android:scheme="imto" />
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<data android:scheme="sip" />
|
||||
<data android:mimeType="vnd.android.cursor.item/org.linphone.profile" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name="org.linphone.LinphoneActivity"
|
||||
|
@ -81,7 +87,6 @@
|
|||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name="org.linphone.IncomingCallActivity"
|
||||
|
@ -154,6 +159,26 @@
|
|||
android:label="@string/service_name"
|
||||
android:stopWithTask="false"/>
|
||||
|
||||
<service
|
||||
android:name="org.linphone.sync.SyncService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.content.SyncAdapter" android:resource="@xml/syncadapter" />
|
||||
<meta-data android:name="android.provider.CONTACTS_STRUCTURE" android:resource="@xml/contacts" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name="org.linphone.sync.AuthenticationService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator"/>
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
|
||||
<receiver android:name="org.linphone.NetworkManager">
|
||||
<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action></intent-filter>
|
||||
</receiver>
|
||||
|
|
|
@ -242,6 +242,19 @@
|
|||
android:visibility="gone"
|
||||
android:layout_alignParentRight="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/voicemailCount"
|
||||
android:textColor="@android:color/white"
|
||||
android:layout_alignParentRight="true"
|
||||
android:textSize="18sp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/exit"
|
||||
android:text="@string/menu_exit"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="history_date_format">d MMM</string>
|
||||
<string name="history_detail_date_format">EEEE MMM d HH:mm</string>
|
||||
<string name="messages_date_format">HH:mm d MMM</string>
|
||||
|
@ -10,6 +9,9 @@
|
|||
<string name="app_name">Linphone</string>
|
||||
<string name="service_name">Linphone Service</string>
|
||||
<string name="addressbook_label">Linphone</string>
|
||||
<string name="sync_account_type">org.linphone</string>
|
||||
<string name="sync_account_name">linphone contacts</string>
|
||||
<string name="sync_mimetype">vnd.android.cursor.item/org.linphone.profile</string>
|
||||
<string name="notification_title">Linphone</string>
|
||||
<string name="wait_dialog_text">Starting up</string>
|
||||
<string name="notification_registered">Registered to %s </string>
|
||||
|
@ -23,7 +25,6 @@
|
|||
<string name="setup_login_generic">I already have a SIP account</string>
|
||||
<string name="setup_linphone_account_hint">Enter your linphone.org username and password</string>
|
||||
<string name="setup_general_account_hint">Enter your SIP account username, password and domain</string>
|
||||
|
||||
<string name="setup_username_hint">username</string>
|
||||
|
||||
<string name="tunnel_host"></string>
|
||||
|
|
|
@ -353,6 +353,7 @@
|
|||
<string name="pref_image_sharing_server_title">Sharing server</string>
|
||||
<string name="pref_remote_provisioning_title">Remote provisioning</string>
|
||||
<string name="delete_contact">Delete</string>
|
||||
<string name="delete_contact_dialog">This contact will be deleted.</string>
|
||||
<string name="sip_address">SIP address</string>
|
||||
<string name="phone_number">Phone number</string>
|
||||
<string name="contact_first_name">First name</string>
|
||||
|
|
8
res/xml/authenticator.xml
Normal file
8
res/xml/authenticator.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<account-authenticator
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:accountType="org.linphone"
|
||||
android:icon="@drawable/logo_linphone_57x57"
|
||||
android:smallIcon="@drawable/logo_linphone_57x57"
|
||||
android:label="@string/app_name"/>
|
13
res/xml/contacts.xml
Normal file
13
res/xml/contacts.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ContactsSource
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<ContactsDataKind
|
||||
android:mimeType="vnd.android.cursor.item/org.linphone.profile"
|
||||
android:icon="@drawable/logo_linphone_57x57"
|
||||
android:summaryColumn="data2"
|
||||
android:detailColumn="data3"
|
||||
android:detailSocialSummary="true"/>
|
||||
|
||||
</ContactsSource>
|
7
res/xml/syncadapter.xml
Normal file
7
res/xml/syncadapter.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:contentAuthority="com.android.contacts"
|
||||
android:accountType="org.linphone"
|
||||
android:supportsUploading="false"
|
||||
android:userVisible="false"/>
|
|
@ -38,7 +38,7 @@ public class Contact implements Serializable {
|
|||
private String name;
|
||||
private transient Uri photoUri;
|
||||
private transient Bitmap photo;
|
||||
private List<String> numerosOrAddresses;
|
||||
private List<String> numbersOrAddresses;
|
||||
private LinphoneFriend friend;
|
||||
|
||||
public Contact(String id, String name) {
|
||||
|
@ -88,14 +88,14 @@ public class Contact implements Serializable {
|
|||
return photo;
|
||||
}
|
||||
|
||||
public List<String> getNumerosOrAddresses() {
|
||||
if (numerosOrAddresses == null)
|
||||
numerosOrAddresses = new ArrayList<String>();
|
||||
return numerosOrAddresses;
|
||||
public List<String> getNumbersOrAddresses() {
|
||||
if (numbersOrAddresses == null)
|
||||
numbersOrAddresses = new ArrayList<String>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,10 +223,18 @@ public class ContactFragment extends Fragment implements OnClickListener {
|
|||
if (id == R.id.editContact) {
|
||||
LinphoneActivity.instance().editContact(contact);
|
||||
} else if (id == R.id.deleteContact) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteExistingContact() {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -98,6 +99,35 @@ public final class ContactHelper {
|
|||
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));
|
||||
|
||||
|
@ -180,12 +210,50 @@ 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;
|
||||
}
|
||||
}
|
|
@ -197,10 +197,16 @@ public class DialerFragment extends Fragment {
|
|||
mAddress.setText("sip:" + intent.getData().getLastPathSegment());
|
||||
} else if (scheme.startsWith("call") || scheme.startsWith("sip")) {
|
||||
mAddress.setText(intent.getData().getSchemeSpecificPart());
|
||||
} else {
|
||||
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();
|
||||
intent.setData(null);
|
||||
|
|
|
@ -201,7 +201,7 @@ public class EditContactFragment extends Fragment {
|
|||
numbersAndAddresses = new ArrayList<NewOrUpdatedNumberOrAddress>();
|
||||
|
||||
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,8 +359,11 @@ public class EditContactFragment extends Fragment {
|
|||
contactID = 0;
|
||||
|
||||
ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
|
||||
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
|
||||
.withValue(RawContacts.ACCOUNT_TYPE, null)
|
||||
.withValue(RawContacts.ACCOUNT_NAME, null).build());
|
||||
.withValue(RawContacts.ACCOUNT_NAME, null)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (getDisplayName() != null) {
|
||||
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
||||
|
@ -400,8 +404,7 @@ 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[]{RawContacts._ID},RawContacts.CONTACT_ID + "=?",
|
||||
new String[]{contactID}, null);
|
||||
if (c != null) {
|
||||
String result = null;
|
||||
|
@ -414,6 +417,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,
|
||||
new String[]{ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME},
|
||||
|
@ -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 "
|
||||
|
@ -532,13 +554,14 @@ public class EditContactFragment extends Fragment {
|
|||
}
|
||||
} 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.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 "
|
||||
|
|
|
@ -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<FragmentsAvailable>();
|
||||
|
@ -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<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
||||
|
||||
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();
|
||||
|
@ -1105,12 +1166,19 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
|
|||
@Override
|
||||
public void run() {
|
||||
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());
|
||||
//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 (!isContactPresenceDisabled) {
|
||||
searchFriendAndAddToContact(contact);
|
||||
}
|
||||
|
@ -1120,6 +1188,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
|
|||
if(contactCursor != null){
|
||||
for (int i = 0; i < contactCursor.getCount(); i++) {
|
||||
Contact contact = Compatibility.getContact(getContentResolver(), contactCursor, i);
|
||||
|
||||
if (contact == null)
|
||||
continue;
|
||||
|
||||
|
@ -1132,6 +1201,7 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene
|
|||
contactList.add(contact);
|
||||
}
|
||||
}
|
||||
getContentResolver().requestSync(mAccount, ContactsContract.AUTHORITY, new Bundle());
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -134,7 +134,6 @@ public class StatusFragment extends Fragment {
|
|||
});
|
||||
}
|
||||
// setMiniLedsForEachAccount();
|
||||
populateSliderContent();
|
||||
populateSliderContent();
|
||||
sliderContentAccounts.invalidate();
|
||||
} catch (IllegalStateException ise) {}
|
||||
|
@ -167,7 +166,6 @@ 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);
|
||||
|
|
|
@ -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<ContentValues> data = new ArrayList<ContentValues>();
|
||||
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<ContentValues> data = new ArrayList<ContentValues>();
|
||||
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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -46,12 +47,10 @@ public class ApiNinePlus {
|
|||
public static void addSipAddressToContact(Context context, ArrayList<ContentProviderOperation> 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))
|
||||
.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()
|
||||
);
|
||||
}
|
||||
|
@ -59,35 +58,33 @@ public class ApiNinePlus {
|
|||
public static void addSipAddressToContact(Context context, ArrayList<ContentProviderOperation> 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))
|
||||
.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<ContentProviderOperation> ops, String oldIm, String newIm, String contactID) {
|
||||
public static void updateSipAddressForContact(ArrayList<ContentProviderOperation> ops, String oldSipAddress, String newSipAddress, 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 };
|
||||
+ 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)
|
||||
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
|
||||
.withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newSipAddress)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
public static void deleteSipAddressFromContact(ArrayList<ContentProviderOperation> ops, String oldIm, String contactID) {
|
||||
public static void deleteSipAddressFromContact(ArrayList<ContentProviderOperation> ops, String oldSipAddress, 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 };
|
||||
+ 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<String> list = new ArrayList<String>();
|
||||
|
||||
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);
|
||||
|
@ -111,27 +108,6 @@ 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 + "%'";
|
||||
|
@ -187,15 +157,11 @@ public class ApiNinePlus {
|
|||
|
||||
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<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) {
|
||||
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<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) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,10 @@ public class Compatibility {
|
|||
}
|
||||
}
|
||||
|
||||
public static List<String> extractContactImAddresses(String id, ContentResolver cr) {
|
||||
return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
|
||||
}
|
||||
|
||||
public static Cursor getContactsCursor(ContentResolver cr) {
|
||||
if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
|
||||
return ApiNinePlus.getContactsCursor(cr, null);
|
||||
|
@ -112,6 +116,10 @@ public class Compatibility {
|
|||
}
|
||||
}
|
||||
|
||||
public static Cursor getImContactsCursor(ContentResolver cr) {
|
||||
return ApiFivePlus.getSIPContactsCursor(cr);
|
||||
}
|
||||
|
||||
public static int getCursorDisplayNameColumnIndex(Cursor cursor) {
|
||||
if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
|
||||
return ApiFivePlus.getCursorDisplayNameColumnIndex(cursor);
|
||||
|
@ -262,6 +270,35 @@ public class Compatibility {
|
|||
}
|
||||
}
|
||||
|
||||
public static void deleteImAddressFromContact(ArrayList<ContentProviderOperation> ops, String oldSipAddress, String 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) {
|
||||
if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
|
||||
|
|
39
src/org/linphone/sync/AuthenticationService.java
Normal file
39
src/org/linphone/sync/AuthenticationService.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
85
src/org/linphone/sync/Authenticator.java
Normal file
85
src/org/linphone/sync/Authenticator.java
Normal file
|
@ -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();
|
||||
}
|
||||
}
|
40
src/org/linphone/sync/SyncAdapter.java
Executable file
40
src/org/linphone/sync/SyncAdapter.java
Executable file
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
45
src/org/linphone/sync/SyncService.java
Executable file
45
src/org/linphone/sync/SyncService.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue