1*90c8c64dSAndroid Build Coastguard Worker /* 2*90c8c64dSAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project 3*90c8c64dSAndroid Build Coastguard Worker * 4*90c8c64dSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*90c8c64dSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*90c8c64dSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*90c8c64dSAndroid Build Coastguard Worker * 8*90c8c64dSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*90c8c64dSAndroid Build Coastguard Worker * 10*90c8c64dSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*90c8c64dSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*90c8c64dSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*90c8c64dSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*90c8c64dSAndroid Build Coastguard Worker * limitations under the License. 15*90c8c64dSAndroid Build Coastguard Worker */ 16*90c8c64dSAndroid Build Coastguard Worker package com.example.android.basiccontactables; 17*90c8c64dSAndroid Build Coastguard Worker 18*90c8c64dSAndroid Build Coastguard Worker import android.app.Activity; 19*90c8c64dSAndroid Build Coastguard Worker import android.app.LoaderManager; 20*90c8c64dSAndroid Build Coastguard Worker import android.content.Context; 21*90c8c64dSAndroid Build Coastguard Worker import android.content.CursorLoader; 22*90c8c64dSAndroid Build Coastguard Worker import android.content.Loader; 23*90c8c64dSAndroid Build Coastguard Worker import android.database.Cursor; 24*90c8c64dSAndroid Build Coastguard Worker import android.net.Uri; 25*90c8c64dSAndroid Build Coastguard Worker import android.os.Bundle; 26*90c8c64dSAndroid Build Coastguard Worker import android.provider.ContactsContract.CommonDataKinds; 27*90c8c64dSAndroid Build Coastguard Worker import android.util.Log; 28*90c8c64dSAndroid Build Coastguard Worker import android.widget.TextView; 29*90c8c64dSAndroid Build Coastguard Worker 30*90c8c64dSAndroid Build Coastguard Worker /** 31*90c8c64dSAndroid Build Coastguard Worker * Helper class to handle all the callbacks that occur when interacting with loaders. Most of the 32*90c8c64dSAndroid Build Coastguard Worker * interesting code in this sample app will be in this file. 33*90c8c64dSAndroid Build Coastguard Worker */ 34*90c8c64dSAndroid Build Coastguard Worker public class ContactablesLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> { 35*90c8c64dSAndroid Build Coastguard Worker 36*90c8c64dSAndroid Build Coastguard Worker Context mContext; 37*90c8c64dSAndroid Build Coastguard Worker 38*90c8c64dSAndroid Build Coastguard Worker public static final String QUERY_KEY = "query"; 39*90c8c64dSAndroid Build Coastguard Worker 40*90c8c64dSAndroid Build Coastguard Worker public static final String TAG = "ContactablesLoaderCallbacks"; 41*90c8c64dSAndroid Build Coastguard Worker ContactablesLoaderCallbacks(Context context)42*90c8c64dSAndroid Build Coastguard Worker public ContactablesLoaderCallbacks(Context context) { 43*90c8c64dSAndroid Build Coastguard Worker mContext = context; 44*90c8c64dSAndroid Build Coastguard Worker } 45*90c8c64dSAndroid Build Coastguard Worker 46*90c8c64dSAndroid Build Coastguard Worker @Override onCreateLoader(int loaderIndex, Bundle args)47*90c8c64dSAndroid Build Coastguard Worker public Loader<Cursor> onCreateLoader(int loaderIndex, Bundle args) { 48*90c8c64dSAndroid Build Coastguard Worker // Where the Contactables table excels is matching text queries, 49*90c8c64dSAndroid Build Coastguard Worker // not just data dumps from Contacts db. One search term is used to query 50*90c8c64dSAndroid Build Coastguard Worker // display name, email address and phone number. In this case, the query was extracted 51*90c8c64dSAndroid Build Coastguard Worker // from an incoming intent in the handleIntent() method, via the 52*90c8c64dSAndroid Build Coastguard Worker // intent.getStringExtra() method. 53*90c8c64dSAndroid Build Coastguard Worker 54*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(uri_with_query) 55*90c8c64dSAndroid Build Coastguard Worker String query = args.getString(QUERY_KEY); 56*90c8c64dSAndroid Build Coastguard Worker Uri uri = Uri.withAppendedPath( 57*90c8c64dSAndroid Build Coastguard Worker CommonDataKinds.Contactables.CONTENT_FILTER_URI, query); 58*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(uri_with_query) 59*90c8c64dSAndroid Build Coastguard Worker 60*90c8c64dSAndroid Build Coastguard Worker 61*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(cursor_loader) 62*90c8c64dSAndroid Build Coastguard Worker // Easy way to limit the query to contacts with phone numbers. 63*90c8c64dSAndroid Build Coastguard Worker String selection = 64*90c8c64dSAndroid Build Coastguard Worker CommonDataKinds.Contactables.HAS_PHONE_NUMBER + " = " + 1; 65*90c8c64dSAndroid Build Coastguard Worker 66*90c8c64dSAndroid Build Coastguard Worker // Sort results such that rows for the same contact stay together. 67*90c8c64dSAndroid Build Coastguard Worker String sortBy = CommonDataKinds.Contactables.LOOKUP_KEY; 68*90c8c64dSAndroid Build Coastguard Worker 69*90c8c64dSAndroid Build Coastguard Worker return new CursorLoader( 70*90c8c64dSAndroid Build Coastguard Worker mContext, // Context 71*90c8c64dSAndroid Build Coastguard Worker uri, // URI representing the table/resource to be queried 72*90c8c64dSAndroid Build Coastguard Worker null, // projection - the list of columns to return. Null means "all" 73*90c8c64dSAndroid Build Coastguard Worker selection, // selection - Which rows to return (condition rows must match) 74*90c8c64dSAndroid Build Coastguard Worker null, // selection args - can be provided separately and subbed into selection. 75*90c8c64dSAndroid Build Coastguard Worker sortBy); // string specifying sort order 76*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(cursor_loader) 77*90c8c64dSAndroid Build Coastguard Worker } 78*90c8c64dSAndroid Build Coastguard Worker 79*90c8c64dSAndroid Build Coastguard Worker @Override onLoadFinished(Loader<Cursor> arg0, Cursor cursor)80*90c8c64dSAndroid Build Coastguard Worker public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) { 81*90c8c64dSAndroid Build Coastguard Worker TextView tv = (TextView) ((Activity)mContext).findViewById(R.id.sample_output); 82*90c8c64dSAndroid Build Coastguard Worker if(tv == null) { 83*90c8c64dSAndroid Build Coastguard Worker Log.e(TAG, "TextView is null?!"); 84*90c8c64dSAndroid Build Coastguard Worker } else if (mContext == null) { 85*90c8c64dSAndroid Build Coastguard Worker Log.e(TAG, "Context is null?"); 86*90c8c64dSAndroid Build Coastguard Worker } else { 87*90c8c64dSAndroid Build Coastguard Worker Log.e(TAG, "Nothing is null?!"); 88*90c8c64dSAndroid Build Coastguard Worker } 89*90c8c64dSAndroid Build Coastguard Worker 90*90c8c64dSAndroid Build Coastguard Worker // Reset text in case of a previous query 91*90c8c64dSAndroid Build Coastguard Worker tv.setText(mContext.getText(R.string.intro_message) + "\n\n"); 92*90c8c64dSAndroid Build Coastguard Worker 93*90c8c64dSAndroid Build Coastguard Worker if (cursor.getCount() == 0) { 94*90c8c64dSAndroid Build Coastguard Worker return; 95*90c8c64dSAndroid Build Coastguard Worker } 96*90c8c64dSAndroid Build Coastguard Worker 97*90c8c64dSAndroid Build Coastguard Worker // Pulling the relevant value from the cursor requires knowing the column index to pull 98*90c8c64dSAndroid Build Coastguard Worker // it from. 99*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(get_columns) 100*90c8c64dSAndroid Build Coastguard Worker int phoneColumnIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER); 101*90c8c64dSAndroid Build Coastguard Worker int emailColumnIndex = cursor.getColumnIndex(CommonDataKinds.Email.ADDRESS); 102*90c8c64dSAndroid Build Coastguard Worker int nameColumnIndex = cursor.getColumnIndex(CommonDataKinds.Contactables.DISPLAY_NAME); 103*90c8c64dSAndroid Build Coastguard Worker int lookupColumnIndex = cursor.getColumnIndex(CommonDataKinds.Contactables.LOOKUP_KEY); 104*90c8c64dSAndroid Build Coastguard Worker int typeColumnIndex = cursor.getColumnIndex(CommonDataKinds.Contactables.MIMETYPE); 105*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(get_columns) 106*90c8c64dSAndroid Build Coastguard Worker 107*90c8c64dSAndroid Build Coastguard Worker cursor.moveToFirst(); 108*90c8c64dSAndroid Build Coastguard Worker // Lookup key is the easiest way to verify a row of data is for the same 109*90c8c64dSAndroid Build Coastguard Worker // contact as the previous row. 110*90c8c64dSAndroid Build Coastguard Worker String lookupKey = ""; 111*90c8c64dSAndroid Build Coastguard Worker do { 112*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(lookup_key) 113*90c8c64dSAndroid Build Coastguard Worker String currentLookupKey = cursor.getString(lookupColumnIndex); 114*90c8c64dSAndroid Build Coastguard Worker if (!lookupKey.equals(currentLookupKey)) { 115*90c8c64dSAndroid Build Coastguard Worker String displayName = cursor.getString(nameColumnIndex); 116*90c8c64dSAndroid Build Coastguard Worker tv.append(displayName + "\n"); 117*90c8c64dSAndroid Build Coastguard Worker lookupKey = currentLookupKey; 118*90c8c64dSAndroid Build Coastguard Worker } 119*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(lookup_key) 120*90c8c64dSAndroid Build Coastguard Worker 121*90c8c64dSAndroid Build Coastguard Worker // BEGIN_INCLUDE(retrieve_data) 122*90c8c64dSAndroid Build Coastguard Worker // The data type can be determined using the mime type column. 123*90c8c64dSAndroid Build Coastguard Worker String mimeType = cursor.getString(typeColumnIndex); 124*90c8c64dSAndroid Build Coastguard Worker if (mimeType.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) { 125*90c8c64dSAndroid Build Coastguard Worker tv.append("\tPhone Number: " + cursor.getString(phoneColumnIndex) + "\n"); 126*90c8c64dSAndroid Build Coastguard Worker } else if (mimeType.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) { 127*90c8c64dSAndroid Build Coastguard Worker tv.append("\tEmail Address: " + cursor.getString(emailColumnIndex) + "\n"); 128*90c8c64dSAndroid Build Coastguard Worker } 129*90c8c64dSAndroid Build Coastguard Worker // END_INCLUDE(retrieve_data) 130*90c8c64dSAndroid Build Coastguard Worker 131*90c8c64dSAndroid Build Coastguard Worker // Look at DDMS to see all the columns returned by a query to Contactables. 132*90c8c64dSAndroid Build Coastguard Worker // Behold, the firehose! 133*90c8c64dSAndroid Build Coastguard Worker for(String column : cursor.getColumnNames()) { 134*90c8c64dSAndroid Build Coastguard Worker Log.d(TAG, column + column + ": " + 135*90c8c64dSAndroid Build Coastguard Worker cursor.getString(cursor.getColumnIndex(column)) + "\n"); 136*90c8c64dSAndroid Build Coastguard Worker } 137*90c8c64dSAndroid Build Coastguard Worker } while (cursor.moveToNext()); 138*90c8c64dSAndroid Build Coastguard Worker } 139*90c8c64dSAndroid Build Coastguard Worker 140*90c8c64dSAndroid Build Coastguard Worker @Override onLoaderReset(Loader<Cursor> cursorLoader)141*90c8c64dSAndroid Build Coastguard Worker public void onLoaderReset(Loader<Cursor> cursorLoader) { 142*90c8c64dSAndroid Build Coastguard Worker } 143*90c8c64dSAndroid Build Coastguard Worker } 144