Example usage for android.provider ContactsContract AUTHORITY

List of usage examples for android.provider ContactsContract AUTHORITY

Introduction

In this page you can find the example usage for android.provider ContactsContract AUTHORITY.

Prototype

String AUTHORITY

To view the source code for android.provider ContactsContract AUTHORITY.

Click Source Link

Document

The authority for the contacts provider

Usage

From source file:com.example.am.myapplication.ContactAdder.java

/**
 * Creates a contact entry from the current UI values in the account named by mSelectedAccount.
 *///from   ww w  .j  a  v a  2  s. c  o  m
protected void createContactEntry() {
    // Get values from UI
    String name = mContactNameEditText.getText().toString();
    String phone = mContactPhoneEditText.getText().toString();
    String email = mContactEmailEditText.getText().toString();
    int phoneType = mContactPhoneTypes.get(mContactPhoneTypeSpinner.getSelectedItemPosition());
    int emailType = mContactEmailTypes.get(mContactEmailTypeSpinner.getSelectedItemPosition());
    ;

    // Prepare contact creation request
    //
    // Note: We use RawContacts because this data must be associated with a particular account.
    //       The system will aggregate this with any other data for this contact and create a
    //       coresponding entry in the ContactsContract.Contacts provider for us.
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
    ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
            .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, mSelectedAccount.getType())
            .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, mSelectedAccount.getName()).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, name).build());
    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
            .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
            .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone)
            .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType).build());
    ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
            .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
            .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
            .withValue(ContactsContract.CommonDataKinds.Email.DATA, email)
            .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType).build());

    // Ask the Contact provider to create a new contact
    Log.i(TAG, "Selected account: " + mSelectedAccount.getName() + " (" + mSelectedAccount.getType() + ")");
    Log.i(TAG, "Creating contact: " + name);
    try {
        getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (Exception e) {
        // Display warning
        Context ctx = getApplicationContext();
        CharSequence txt = getString(R.string.contactCreationFailure);
        int duration = Toast.LENGTH_SHORT;
        Toast toast = Toast.makeText(ctx, txt, duration);
        toast.show();

        // Log exception
        Log.e(TAG, "Exceptoin encoutered while inserting contact: " + e);
    }
}

From source file:com.granita.contacticloudsync.syncadapter.AccountSettings.java

@SuppressWarnings("Recycle")
private void update_1_2() throws ContactsStorageException {
    /* - KEY_ADDRESSBOOK_URL ("addressbook_url"),
       - KEY_ADDRESSBOOK_CTAG ("addressbook_ctag"),
       - KEY_ADDRESSBOOK_VCARD_VERSION ("addressbook_vcard_version") are not used anymore (now stored in ContactsContract.SyncState)
       - KEY_LAST_ANDROID_VERSION ("last_android_version") has been added
    *///from   w w w . j  ava2 s  . c  o m

    // move previous address book info to ContactsContract.SyncState
    @Cleanup("release")
    ContentProviderClient provider = context.getContentResolver()
            .acquireContentProviderClient(ContactsContract.AUTHORITY);
    if (provider == null)
        throw new ContactsStorageException("Couldn't access Contacts provider");

    LocalAddressBook addr = new LocalAddressBook(account, provider);

    // until now, ContactsContract.Settings.UNGROUPED_VISIBLE was not set explicitly
    ContentValues values = new ContentValues();
    values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1);
    addr.updateSettings(values);

    String url = accountManager.getUserData(account, "addressbook_url");
    if (!TextUtils.isEmpty(url))
        addr.setURL(url);
    accountManager.setUserData(account, "addressbook_url", null);

    String cTag = accountManager.getUserData(account, "addressbook_ctag");
    if (!TextUtils.isEmpty(cTag))
        addr.setCTag(cTag);
    accountManager.setUserData(account, "addressbook_ctag", null);

    accountManager.setUserData(account, KEY_SETTINGS_VERSION, "2");
}

From source file:com.barak.pix.FeedsActivity.java

/**
 * This method remove IM entry at default Contact application.
 *
 * @param contentResolver/*from   w w  w.  ja  va 2s. c  o m*/
 *            content resolver
 * @param uid
 *            User id from android
 * @param account
 *            account name
 */
public static void removeIMContactField(ContentResolver contentResolver, String uid, String account) {
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
            .withSelection(
                    ContactsContract.Data.RAW_CONTACT_ID + "=? and " + ContactsContract.Data.MIMETYPE
                            + "=? and " + ContactsContract.CommonDataKinds.Im.DATA + " = ?",
                    new String[] { String.valueOf(uid), ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE,
                            account })
            .build());

    try {
        contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (Exception e) {
        Log.d(LOG_TAG, "Can't delete Contact's IM field.");
    }
}

From source file:at.bitfire.davdroid.AccountSettings.java

@SuppressWarnings({ "Recycle", "unused" })
private void update_1_2() throws ContactsStorageException {
    /* - KEY_ADDRESSBOOK_URL ("addressbook_url"),
       - KEY_ADDRESSBOOK_CTAG ("addressbook_ctag"),
       - KEY_ADDRESSBOOK_VCARD_VERSION ("addressbook_vcard_version") are not used anymore (now stored in ContactsContract.SyncState)
       - KEY_LAST_ANDROID_VERSION ("last_android_version") has been added
    *///from  w w w.  j a v  a2s  .c o  m

    // move previous address book info to ContactsContract.SyncState
    @Cleanup("release")
    ContentProviderClient provider = context.getContentResolver()
            .acquireContentProviderClient(ContactsContract.AUTHORITY);
    if (provider == null)
        throw new ContactsStorageException("Couldn't access Contacts provider");

    LocalAddressBook addr = new LocalAddressBook(account, provider);

    // until now, ContactsContract.Settings.UNGROUPED_VISIBLE was not set explicitly
    ContentValues values = new ContentValues();
    values.put(ContactsContract.Settings.UNGROUPED_VISIBLE, 1);
    addr.updateSettings(values);

    String url = accountManager.getUserData(account, "addressbook_url");
    if (!TextUtils.isEmpty(url))
        addr.setURL(url);
    accountManager.setUserData(account, "addressbook_url", null);

    String cTag = accountManager.getUserData(account, "addressbook_ctag");
    if (!TextUtils.isEmpty(cTag))
        addr.setCTag(cTag);
    accountManager.setUserData(account, "addressbook_ctag", null);
}

From source file:org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity.java

@SuppressLint("InflateParams")
@Override/*from  w w  w. j a va 2 s .  c o  m*/
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mKeyRepository = KeyRepository.create(this);
    mImportOpHelper = new CryptoOperationHelper<>(1, this, this, null);

    setTitle(null);

    mStatusText = (TextView) findViewById(R.id.view_key_status);
    mStatusImage = (ImageView) findViewById(R.id.view_key_status_image);
    mAppBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
    mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);

    mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files);
    mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text);
    mFab = (FloatingActionButton) findViewById(R.id.fab);
    mPhoto = (ImageView) findViewById(R.id.view_key_photo);
    mPhotoLayout = (FrameLayout) findViewById(R.id.view_key_photo_layout);
    mQrCode = (ImageView) findViewById(R.id.view_key_qr_code);
    mQrCodeLayout = (CardView) findViewById(R.id.view_key_qr_code_layout);

    mRotateSpin = AnimationUtils.loadAnimation(this, R.anim.rotate_spin);

    //ContentDescriptionHint Listeners implemented

    ContentDescriptionHint.setup(mActionEncryptFile);
    ContentDescriptionHint.setup(mActionEncryptText);
    ContentDescriptionHint.setup(mFab);

    mRotateSpin.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mRefreshItem.getActionView().clearAnimation();
            mRefreshItem.setActionView(null);
            mRefreshItem.setEnabled(true);

            // this is a deferred call
            supportInvalidateOptionsMenu();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    });
    mRotate = AnimationUtils.loadAnimation(this, R.anim.rotate);
    mRotate.setRepeatCount(Animation.INFINITE);
    mRotate.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

        }

        @Override
        public void onAnimationEnd(Animation animation) {

        }

        @Override
        public void onAnimationRepeat(Animation animation) {
            if (!mIsRefreshing) {
                mRefreshItem.getActionView().clearAnimation();
                mRefreshItem.getActionView().startAnimation(mRotateSpin);
            }
        }
    });
    mRefresh = getLayoutInflater().inflate(R.layout.indeterminate_progress, null);

    mDataUri = getIntent().getData();
    if (mDataUri == null) {
        Log.e(Constants.TAG, "Data missing. Should be uri of key!");
        finish();
        return;
    }
    if (mDataUri.getHost().equals(ContactsContract.AUTHORITY)) {
        mDataUri = new ContactHelper(this).dataUriFromContactUri(mDataUri);
        if (mDataUri == null) {
            Log.e(Constants.TAG, "Contact Data missing. Should be uri of key!");
            Toast.makeText(this, R.string.error_contacts_key_id_missing, Toast.LENGTH_LONG).show();
            finish();
            return;
        }
    }

    Log.i(Constants.TAG, "mDataUri: " + mDataUri);

    mActionEncryptFile.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            encrypt(mDataUri, false);
        }
    });
    mActionEncryptText.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            encrypt(mDataUri, true);
        }
    });

    mFab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mIsSecret) {
                startSafeSlinger(mDataUri);
            } else {
                scanQrCode();
            }
        }
    });

    mQrCodeLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showQrCodeDialog();
        }
    });

    // Prepare the loaders. Either re-connect with an existing ones,
    // or start new ones.
    getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);

    if (savedInstanceState == null && getIntent().hasExtra(EXTRA_DISPLAY_RESULT)) {
        OperationResult result = getIntent().getParcelableExtra(EXTRA_DISPLAY_RESULT);
        result.createNotify(this).show();
    }

    // Fragments are stored, no need to recreate those
    if (savedInstanceState != null) {
        return;
    }

    if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) {
        FragmentManager manager = getSupportFragmentManager();
        final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance(mDataUri);
        manager.beginTransaction().replace(R.id.view_key_keybase_fragment, keybaseFrag).commit();
    }
}

From source file:org.codarama.haxsync.services.ContactsSyncAdapterService.java

private static void updateContactStatus(long rawContactId, String status, long timeStamp) {
    if (status != null && timeStamp != 0) {
        ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
        Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
        Uri entityUri = Uri.withAppendedPath(rawContactUri, Entity.CONTENT_DIRECTORY);
        Cursor c = mContentResolver.query(entityUri,
                new String[] { RawContacts.SOURCE_ID, Entity.DATA_ID, Entity.MIMETYPE, Entity.DATA1 }, null,
                null, null);/*from  w  w  w  .  j  a  v a  2 s.  c o  m*/
        try {
            while (c.moveToNext()) {
                if (!c.isNull(1)) {
                    String mimeType = c.getString(2);

                    if (mimeType.equals("vnd.android.cursor.item/vnd.org.codarama.haxsync.profile")) {
                        ContentProviderOperation.Builder builder = ContentProviderOperation
                                .newInsert(ContactsContract.StatusUpdates.CONTENT_URI);
                        builder.withValue(ContactsContract.StatusUpdates.DATA_ID, c.getLong(1));
                        builder.withValue(ContactsContract.StatusUpdates.STATUS, status);
                        builder.withValue(ContactsContract.StatusUpdates.STATUS_RES_PACKAGE,
                                "org.codarama.haxsync");
                        builder.withValue(ContactsContract.StatusUpdates.STATUS_LABEL, R.string.app_name);
                        builder.withValue(ContactsContract.StatusUpdates.STATUS_ICON, R.drawable.icon);
                        builder.withValue(ContactsContract.StatusUpdates.STATUS_TIMESTAMP, timeStamp);
                        operationList.add(builder.build());
                    }
                }
            }
        } finally {
            c.close();
        }
        try {
            mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
        } catch (RemoteException e) {
            Log.e("Error", e.getLocalizedMessage());
        } catch (OperationApplicationException e) {
            Log.e("Error", e.getLocalizedMessage());
        }
    }
}

From source file:com.ntsync.android.sync.shared.SyncUtils.java

/**
 * Create a new Account and activate the automatic sync
 * /*  www  .  jav a2s  . c o m*/
 * @param account
 *            null is not allowed
 * @param accountManager
 *            null is not allowed
 * @param password
 *            null is not allowed
 */
public static boolean createAccount(Context context, final Account account, AccountManager accountManager,
        String password) {
    boolean added = accountManager.addAccountExplicitly(account, password, null);
    if (added) {
        List<PeriodicSync> syncs = ContentResolver.getPeriodicSyncs(account, ContactsContract.AUTHORITY);
        if (syncs != null) {
            // Remove default syncs.
            for (PeriodicSync periodicSync : syncs) {
                ContentResolver.removePeriodicSync(account, ContactsContract.AUTHORITY, periodicSync.extras);
            }
        }
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
        int synctime;
        try {
            synctime = settings.getInt("pref_synctime", DEFAULT_SYNCINTERVAL);
        } catch (ClassCastException e) {
            LogHelper.logI(TAG, "Invalid SyncTime-Settingvalue", e);
            synctime = DEFAULT_SYNCINTERVAL;
        }
        if (synctime != 0) {
            addPeriodicSync(ContactsContract.AUTHORITY, Bundle.EMPTY, synctime, context);
        }

        // Set contacts sync for this account.
        ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
    } else {
        LogHelper.logI(TAG, "Account " + account.name + " is already available.");
    }
    return added;
}

From source file:com.barak.pix.FeedsActivity.java

/**
 * This method remove IM all entries at default Contact application
 *
 * @param contentResolver/*  w  ww.ja v a2s . c om*/
 *            content resolver
 */
public static void deleteAllIMContactField(ContentResolver contentResolver) {
    ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

    ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
            .withSelection(
                    ContactsContract.Data.MIMETYPE + "= ? and "
                            + ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL + "= ?",
                    new String[] { ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE, IM_LABEL })
            .build());

    try {
        contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    } catch (Exception e) {
        Log.d(LOG_TAG, "An exception occurred when deleting all IM field of Contact.");
    }
}

From source file:org.xwalk.runtime.extension.api.contacts.ContactSaver.java

public JSONObject save(String saveString) {
    mOps = new ArrayList<ContentProviderOperation>();
    try {//w  w w.j  av a 2  s . c om
        mContact = new JSONObject(saveString);
    } catch (JSONException e) {
        Log.e(TAG, "Failed to parse json data: " + e.toString());
        return new JSONObject();
    }

    mJson = new ContactJson(mContact);

    Builder builder = null;
    mId = mJson.getString("id");
    mIsUpdate = mUtils.hasID(mId);

    Set<String> oldRawIds = null;
    if (!mIsUpdate) { // Create a null record for inserting later
        oldRawIds = mUtils.getCurrentRawIds();
        mId = null;
        builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
        builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null);
        builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null);
        mOps.add(builder.build());
    }

    // W3C                  Android
    //-------------------------------------------------
    // displayName          StructuredName.display_name
    // honorificPrefixes    StructuredName.prefix
    // givenNames           StructuredName.given_name
    // additionalNames      StructuredName.middle_name
    // familyNames          StructuredName.family_name
    // honorificSuffixes    StructuredName.suffix
    // nicknames            Nickname.name
    if (mContact.has("name")) {
        final JSONObject name = mJson.getObject("name");
        final ContactJson nameJson = new ContactJson(name);
        builder = newBuilder(StructuredName.CONTENT_ITEM_TYPE);
        builder.withValue(StructuredName.DISPLAY_NAME, nameJson.getString("displayName"));
        //FIXME(hdq): should read all names
        builder.withValue(StructuredName.FAMILY_NAME, nameJson.getFirstValue("familyNames"));
        builder.withValue(StructuredName.GIVEN_NAME, nameJson.getFirstValue("givenNames"));
        builder.withValue(StructuredName.MIDDLE_NAME, nameJson.getFirstValue("additionalNames"));
        builder.withValue(StructuredName.PREFIX, nameJson.getFirstValue("honorificPrefixes"));
        builder.withValue(StructuredName.SUFFIX, nameJson.getFirstValue("honorificSuffixes"));
        mOps.add(builder.build());

        // Nickname belongs to another mimetype, so we need another builder for it.
        if (name.has("nicknames")) {
            builder = newBuilder(Nickname.CONTENT_ITEM_TYPE);
            builder.withValue(Nickname.NAME, nameJson.getFirstValue("nicknames"));
            mOps.add(builder.build());
        }
    }

    if (mContact.has("categories")) {
        List<String> groupIds = new ArrayList<String>();
        for (String groupTitle : mJson.getStringArray("categories")) {
            groupIds.add(mUtils.getEnsuredGroupId(groupTitle));
        }
        buildByArray(GroupMembership.CONTENT_ITEM_TYPE, GroupMembership.GROUP_ROW_ID, groupIds);
    }

    if (mContact.has("gender")) {
        final String gender = mJson.getString("gender");
        if (Arrays.asList("male", "female", "other", "none", "unknown").contains(gender)) {
            builder = newBuilder(ContactConstants.CUSTOM_MIMETYPE_GENDER);
            builder.withValue(Data.DATA1, gender);
            mOps.add(builder.build());
        }
    }

    buildByDate("lastUpdated", ContactConstants.CUSTOM_MIMETYPE_LASTUPDATED, Data.DATA1);
    buildByEvent("birthday", Event.TYPE_BIRTHDAY);
    buildByEvent("anniversary", Event.TYPE_ANNIVERSARY);

    buildByContactMapList();

    // Perform the operation batch
    try {
        mUtils.mResolver.applyBatch(ContactsContract.AUTHORITY, mOps);
    } catch (Exception e) {
        if (e instanceof RemoteException || e instanceof OperationApplicationException
                || e instanceof SecurityException) {
            Log.e(TAG, "Failed to apply batch: " + e.toString());
            return new JSONObject();
        } else {
            throw new RuntimeException(e);
        }
    }

    // If it is a new contact, need to get and return its auto-generated id.
    if (!mIsUpdate) {
        Set<String> newRawIds = mUtils.getCurrentRawIds();
        if (newRawIds == null)
            return new JSONObject();
        newRawIds.removeAll(oldRawIds);
        if (newRawIds.size() != 1) {
            Log.e(TAG, "Something wrong after batch applied, " + "new raw ids are: " + newRawIds.toString());
            return mContact;
        }
        String id = mUtils.getId(newRawIds.iterator().next());
        PutToContact(id);
    }
    return mContact;
}

From source file:at.bitfire.davdroid.AccountSettings.java

@SuppressWarnings({ "Recycle", "unused" })
private void update_2_3() {
    // Don't show a warning for Android updates anymore
    accountManager.setUserData(account, "last_android_version", null);

    Long serviceCardDAV = null, serviceCalDAV = null;

    ServiceDB.OpenHelper dbHelper = new ServiceDB.OpenHelper(context);
    try {//from   w ww.  ja  v  a 2  s .  c  o m
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        // we have to create the WebDAV Service database only from the old address book, calendar and task list URLs

        // CardDAV: migrate address books
        ContentProviderClient client = context.getContentResolver()
                .acquireContentProviderClient(ContactsContract.AUTHORITY);
        if (client != null)
            try {
                LocalAddressBook addrBook = new LocalAddressBook(account, client);
                String url = addrBook.getURL();
                if (url != null) {
                    App.log.fine("Migrating address book " + url);

                    // insert CardDAV service
                    ContentValues values = new ContentValues();
                    values.put(Services.ACCOUNT_NAME, account.name);
                    values.put(Services.SERVICE, Services.SERVICE_CARDDAV);
                    serviceCardDAV = db.insert(Services._TABLE, null, values);

                    // insert address book
                    values.clear();
                    values.put(Collections.SERVICE_ID, serviceCardDAV);
                    values.put(Collections.URL, url);
                    values.put(Collections.SYNC, 1);
                    db.insert(Collections._TABLE, null, values);

                    // insert home set
                    HttpUrl homeSet = HttpUrl.parse(url).resolve("../");
                    values.clear();
                    values.put(HomeSets.SERVICE_ID, serviceCardDAV);
                    values.put(HomeSets.URL, homeSet.toString());
                    db.insert(HomeSets._TABLE, null, values);
                }

            } catch (ContactsStorageException e) {
                App.log.log(Level.SEVERE, "Couldn't migrate address book", e);
            } finally {
                client.release();
            }

        // CalDAV: migrate calendars + task lists
        Set<String> collections = new HashSet<>();
        Set<HttpUrl> homeSets = new HashSet<>();

        client = context.getContentResolver().acquireContentProviderClient(CalendarContract.AUTHORITY);
        if (client != null)
            try {
                LocalCalendar calendars[] = (LocalCalendar[]) LocalCalendar.find(account, client,
                        LocalCalendar.Factory.INSTANCE, null, null);
                for (LocalCalendar calendar : calendars) {
                    String url = calendar.getName();
                    App.log.fine("Migrating calendar " + url);
                    collections.add(url);
                    homeSets.add(HttpUrl.parse(url).resolve("../"));
                }
            } catch (CalendarStorageException e) {
                App.log.log(Level.SEVERE, "Couldn't migrate calendars", e);
            } finally {
                client.release();
            }

        TaskProvider provider = LocalTaskList.acquireTaskProvider(context.getContentResolver());
        if (provider != null)
            try {
                LocalTaskList[] taskLists = (LocalTaskList[]) LocalTaskList.find(account, provider,
                        LocalTaskList.Factory.INSTANCE, null, null);
                for (LocalTaskList taskList : taskLists) {
                    String url = taskList.getSyncId();
                    App.log.fine("Migrating task list " + url);
                    collections.add(url);
                    homeSets.add(HttpUrl.parse(url).resolve("../"));
                }
            } catch (CalendarStorageException e) {
                App.log.log(Level.SEVERE, "Couldn't migrate task lists", e);
            } finally {
                provider.close();
            }

        if (!collections.isEmpty()) {
            // insert CalDAV service
            ContentValues values = new ContentValues();
            values.put(Services.ACCOUNT_NAME, account.name);
            values.put(Services.SERVICE, Services.SERVICE_CALDAV);
            serviceCalDAV = db.insert(Services._TABLE, null, values);

            // insert collections
            for (String url : collections) {
                values.clear();
                values.put(Collections.SERVICE_ID, serviceCalDAV);
                values.put(Collections.URL, url);
                values.put(Collections.SYNC, 1);
                db.insert(Collections._TABLE, null, values);
            }

            // insert home sets
            for (HttpUrl homeSet : homeSets) {
                values.clear();
                values.put(HomeSets.SERVICE_ID, serviceCalDAV);
                values.put(HomeSets.URL, homeSet.toString());
                db.insert(HomeSets._TABLE, null, values);
            }
        }
    } finally {
        dbHelper.close();
    }

    // initiate service detection (refresh) to get display names, colors etc.
    Intent refresh = new Intent(context, DavService.class);
    refresh.setAction(DavService.ACTION_REFRESH_COLLECTIONS);
    if (serviceCardDAV != null) {
        refresh.putExtra(DavService.EXTRA_DAV_SERVICE_ID, serviceCardDAV);
        context.startService(refresh);
    }
    if (serviceCalDAV != null) {
        refresh.putExtra(DavService.EXTRA_DAV_SERVICE_ID, serviceCalDAV);
        context.startService(refresh);
    }
}