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:
Margaux Clerc 2015-03-23 17:41:10 +01:00
parent 885743b8fe
commit 135361c563
25 changed files with 711 additions and 167 deletions

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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>

View 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
View 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
View 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"/>

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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;
}
}

View file

@ -198,9 +198,15 @@ public class DialerFragment extends Fragment {
} else if (scheme.startsWith("call") || scheme.startsWith("sip")) {
mAddress.setText(intent.getData().getSchemeSpecificPart());
} else {
Log.e("Unknown scheme: ",scheme);
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);

View file

@ -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 "

View file

@ -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,21 +1166,29 @@ 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);
}
sipContactList.add(contact);
}
}
if(contactCursor != null) {
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)

View file

@ -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);
}
}

View file

@ -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;
/**

View file

@ -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);

View file

@ -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);

View file

@ -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();

View file

@ -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();
}
}
}
}

View file

@ -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)) {

View 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();
}
}

View 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();
}
}

View 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) {
}
}

View 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();
}
}