1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.example.android.businesscard;
18 
19 import android.app.Activity;
20 import android.content.Intent;
21 import android.graphics.Insets;
22 import android.net.Uri;
23 import android.os.AsyncTask;
24 import android.os.Bundle;
25 import android.view.View;
26 import android.view.View.OnClickListener;
27 import android.view.ViewGroup;
28 import android.view.WindowInsets;
29 import android.widget.Button;
30 import android.widget.TextView;
31 
32 /**
33  * A simple activity that shows a "Pick Contact" button and two fields: contact's name
34  * and phone number.  The user taps on the Pick Contact button to bring up
35  * the contact chooser.  Once this activity receives the result from contact picker,
36  * it launches an asynchronous query (queries should always be asynchronous) to load
37  * contact's name and phone number. When the query completes, the activity displays
38  * the loaded data.
39  */
40 public class BusinessCardActivity extends Activity  {
41 
42     // Request code for the contact picker activity
43     private static final int PICK_CONTACT_REQUEST = 1;
44 
45     /**
46      * An SDK-specific instance of {@link ContactAccessor}.  The activity does not need
47      * to know what SDK it is running in: all idiosyncrasies of different SDKs are
48      * encapsulated in the implementations of the ContactAccessor class.
49      */
50     private final ContactAccessor mContactAccessor = ContactAccessor.getInstance();
51 
52     /**
53      * Called with the activity is first created.
54      */
55     @Override
onCreate(Bundle savedInstanceState)56     public void onCreate(Bundle savedInstanceState) {
57         super.onCreate(savedInstanceState);
58 
59         setContentView(R.layout.business_card);
60         getWindow().setDecorFitsSystemWindows(false);
61         findViewById(android.R.id.content).setOnApplyWindowInsetsListener((v, w) -> {
62             final Insets i = w.getInsets(
63                     WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
64             final View topBarBackground = findViewById(R.id.top_bar_background);
65             final ViewGroup.LayoutParams attrs = topBarBackground.getLayoutParams();
66             attrs.height = i.top;
67             topBarBackground.setLayoutParams(attrs);
68             v.setPadding(i.left, 0, i.right, i.bottom);
69             return WindowInsets.CONSUMED;
70         });
71 
72         // Install a click handler on the Pick Contact button
73         Button pickContact = (Button)findViewById(R.id.pick_contact_button);
74         pickContact.setOnClickListener(new OnClickListener() {
75 
76             public void onClick(View v) {
77                 pickContact();
78             }
79         });
80     }
81 
82     /**
83      * Click handler for the Pick Contact button.  Invokes a contact picker activity.
84      * The specific intent used to bring up that activity differs between versions
85      * of the SDK, which is why we delegate the creation of the intent to ContactAccessor.
86      */
pickContact()87     protected void pickContact() {
88         startActivityForResult(mContactAccessor.getPickContactIntent(), PICK_CONTACT_REQUEST);
89     }
90 
91     /**
92      * Invoked when the contact picker activity is finished. The {@code contactUri} parameter
93      * will contain a reference to the contact selected by the user. We will treat it as
94      * an opaque URI and allow the SDK-specific ContactAccessor to handle the URI accordingly.
95      */
96     @Override
onActivityResult(int requestCode, int resultCode, Intent data)97     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
98         if (requestCode == PICK_CONTACT_REQUEST && resultCode == RESULT_OK) {
99             loadContactInfo(data.getData());
100         }
101     }
102 
103     /**
104      * Load contact information on a background thread.
105      */
loadContactInfo(Uri contactUri)106     private void loadContactInfo(Uri contactUri) {
107 
108         /*
109          * We should always run database queries on a background thread. The database may be
110          * locked by some process for a long time.  If we locked up the UI thread while waiting
111          * for the query to come back, we might get an "Application Not Responding" dialog.
112          */
113         AsyncTask<Uri, Void, ContactInfo> task = new AsyncTask<Uri, Void, ContactInfo>() {
114 
115             @Override
116             protected ContactInfo doInBackground(Uri... uris) {
117                 return mContactAccessor.loadContact(getContentResolver(), uris[0]);
118             }
119 
120             @Override
121             protected void onPostExecute(ContactInfo result) {
122                 bindView(result);
123             }
124         };
125 
126         task.execute(contactUri);
127     }
128 
129     /**
130      * Displays contact information: name and phone number.
131      */
bindView(ContactInfo contactInfo)132     protected void bindView(ContactInfo contactInfo) {
133         TextView displayNameView = (TextView) findViewById(R.id.display_name_text_view);
134         displayNameView.setText(contactInfo.getDisplayName());
135 
136         TextView phoneNumberView = (TextView) findViewById(R.id.phone_number_text_view);
137         phoneNumberView.setText(contactInfo.getPhoneNumber());
138     }
139 }
140