I want to display my application name and icon on the user contact details like whatsapp icon.I will try to syncAdapter for this purpose.But i can not get in output.If anyone can you help me?
Authenticator Classs
public class Authenticator extends AbstractAccountAuthenticator {
private final Context mContext;
public Authenticator(Context context) {
super(context);
mContext = context;
}
@Override
public Bundle editProperties(AccountAuthenticatorResponse response,
String accountType) {
return null;
}
@Override
public Bundle addAccount(AccountAuthenticatorResponse response,
String accountType, String authTokenType, String[] requiredFeatures,
Bundle options) throws NetworkErrorException {
final Intent intent = new Intent(mContext, MainActivity.class);
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
final Bundle bundle = new Bundle();
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
return bundle;
}
@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle options) throws NetworkErrorException {
final Bundle result = new Bundle();
result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
result.putString(AccountManager.KEY_ACCOUNT_TYPE, SyncStateContract.Constants.ACCOUNT_TYPE);
return result;
}
@Override
public String getAuthTokenLabel(String authTokenType) {
return null;
}
@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle options) throws NetworkErrorException {
return null;
}
@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
String[] features) throws NetworkErrorException {
return null;
}
}
AuthenticatorService Class
public class AuthenticatorService extends Service {
private Authenticator authenticator;
@Override
public void onCreate() {
authenticator = new Authenticator(this);
}
/*
* When the system binds to this Service to make the RPC call
* return the authenticator’s IBinder.
*/
@Override
public IBinder onBind(Intent intent) {
return authenticator.getIBinder();
}
}
ContactManager Class
public class ContactsManager {
private static String MIMETYPE = "vnd.android.cursor.item/com.example.syncadapter";
public static void addContact(Context context,MyContact contact){
ContentResolver resolver = context.getContentResolver();
ArrayList<ContentProviderOperation> ops =
new ArrayList<ContentProviderOperation>();
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(
ContactsContract.RawContacts.CONTENT_URI, true))
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME,
SyncStateContract.Constants.ACCOUNT_NAME)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE,
SyncStateContract.Constants.ACCOUNT_TYPE)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.build());
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(
ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
contact.name)
.build());
ops.add(ContentProviderOperation
.newInsert(addCallerIsSyncAdapterParameter(
ContactsContract.Data.CONTENT_URI, true))
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID,0)
.withValue(ContactsContract.Data.MIMETYPE, MIMETYPE)
.withValue(ContactsContract.Data.DATA1, 12345)
.withValue(ContactsContract.Data.DATA2, "user")
.withValue(ContactsContract.Data.DATA3, "MyData")
.build());
try {
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
}
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;
}
}
MainActivity Class
ublic class MainActivity extends AppCompatActivity {
private ArrayList<String> mNames = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Retrieve names from phone's contact list and save in mNames
getNames();
// Apply changes to phone's contact list
new Thread(new Runnable() {
@Override
public void run() {
String name;
for(int i=0;i<mNames.size();i++){
name = mNames.get(i);
ContactsManager.addContact(MainActivity.this, new MyContact(name));
}
}
}).start();
}
private void getNames(){
int hasPhone;
Cursor c = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null,null,null,null);
if((c != null) && c.moveToFirst()){
while(c.moveToNext()){
hasPhone = Integer.parseInt(c.getString(
c.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if(hasPhone == 1)
mNames.add(c.getString(
c.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)));
}
c.close();
}
}
}
MyContact Class for getting user name
public class MyContact {
String name;
public MyContact(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyContact)) return false;
MyContact myContact = (MyContact) o;
return Objects.equals(name, myContact.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
SyncAdapter class
public class SyncAdapter extends AbstractThreadedSyncAdapter {
public SyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
Log.d("sync adapter","Sync Adapter created.");
}
@Override
public void onPerformSync(Account account, Bundle extras,
String authority, ContentProviderClient provider,
SyncResult syncResult) {
Log.d("sync adapter","Sync Adapter called.");
}
}
SyncService class
public class SyncService extends Service {
private static final Object sSyncAdapterLock = new Object();
private static SyncAdapter mSyncAdapter = null;
@Override
public void onCreate() {
Log.d("sync adapter","Sync Service created.");
synchronized (sSyncAdapterLock){
if(mSyncAdapter == null){
mSyncAdapter = new SyncAdapter(getApplicationContext(),
true);
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("sync adapter","Sync Service binded.");
return mSyncAdapter.getSyncAdapterBinder();
}
}
Authenticator xml file
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.example.ajay.contacts_4"
android:icon="@mipmap/ic_launcher"
android:smallIcon="@mipmap/ic_launcher"
android:label="@string/app_name" />
Contact xml file
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">
<ContactsDataKind
android:mimeType="vnd.android.cursor.item/com.example.syncadapter.message"
android:icon="@mipmap/ic_launcher"
android:summaryColumn="data2"
android:detailColumn="data3"/>
<ContactsDataKind
android:mimeType="vnd.android.cursor.item/com.example.syncadapter.voice"
android:icon="@mipmap/ic_launcher"
android:summaryColumn="data2"
android:detailColumn="data3"/>
<ContactsDataKind
android:mimeType="vnd.android.cursor.item/com.example.syncadapter.video"
android:icon="@mipmap/ic_launcher"
android:summaryColumn="data2"
android:detailColumn="data3"/>
</ContactsAccountType>
SyncAdapter xml file
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.example.syncadapter"
android:supportsUploading="false"
android:userVisible="true"/>
Manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.syncadapter">
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SyncAdapter"
tools:targetApi="31">
<activity
android:name=".AuthenticatorActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:mimeType="vnd.android.cursor.item/com.example.syncadapter.message" />
</intent-filter>
</activity>
<service android:name=".AuthenticatorService"
tools:ignore="Instantiatable"
android:exported="true">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<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>
</application>
</manifest>
