15635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov/* 25635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Copyright (C) 2009 The Android Open Source Project 35635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * 45635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License"); 55635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * you may not use this file except in compliance with the License. 65635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * You may obtain a copy of the License at 75635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * 85635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * http://www.apache.org/licenses/LICENSE-2.0 95635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * 105635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software 115635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS, 125635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * See the License for the specific language governing permissions and 145635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * limitations under the License. 155635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 165635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 175635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovpackage com.example.android.businesscard; 185635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 195635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.app.Activity; 205635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.content.Intent; 215635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.net.Uri; 225635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.os.AsyncTask; 235635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.os.Bundle; 245635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.view.View; 255635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.view.View.OnClickListener; 265635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.widget.Button; 275635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovimport android.widget.TextView; 285635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 295635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov/** 305635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * A simple activity that shows a "Pick Contact" button and two fields: contact's name 315635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * and phone number. The user taps on the Pick Contact button to bring up 325635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * the contact chooser. Once this activity receives the result from contact picker, 335635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * it launches an asynchronous query (queries should always be asynchronous) to load 345635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * contact's name and phone number. When the query completes, the activity displays 355635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * the loaded data. 365635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 375635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikovpublic class BusinessCardActivity extends Activity { 385635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 395635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov // Request code for the contact picker activity 405635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov private static final int PICK_CONTACT_REQUEST = 1; 415635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 425635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 435635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * An SDK-specific instance of {@link ContactAccessor}. The activity does not need 445635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * to know what SDK it is running in: all idiosyncrasies of different SDKs are 455635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * encapsulated in the implementations of the ContactAccessor class. 465635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 475635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov private final ContactAccessor mContactAccessor = ContactAccessor.getInstance(); 485635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 495635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 505635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Called with the activity is first created. 515635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 525635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov @Override 535635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov public void onCreate(Bundle savedInstanceState) { 545635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov super.onCreate(savedInstanceState); 555635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 565635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov setContentView(R.layout.business_card); 575635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 585635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov // Install a click handler on the Pick Contact button 595635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov Button pickContact = (Button)findViewById(R.id.pick_contact_button); 605635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov pickContact.setOnClickListener(new OnClickListener() { 615635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 625635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov public void onClick(View v) { 635635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov pickContact(); 645635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 655635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov }); 665635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 675635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 685635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 695635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Click handler for the Pick Contact button. Invokes a contact picker activity. 705635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * The specific intent used to bring up that activity differs between versions 715635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * of the SDK, which is why we delegate the creation of the intent to ContactAccessor. 725635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 735635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov protected void pickContact() { 745635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov startActivityForResult(mContactAccessor.getPickContactIntent(), PICK_CONTACT_REQUEST); 755635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 765635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 775635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 785635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Invoked when the contact picker activity is finished. The {@code contactUri} parameter 795635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * will contain a reference to the contact selected by the user. We will treat it as 805635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * an opaque URI and allow the SDK-specific ContactAccessor to handle the URI accordingly. 815635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 825635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov @Override 835635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov protected void onActivityResult(int requestCode, int resultCode, Intent data) { 845635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov if (requestCode == PICK_CONTACT_REQUEST && resultCode == RESULT_OK) { 855635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov loadContactInfo(data.getData()); 865635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 875635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 885635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 895635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 905635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Load contact information on a background thread. 915635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 925635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov private void loadContactInfo(Uri contactUri) { 935635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 945635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /* 955635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * We should always run database queries on a background thread. The database may be 965635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * locked by some process for a long time. If we locked up the UI thread while waiting 975635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * for the query to come back, we might get an "Application Not Responding" dialog. 985635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 995635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov AsyncTask<Uri, Void, ContactInfo> task = new AsyncTask<Uri, Void, ContactInfo>() { 1005635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 1015635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov @Override 1025635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov protected ContactInfo doInBackground(Uri... uris) { 1035635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov return mContactAccessor.loadContact(getContentResolver(), uris[0]); 1045635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 1055635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 1065635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov @Override 1075635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov protected void onPostExecute(ContactInfo result) { 1085635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov bindView(result); 1095635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 1105635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov }; 1115635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 1125635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov task.execute(contactUri); 1135635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 1145635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 1155635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov /** 1165635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov * Displays contact information: name and phone number. 1175635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov */ 1185635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov protected void bindView(ContactInfo contactInfo) { 1195635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov TextView displayNameView = (TextView) findViewById(R.id.display_name_text_view); 1205635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov displayNameView.setText(contactInfo.getDisplayName()); 1215635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov 1225635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov TextView phoneNumberView = (TextView) findViewById(R.id.phone_number_text_view); 1235635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov phoneNumberView.setText(contactInfo.getPhoneNumber()); 1245635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov } 1255635cf46c1d8df9a2a3bda2538a1ab813237dc3cDmitri Plotnikov} 126