com.rukman.emde.smsgroups.platform.GMSContactOperations.java Source code

Java tutorial

Introduction

Here is the source code for com.rukman.emde.smsgroups.platform.GMSContactOperations.java

Source

/*
 * Copyright (C) 2013 Brion N. Emde
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.rukman.emde.smsgroups.platform;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

import android.accounts.Account;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.SyncResult;
import android.content.res.AssetManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.Settings;

import com.rukman.emde.smsgroups.GMSApplication;
import com.rukman.emde.smsgroups.client.JSONKeys;

/**
 * Helper class for storing data in the platform content providers.
 */
public class GMSContactOperations {
    @SuppressWarnings("unused")
    private static final String TAG = "GMSContactOperations";

    private static Uri addCallerIsSyncAdapterParameter(Uri uri, boolean isSyncOperation) {
        if (isSyncOperation) {
            // If we're in the middle of a real sync-adapter operation, then go ahead
            // and tell the Contacts provider that we're the sync adapter.  That
            // gives us some special permissions - like the ability to really
            // delete a contact, and the ability to clear the dirty flag.
            //
            // If we're not in the middle of a sync operation (for example, we just
            // locally created/edited a new contact), then we don't want to use
            // the special permissions, and the system will automagically mark
            // the contact as 'dirty' for us!
            return uri.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
        }
        return uri;
    }

    /**
     * Find the group whose SOURCE_ID column matches the parameter.
     * 
     * @param provider - ContentProviderClient
     * @param account - User account
     * @param sourceId - Cloud Id of the group.
     * @return Cursor object returned from query with projection:
     *     new String[] { RawContacts._ID, RawContacts.SOURCE_ID }; 
     */
    public static Cursor findGroupInContacts(ContentProviderClient provider, Account account, String sourceId) {
        Cursor cursor = null;
        try {
            Uri uri = RawContacts.CONTENT_URI.buildUpon()
                    .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
                    .appendQueryParameter(RawContacts.ACCOUNT_TYPE, GMSApplication.ACCOUNT_TYPE).build();
            cursor = provider.query(uri, new String[] { RawContacts._ID, RawContacts.SOURCE_ID },
                    RawContacts.SOURCE_ID + "=?", new String[] { sourceId }, null);
            return cursor;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return cursor;
    }

    public static long addGroupToContacts(Context context, ContentProviderClient provider, Account account,
            JSONObject group, SyncResult result)
            throws RemoteException, OperationApplicationException, JSONException {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
                .withValue(RawContacts.ACCOUNT_TYPE, GMSApplication.ACCOUNT_TYPE)
                .withValue(RawContacts.ACCOUNT_NAME, account.name)
                .withValue(RawContacts.SOURCE_ID, group.getString(JSONKeys.KEY_ID));
        ops.add(op.build());
        op = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(CommonDataKinds.StructuredName.DISPLAY_NAME, group.getString(JSONKeys.KEY_NAME));
        ops.add(op.build());
        op = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(CommonDataKinds.Phone.NUMBER, group.get(JSONKeys.KEY_PHONE))
                .withValue(CommonDataKinds.Phone.TYPE, CommonDataKinds.Phone.TYPE_MAIN);
        ops.add(op.build());
        op = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE).withYieldAllowed(true);
        ops.add(op.build());
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            is = context.getAssets().open("gms.png", AssetManager.ACCESS_BUFFER);
            baos = new ByteArrayOutputStream();
            int value = is.read();
            while (value != -1) {
                baos.write(value);
                value = is.read();
            }
            op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
                    .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                    .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
                    .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, baos.toByteArray())
                    .withYieldAllowed(true);
            ops.add(op.build());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (baos != null) {
                    baos.close();
                }
            } catch (IOException ignore) {
            }
        }
        ContentProviderResult[] results = provider.applyBatch(ops);
        return (results[0].uri != null) ? ContentUris.parseId(results[0].uri) : -1L;
    }

    public static int removeGroupFromContacts(ContentProviderClient provider, Account account, long rawContactId,
            SyncResult result) throws RemoteException {
        Uri uri = addCallerIsSyncAdapterParameter(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId),
                true);
        return provider.delete(uri, null, null);
    }

    /**
     * When we first add a sync adapter to the system, the contacts from that
     * sync adapter will be hidden unless they're merged/grouped with an existing
     * contact.  But typically we want to actually show those contacts, so we
     * need to mess with the Settings table to get them to show up.
     *
     * @param context the Authenticator Activity context
     * @param account the Account who's visibility we're changing
     * @param visible true if we want the contacts visible, false for hidden
     */
    public static void setAccountContactsVisibility(Context context, Account account, boolean visible) {
        ContentValues values = new ContentValues();
        values.put(RawContacts.ACCOUNT_NAME, account.name);
        values.put(RawContacts.ACCOUNT_TYPE, GMSApplication.ACCOUNT_TYPE);
        values.put(Settings.UNGROUPED_VISIBLE, visible ? 1 : 0);
        context.getContentResolver().insert(Settings.CONTENT_URI, values);
    }

}