Java tutorial
/* * 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); } }