14cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann/*
2ef3f8f045ed4150caa64749742227acd0e6b85d8Daniel Lehmann * Copyright (C) 2010 The Android Open Source Project
34cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
44cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * Licensed under the Apache License, Version 2.0 (the "License");
54cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * you may not use this file except in compliance with the License.
64cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * You may obtain a copy of the License at
74cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
84cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *      http://www.apache.org/licenses/LICENSE-2.0
94cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann *
104cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * Unless required by applicable law or agreed to in writing, software
114cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * distributed under the License is distributed on an "AS IS" BASIS,
124cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * See the License for the specific language governing permissions and
144cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann * limitations under the License
154cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann */
164cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
174cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannpackage com.android.contacts.activities;
184cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
192eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.app.ActionBar;
2079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuanimport android.app.Fragment;
2160be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmannimport android.content.ActivityNotFoundException;
22caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport android.content.ContentValues;
23078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Chengimport android.content.Context;
2418f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmannimport android.content.Intent;
25c2687c3c38d8fb5f34ad6d8fb5c33e16f335183cDaniel Lehmannimport android.net.Uri;
264cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.os.Bundle;
272eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.os.Handler;
28d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.text.TextUtils;
294cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.util.Log;
304cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmannimport android.view.KeyEvent;
31942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.Menu;
32942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.MenuInflater;
33942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuanimport android.view.MenuItem;
342a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmannimport android.view.MenuItem.OnMenuItemClickListener;
352eb969cc399d87b659a45568fa951d394c216917Katherine Kuanimport android.view.View;
36d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.view.accessibility.AccessibilityEvent;
37d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawaimport android.view.accessibility.AccessibilityManager;
38caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport android.widget.Toast;
39caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov
40e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactSaveService;
41e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.ContactsActivity;
42e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.R;
43e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailDisplayUtils;
44e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailFragment;
45e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactDetailLayoutController;
46e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactLoaderFragment;
47e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
48e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.interactions.ContactDeletionInteraction;
49851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.Contact;
50851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.account.AccountWithDataSet;
51e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.util.PhoneCapabilityTester;
52e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
53caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikovimport java.util.ArrayList;
544cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
556f667b55687bf9193323802e8f3234f0ab254388Dmitri Plotnikovpublic class ContactDetailActivity extends ContactsActivity {
564cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    private static final String TAG = "ContactDetailActivity";
574cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
582a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    /** Shows a toogle button for hiding/showing updates. Don't submit with true */
592a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann    private static final boolean DEBUG_TRANSITIONS = false;
602a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann
61851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    private Contact mContactData;
62942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    private Uri mLookupUri;
63942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
6451f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan    private ContactDetailLayoutController mContactDetailLayoutController;
652eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private ContactLoaderFragment mLoaderFragment;
662eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
672eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private Handler mHandler = new Handler();
682eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
694cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    @Override
706fa7384a1a5576ace18159de61af91c8b7c34dc6Dave Santoro    protected void onCreate(Bundle savedState) {
714cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann        super.onCreate(savedState);
72c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann        if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
73c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            // This activity must not be shown. We have to select the contact in the
745e684a424e7036ba3d379221d1889b4dd7265021Dave Santoro            // PeopleActivity instead ==> Create a forward intent and finish
75c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            final Intent originalIntent = getIntent();
76c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            Intent intent = new Intent();
77c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            intent.setAction(originalIntent.getAction());
78c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
79d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann
80d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // If we are launched from the outside, we should create a new task, because the user
81d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // can freely navigate the app (this is different from phones, where only the UP button
82d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            // kicks the user into the full app)
83d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            if (shouldUpRecreateTask(intent)) {
84d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |
85d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                        Intent.FLAG_ACTIVITY_TASK_ON_HOME);
86d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            } else {
87d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
88d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                        Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_SINGLE_TOP |
89d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann                        Intent.FLAG_ACTIVITY_CLEAR_TOP);
90d0414e5bd478444a9360c95258c267373f02554bDaniel Lehmann            }
91c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann
929856fcee477d04f51bdbcbfdf632876c6b8a1173Katherine Kuan            intent.setClass(this, PeopleActivity.class);
93c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            startActivity(intent);
94c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            finish();
95c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann            return;
96c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann        }
97c90c705db8b3665ba9c8d8ce4b8ab3a03e38ddc7Daniel Lehmann
9825a0282e968ebcdec6510bdb766ffba79b6fb8c4Daniel Lehmann        setContentView(R.layout.contact_detail_activity);
99db0d8669cd1ffaa45827edb65b2b0eecb27561f5Katherine Kuan
10051f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
1012f41fe6bcc8d055bf53ad070425552fad57dff21Daniel Lehmann                getFragmentManager(), null, findViewById(R.id.contact_detail_container),
10251f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan                mContactDetailFragmentListener);
103cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
10413fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        // We want the UP affordance but no app icon.
10513fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        // Setting HOME_AS_UP, SHOW_TITLE and clearing SHOW_HOME does the trick.
10613fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki        ActionBar actionBar = getActionBar();
1074ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson        if (actionBar != null) {
10813fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki            actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
10913fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki                    ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
11013fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki                    | ActionBar.DISPLAY_SHOW_HOME);
11113fd2d99efcafa86c117855aafaf9fca445d38dbMakoto Onuki            actionBar.setTitle("");
1124ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson        }
1134ec198790236ab4be6bc5d73441215b684832618Isaac Katzenelson
114cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        Log.i(TAG, getIntent().getData().toString());
1154cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    }
1164cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
11779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    @Override
11879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    public void onAttachFragment(Fragment fragment) {
119db0d8669cd1ffaa45827edb65b2b0eecb27561f5Katherine Kuan         if (fragment instanceof ContactLoaderFragment) {
1202eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment = (ContactLoaderFragment) fragment;
1212eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment.setListener(mLoaderFragmentListener);
1222eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mLoaderFragment.loadUri(getIntent().getData());
12379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        }
12479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
12579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
1264cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    @Override
127942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    public boolean onCreateOptionsMenu(Menu menu) {
128942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        super.onCreateOptionsMenu(menu);
129942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        MenuInflater inflater = getMenuInflater();
130942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        inflater.inflate(R.menu.star, menu);
1312a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        if (DEBUG_TRANSITIONS) {
1322a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann            final MenuItem toggleSocial =
1332a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                    menu.add(mLoaderFragment.getLoadStreamItems() ? "less" : "more");
1342a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann            toggleSocial.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
1352a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann            toggleSocial.setOnMenuItemClickListener(new OnMenuItemClickListener() {
1362a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                @Override
1372a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                public boolean onMenuItemClick(MenuItem item) {
1382a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                    mLoaderFragment.toggleLoadStreamItems();
1392a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                    invalidateOptionsMenu();
1402a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                    return false;
1412a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann                }
1422a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann            });
1432a45e35ab3273c8901d9df3671e51614dc0250c6Daniel Lehmann        }
144942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        return true;
145942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    }
146942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
147942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    @Override
148942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    public boolean onPrepareOptionsMenu(Menu menu) {
149c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        final MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
150c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann        starredMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
151942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            @Override
152c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            public boolean onMenuItemClick(MenuItem item) {
153942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                // Toggle "starred" state
154942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                // Make sure there is a contact
155942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                if (mLookupUri != null) {
156c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // Read the current starred value from the UI instead of using the last
157c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // loaded state. This allows rapid tapping without writing the same
158c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // value several times
159c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    final boolean isStarred = starredMenuItem.isChecked();
160c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann
161c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // To improve responsiveness, swap out the picture (and tag) in the UI already
162c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem,
163c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
164c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            !isStarred);
165c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann
166c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    // Now perform the real save
167942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                    Intent intent = ContactSaveService.createSetStarredIntent(
168c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                            ContactDetailActivity.this, mLookupUri, !isStarred);
169942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                    ContactDetailActivity.this.startService(intent);
170942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                }
171c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                return true;
172942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            }
173942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        });
174942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        // If there is contact data, update the starred state
175942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        if (mContactData != null) {
176c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann            ContactDetailDisplayUtils.configureStarredMenuItem(starredMenuItem,
177c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
178c42ea4eca298419484444a57bfc2da2c83e7adb7Daniel Lehmann                    mContactData.getStarred());
179942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        }
180942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan        return true;
181942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    }
182942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan
183942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan    @Override
1844cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    public boolean onKeyDown(int keyCode, KeyEvent event) {
18558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // First check if the {@link ContactLoaderFragment} can handle the key
186f6141f1bc0116dd5c9dc399567502d74300326b6Katherine Kuan        if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
18758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
18858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // Otherwise find the correct fragment to handle the event
18951f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        FragmentKeyListener mCurrentFragment = mContactDetailLayoutController.getCurrentPage();
190f6141f1bc0116dd5c9dc399567502d74300326b6Katherine Kuan        if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
1914cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann
19258fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        // In the last case, give the key event to the superclass.
1934cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann        return super.onKeyDown(keyCode, event);
1944cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann    }
19518f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann
1962eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    @Override
1972eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    protected void onSaveInstanceState(Bundle outState) {
1982eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        super.onSaveInstanceState(outState);
19951f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        if (mContactDetailLayoutController != null) {
20051f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan            mContactDetailLayoutController.onSaveInstanceState(outState);
20151f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan        }
2022eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
20318f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann
2042eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private final ContactLoaderFragmentListener mLoaderFragmentListener =
2052eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            new ContactLoaderFragmentListener() {
20669e7fec6dd8a3d24054863c6c648512577fce35cDaniel Lehmann        @Override
20758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onContactNotFound() {
20858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            finish();
20958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
21058fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
21158fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
212851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu        public void onDetailsLoaded(final Contact result) {
213942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            if (result == null) {
214942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan                return;
215942cec2d8a248b1a22e95f4d573d235e281ee91aKatherine Kuan            }
2162eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // Since {@link FragmentTransaction}s cannot be done in the onLoadFinished() of the
2172eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // {@link LoaderCallbacks}, then post this {@link Runnable} to the {@link Handler}
2182eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            // on the main thread to execute later.
2192eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            mHandler.post(new Runnable() {
2202eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                @Override
2212eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                public void run() {
222bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    // If the activity is destroyed (or will be destroyed soon), don't update the UI
223bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    if (isFinishing()) {
224bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                        return;
225bed71bedbaae4d6b26b2b64db476bffa710753e5Makoto Onuki                    }
2262eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    mContactData = result;
2272eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    mLookupUri = result.getLookupUri();
2282eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    invalidateOptionsMenu();
2292eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                    setupTitle();
23051f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan                    mContactDetailLayoutController.setContactData(mContactData);
2312eb969cc399d87b659a45568fa951d394c216917Katherine Kuan                }
2322eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            });
2332eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        }
23458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
23558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
23658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onEditRequested(Uri contactLookupUri) {
2375c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
2385c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            intent.putExtra(
2395c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan                    ContactEditorActivity.INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
2405c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // Don't finish the detail activity after launching the editor because when the
2415c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // editor is done, we will still want to show the updated contact details using
2425c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            // this activity.
2435c3a0a1440625fab859aab420cb08bc0276358a0Katherine Kuan            startActivity(intent);
24458fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
24558fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan
24658fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        @Override
24758fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        public void onDeleteRequested(Uri contactUri) {
24858fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan            ContactDeletionInteraction.start(ContactDetailActivity.this, contactUri, true);
24958fc577bd7966e6566cdcac09589a0d3e05128e7Katherine Kuan        }
2502eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    };
2512eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2522eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    /**
2532eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     * Setup the activity title and subtitle with contact name and company.
2542eb969cc399d87b659a45568fa951d394c216917Katherine Kuan     */
2552eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    private void setupTitle() {
2562eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        CharSequence displayName = ContactDetailDisplayUtils.getDisplayName(this, mContactData);
2572eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        String company =  ContactDetailDisplayUtils.getCompany(this, mContactData);
2582eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
2592eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        ActionBar actionBar = getActionBar();
2602eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        actionBar.setTitle(displayName);
2612eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        actionBar.setSubtitle(company);
262d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawa
263078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng        if (!TextUtils.isEmpty(displayName)) {
264078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            AccessibilityManager accessibilityManager =
265078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                    (AccessibilityManager) this.getSystemService(Context.ACCESSIBILITY_SERVICE);
266078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            if (accessibilityManager.isEnabled()) {
267078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                View decorView = getWindow().getDecorView();
268078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                decorView.setContentDescription(displayName);
269078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng                decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
270078d08f5e497231cbe7fb520b5a4e42a398201a6Chiao Cheng            }
271d6272412cdf3fdda90e835ec5b0cd1e15a0c97c9Daisuke Miyakawa        }
2722eb969cc399d87b659a45568fa951d394c216917Katherine Kuan    }
2732eb969cc399d87b659a45568fa951d394c216917Katherine Kuan
27451f1071a1dc91dace0de73be1c5fbba4f091f054Katherine Kuan    private final ContactDetailFragment.Listener mContactDetailFragmentListener =
2752eb969cc399d87b659a45568fa951d394c216917Katherine Kuan            new ContactDetailFragment.Listener() {
2762eb969cc399d87b659a45568fa951d394c216917Katherine Kuan        @Override
277cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann        public void onItemClicked(Intent intent) {
27808bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan            if (intent == null) {
27908bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan                return;
28008bcf715d5ea7f07ce18a282d9850ac70552ca9dKatherine Kuan            }
28160be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            try {
28260be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann                startActivity(intent);
28360be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            } catch (ActivityNotFoundException e) {
28460be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann                Log.e(TAG, "No activity found for intent: " + intent);
28560be1a1e8639a58d16f58686f8a89747d6079cc7Daniel Lehmann            }
28618f104fa8c167a510b2cca3c15a43833c9a54c7cDaniel Lehmann        }
287cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann
28869e7fec6dd8a3d24054863c6c648512577fce35cDaniel Lehmann        @Override
289caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov        public void onCreateRawContactRequested(
2902b3f3c54d3beb017b2f59f19e9ce0ecc3e039dbcDave Santoro                ArrayList<ContentValues> values, AccountWithDataSet account) {
291caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            Toast.makeText(ContactDetailActivity.this, R.string.toast_making_personal_copy,
292caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov                    Toast.LENGTH_LONG).show();
293caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
2949d730dd9d9efe125c9102b298f897577157ffecdDmitri Plotnikov                    ContactDetailActivity.this, values, account,
2959d730dd9d9efe125c9102b298f897577157ffecdDmitri Plotnikov                    ContactDetailActivity.class, Intent.ACTION_VIEW);
296caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov            startService(serviceIntent);
297caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov
298caf0bc759c4ef96dde5bb0a5256c1dcb51b6ccc4Dmitri Plotnikov        }
299cdef2b60aa87b1178033fdc964a3402386c03d7cDaniel Lehmann    };
30079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan
30179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    /**
30279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * This interface should be implemented by {@link Fragment}s within this
30379700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * activity so that the activity can determine whether the currently
30479700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     * displayed view is handling the key event or not.
30579700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan     */
30679700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    public interface FragmentKeyListener {
30779700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        /**
30879700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         * Returns true if the key down event will be handled by the implementing class, or false
30979700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         * otherwise.
31079700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan         */
31179700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan        public boolean handleKeyDown(int keyCode);
31279700889dad553dcde9e22a2fd23df768f68080fKatherine Kuan    }
3134cd94419d615e5513849516dfcbf0ce4cd08ecd0Daniel Lehmann}
314