Skip to content

Instantly share code, notes, and snippets.

@ryanamaral
Forked from Sunno/AndroidManifest.xml
Created July 30, 2020 02:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanamaral/470dc9327627ae419b394e02d0cc7853 to your computer and use it in GitHub Desktop.
Save ryanamaral/470dc9327627ae419b394e02d0cc7853 to your computer and use it in GitHub Desktop.
Set a custom contact item in android address book
/**
* This code is based in https://github.com/nemezis/SampleContacts
* I'm just explaining it, since I lost a lot of time figuring out how it really works
* **/
package com.my_app;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Contacts;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.Settings;
import android.webkit.WebChromeClient.CustomViewCallback;
public class ContactsManager {
// this must be exactly mime type defined in contacts.xml
private static String MIMETYPE = "vnd.android.cursor.item/com.my_app.contact_item";
public static void addContact(Context context, MyContact contact) { // My Contact object is a custom object made by you
ContentResolver resolver = context.getContentResolver();
resolver.delete(RawContacts.CONTENT_URI, RawContacts.ACCOUNT_TYPE + " = ?", new String[] { AccountGeneral.ACCOUNT_TYPE });
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
/**
* this is very important, if you want to add this raw contact to a contact (please refer to android contact provider guide in order to get the difference)
* my advise is you to add contact id manually, even though most times android does this automatically.
* **/
int contact_id = 1234;
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI, true))
.withValue(RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.CONTACT_ID, contact_id)
.build());
// this is for display name
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Settings.CONTENT_URI, true))
.withValue(RawContacts.ACCOUNT_NAME, AccountGeneral.ACCOUNT_NAME)
.withValue(RawContacts.ACCOUNT_TYPE, AccountGeneral.ACCOUNT_TYPE)
.withValue(Settings.UNGROUPED_VISIBLE, 1)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.GIVEN_NAME, contact.name)
.withValue(StructuredName.FAMILY_NAME, contact.lastName)
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "12342145")
.build());
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, "sample@email.com")
.build());
//This is our custom data field in our contact
ops.add(ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, MIMETYPE)
.withValue(Data.DATA1, 12345)
.withValue(Data.DATA2, "sample")
.withValue(Data.DATA3, "sample")
.build());
try {
ContentProviderResult[] results = resolver.applyBatch(ContactsContract.AUTHORITY, ops);
if (results.length == 0)
;
}
catch (Exception e) {
e.printStackTrace();
}
}
private static Uri addCallerIsSyncAdapterParameter(Uri uri, boolean isSyncOperation) {
if (isSyncOperation) {
return uri.buildUpon()
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.build();
}
return uri;
}
public static List<MyContact> getMyContacts() {
return null;
}
public static void updateMyContact(Context context, String name) {
int id = -1;
Cursor cursor = context.getContentResolver().query(Data.CONTENT_URI, new String[] { Data.RAW_CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.CONTACT_ID },
StructuredName.DISPLAY_NAME + "= ?",
new String[] {name}, null);
if (cursor != null && cursor.moveToFirst()) {
do {
id = cursor.getInt(0);
Log.i(cursor.getString(0));
Log.i(cursor.getString(1));
Log.i(cursor.getString(2));
Log.i(cursor.getString(3));
} while (cursor.moveToNext());
}
if (id != -1) {
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValue(Data.RAW_CONTACT_ID, id)
.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE)
.withValue(Email.DATA, "sample")
.build());
ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValue(Data.RAW_CONTACT_ID, id)
.withValue(Data.MIMETYPE, MIMETYPE)
.withValue(Data.DATA1, "profile")
.withValue(Data.DATA2, "profile")
.withValue(Data.DATA3, "profile")
.build());
try {
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
}
catch (Exception e) {
e.printStackTrace();
}
}
else {
Log.i("id not found");
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my_app" >
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<!-- for syncing -->
<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" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<application
android:allowBackup="true"
android:icon="@drawable/my_icon"
android:label="@string/app_name"
android:theme="@style/AppTheme"
>
<service
android:name=".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>
<!-- IMPORTANT: this activity is mandatory since it will not show your app icon in contact details if you ommit this
Actually omiting this made me lose a lot ot time -->
<!-- MimeType must be the same you defined in contacts.xml -->
<activity android:name=".ViewDataACtivity" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/com.my_app.contact_item" />
</intent-filter>
</activity>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<ContactsSource xmlns:android="http://schemas.android.com/apk/res/android">
<ContactsDataKind
android:mimeType="vnd.android.cursor.item/com.my_app.contact_item"
android:icon="@drawable/ic_launcher"
android:summaryColumn="data2"
android:detailColumn="data3"/>
</ContactsSource>
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.my_app"
android:contentAuthority="com.android.contacts" <!-- mandatory to set exactly this -->
android:userVisible="true"
android:supportsUploading="false"/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment