如何使用自定义IM添加原始联系人?

时间:2016-01-26 10:20:36

标签: android android-contentprovider android-contacts

在我的同步适配器下面。在我添加StubAdapter(自动同步所需)之前,performSync方法创建了联系人,我的应用程序标签。添加SubAdapter后,自动同步有效,但新创建的帐户不再显示应用程序图标,它们属于gmail帐户,而不是我的应用帐户。我在哪里犯了错误以及如何解决它?

SyncAdapter

public class ContactsSyncAdapterService extends Service {
  private static SyncAdapterImpl sSyncAdapter = null;

  public ContactsSyncAdapterService() {
    super();
  }

  private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
    private Context mContext;

    public SyncAdapterImpl(Context context) {
      super(context, true);
      mContext = context;
    }

    @Override public void onPerformSync(Account account, Bundle extras, String authority,
        ContentProviderClient provider, SyncResult syncResult) {
      try {
        ContactsSyncAdapterService.performSync(mContext, account, extras, authority, provider,
            syncResult);
      } catch (OperationCanceledException e) {
      }
    }
  }

  @Override public IBinder onBind(Intent intent) {
    IBinder ret = null;
    ret = getSyncAdapter().getSyncAdapterBinder();
    return ret;
  }

  private SyncAdapterImpl getSyncAdapter() {
    if (sSyncAdapter == null) sSyncAdapter = new SyncAdapterImpl(this);
    return sSyncAdapter;
  }

  private static void performSync(Context context, Account account, Bundle extras, String authority,
      ContentProviderClient provider, SyncResult syncResult) throws OperationCanceledException {
    Cursor c = context.getContentResolver()
        .query(addCallerIsSyncAdapterParameter(ContactsProvider.CONTENT_URI, true), null, null,
            null, null);
    context.getContentResolver()
        .delete(addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI, true),
            RawContacts.ACCOUNT_TYPE + " = ?", new String[] { "packgename" });
    while (c.moveToNext()) {
      ContactsManager.addContact(context, account, new MyContact(c));
    }
    c.close();
  }

  private static Uri addCallerIsSyncAdapterParameter(Uri uri, boolean isSyncOperation) {
    if (isSyncOperation) {
      return uri.buildUpon()
          .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
          .build();
    }
    return uri;
  }
}

添加联系功能

private static String MIMETYPE = "vnd.android.cursor.item/vnd.packagename.profile";

  public static void addContact(Context context, Account account, MyContact contact) {
    Log.e("mcheck", contact.toString());
    ContentResolver resolver = context.getContentResolver();

    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

    ops.add(ContentProviderOperation.newInsert(
        addCallerIsSyncAdapterParameter(RawContacts.CONTENT_URI, true))
        .withValue(RawContacts.ACCOUNT_NAME, account.name).withValue(RawContacts.ACCOUNT_TYPE,
            account.type)
            //.withValue(RawContacts.SOURCE_ID, 12345)
            //.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED)
        .build());

    ops.add(ContentProviderOperation.newInsert(
        addCallerIsSyncAdapterParameter(Settings.CONTENT_URI, true))
        .withValue(RawContacts.ACCOUNT_NAME, account.name)
        .withValue(RawContacts.ACCOUNT_TYPE, 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.DISPLAY_NAME, contact.name)
            .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, contact.phone)
            .build());
    ops.add(
        ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
            .withValueBackReference(Data.RAW_CONTACT_ID, 0)
            .withValue(ContactsContract.Data.MIMETYPE,
                ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE)
            .withValue(ContactsContract.CommonDataKinds.Note.NOTE, contact.note)
            .build());
    if (!TextUtils.isEmpty(contact.email)) {
      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, contact.email)
          .build());
    }

    ops.add(
        ContentProviderOperation.newInsert(addCallerIsSyncAdapterParameter(Data.CONTENT_URI, true))
            .withValueBackReference(Data.RAW_CONTACT_ID, 0)
            .withValue(Data.MIMETYPE, MIMETYPE)
            .withValue(Data.DATA1, contact.id)
            .withValue(Data.DATA3, "Открыть профиль")
            .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;
  }

authenticator.xml

<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="packgename"
    android:icon="@drawable/ic_auth_sync"
    android:smallIcon="@drawable/ic_auth_sync_small"
    android:label="@string/app_name"
    android:accountPreferences="@xml/account_preferences"
    android:supportsUploading="false"/>

自定义联系人数据类型

<ContactsSource xmlns:android="http://schemas.android.com/apk/res/android">
  <ContactsDataKind
      android:icon="@drawable/ic_auth_sync"
      android:mimeType="vnd.android.cursor.item/vnd.packgename.profile"
      android:summaryColumn="data2"
      android:detailColumn="data3"
      />
</ContactsSource> 

同步adapter.xml

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
    android:accountType="packgename"
    android:supportsUploading="true"
    android:contentAuthority="packgename.sync.provider"
    android:isAlwaysSyncable="true"
    android:userVisible="true"
    />

StubAdapter

public class StubProvider extends ContentProvider {
  /*
   * Always return true, indicating that the
   * provider loaded correctly.
   */
  @Override public boolean onCreate() {
    return true;
  }

  /*
   * Return no type for MIME type
   */
  @Override public String getType(Uri uri) {
    return null;
  }

  /*
   * query() always returns no results
   *
   */
  @Override public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String sortOrder) {
    return null;
  }

  /*
   * insert() always returns null (no URI)
   */
  @Override public Uri insert(Uri uri, ContentValues values) {
    return null;
  }

  /*
   * delete() always returns "no rows affected" (0)
   */
  @Override public int delete(Uri uri, String selection, String[] selectionArgs) {
    return 0;
  }

  /*
   * update() always returns "no rows affected" (0)
   */
  public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    return 0;
  }
}

身份验证

public class AccountAuthenticatorService extends Service {
  private static final String TAG = "AccountSAS";
  private static AccountAuthenticatorImpl sAccountAuthenticator = null;

  public AccountAuthenticatorService() {
    super();
  }

  @Override public IBinder onBind(Intent intent) {
    IBinder ret = null;
    if (intent.getAction().equals(AccountManager.ACTION_AUTHENTICATOR_INTENT)) {
      ret = getAuthenticator().getIBinder();
    }
    return ret;
  }

  private AccountAuthenticatorImpl getAuthenticator() {
    if (sAccountAuthenticator == null) sAccountAuthenticator = new AccountAuthenticatorImpl(this);
    return sAccountAuthenticator;
  }

  private static class AccountAuthenticatorImpl extends AbstractAccountAuthenticator {
    private Context mContext;

    public AccountAuthenticatorImpl(Context context) {
      super(context);
      mContext = context;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#addAccount(android.
     * accounts.AccountAuthenticatorResponse, java.lang.String,
     * java.lang.String, java.lang.String[], android.os.Bundle)
     */
    @Override public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
        String authTokenType, String[] requiredFeatures, Bundle options)
        throws NetworkErrorException {
      Bundle result = new Bundle();
      Intent i = new Intent(mContext, packgename.view.activity.LoginActivity.class);
      i.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response);
      result.putParcelable(AccountManager.KEY_INTENT, i);
      return result;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#confirmCredentials(
     * android.accounts.AccountAuthenticatorResponse,
     * android.accounts.Account, android.os.Bundle)
     */
    @Override public Bundle confirmCredentials(AccountAuthenticatorResponse response,
        Account account, Bundle options) {
      // TODO Auto-generated method stub
      Log.i(TAG, "confirmCredentials");
      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#editProperties(android
     * .accounts.AccountAuthenticatorResponse, java.lang.String)
     */
    @Override public Bundle editProperties(AccountAuthenticatorResponse response,
        String accountType) {
      // TODO Auto-generated method stub
      Log.i(TAG, "editProperties");
      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#getAuthToken(android
     * .accounts.AccountAuthenticatorResponse, android.accounts.Account,
     * java.lang.String, android.os.Bundle)
     */
    @Override public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
        String authTokenType, Bundle options) throws NetworkErrorException {
      // TODO Auto-generated method stub

      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#getAuthTokenLabel(java
     * .lang.String)
     */
    @Override public String getAuthTokenLabel(String authTokenType) {
      // TODO Auto-generated method stub
      Log.i(TAG, "getAuthTokenLabel");
      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#hasFeatures(android
     * .accounts.AccountAuthenticatorResponse, android.accounts.Account,
     * java.lang.String[])
     */
    @Override public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
        String[] features) throws NetworkErrorException {
      // TODO Auto-generated method stub
      Log.i(TAG, "hasFeatures: " + features);
      return null;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * android.accounts.AbstractAccountAuthenticator#updateCredentials(android
     * .accounts.AccountAuthenticatorResponse, android.accounts.Account,
     * java.lang.String, android.os.Bundle)
     */
    @Override public Bundle updateCredentials(AccountAuthenticatorResponse response,
        Account account, String authTokenType, Bundle options) {
      // TODO Auto-generated method stub
      Log.i(TAG, "updateCredentials");
      return null;
    }
  }
}

0 个答案:

没有答案