Home | History | Annotate | Download | only in activities
      1 /*
      2  * Copyright (C) 2010 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.android.contacts.activities;
     18 
     19 import com.android.contacts.ContactLoader;
     20 import com.android.contacts.ContactSaveService;
     21 import com.android.contacts.ContactsActivity;
     22 import com.android.contacts.R;
     23 import com.android.contacts.detail.ContactDetailDisplayUtils;
     24 import com.android.contacts.detail.ContactDetailFragment;
     25 import com.android.contacts.detail.ContactDetailLayoutController;
     26 import com.android.contacts.detail.ContactLoaderFragment;
     27 import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
     28 import com.android.contacts.interactions.ContactDeletionInteraction;
     29 import com.android.contacts.model.AccountWithDataSet;
     30 import com.android.contacts.util.PhoneCapabilityTester;
     31 
     32 import android.app.ActionBar;
     33 import android.app.Fragment;
     34 import android.content.ActivityNotFoundException;
     35 import android.content.ContentValues;
     36 import android.content.Intent;
     37 import android.net.Uri;
     38 import android.os.Bundle;
     39 import android.os.Handler;
     40 import android.text.TextUtils;
     41 import android.util.Log;
     42 import android.view.KeyEvent;
     43 import android.view.Menu;
     44 import android.view.MenuInflater;
     45 import android.view.MenuItem;
     46 import android.view.View;
     47 import android.view.View.OnClickListener;
     48 import android.view.ViewGroup;
     49 import android.view.accessibility.AccessibilityEvent;
     50 import android.view.accessibility.AccessibilityManager;
     51 import android.widget.CheckBox;
     52 import android.widget.Toast;
     53 
     54 import java.util.ArrayList;
     55 
     56 public class ContactDetailActivity extends ContactsActivity {
     57     private static final String TAG = "ContactDetailActivity";
     58 
     59     /**
     60      * Intent key for a boolean that specifies whether the "up" afforance in this activity should
     61      * behave as default (return user back to {@link PeopleActivity}) or whether the activity should
     62      * instead be finished.
     63      */
     64     public static final String INTENT_KEY_IGNORE_DEFAULT_UP_BEHAVIOR = "ignoreDefaultUpBehavior";
     65 
     66     private ContactLoader.Result mContactData;
     67     private Uri mLookupUri;
     68     private boolean mIgnoreDefaultUpBehavior;
     69 
     70     private ContactDetailLayoutController mContactDetailLayoutController;
     71     private ContactLoaderFragment mLoaderFragment;
     72 
     73     private Handler mHandler = new Handler();
     74 
     75     @Override
     76     public void onCreate(Bundle savedState) {
     77         super.onCreate(savedState);
     78         if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
     79             // This activity must not be shown. We have to select the contact in the
     80             // PeopleActivity instead ==> Create a forward intent and finish
     81             final Intent originalIntent = getIntent();
     82             Intent intent = new Intent();
     83             intent.setAction(originalIntent.getAction());
     84             intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
     85             intent.setFlags(
     86                     Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_FORWARD_RESULT
     87                             | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
     88 
     89             intent.setClass(this, PeopleActivity.class);
     90             startActivity(intent);
     91             finish();
     92             return;
     93         }
     94 
     95         mIgnoreDefaultUpBehavior = getIntent().getBooleanExtra(
     96                 INTENT_KEY_IGNORE_DEFAULT_UP_BEHAVIOR, false);
     97 
     98         setContentView(R.layout.contact_detail_activity);
     99 
    100         mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
    101                 getFragmentManager(), findViewById(R.id.contact_detail_container),
    102                 mContactDetailFragmentListener);
    103 
    104         // We want the UP affordance but no app icon.
    105         // Setting HOME_AS_UP, SHOW_TITLE and clearing SHOW_HOME does the trick.
    106         ActionBar actionBar = getActionBar();
    107         if (actionBar != null) {
    108             actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
    109                     ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
    110                     | ActionBar.DISPLAY_SHOW_HOME);
    111             actionBar.setTitle("");
    112         }
    113 
    114         Log.i(TAG, getIntent().getData().toString());
    115     }
    116 
    117     @Override
    118     public void onAttachFragment(Fragment fragment) {
    119          if (fragment instanceof ContactLoaderFragment) {
    120             mLoaderFragment = (ContactLoaderFragment) fragment;
    121             mLoaderFragment.setListener(mLoaderFragmentListener);
    122             mLoaderFragment.loadUri(getIntent().getData());
    123         }
    124     }
    125 
    126     @Override
    127     public boolean onCreateOptionsMenu(Menu menu) {
    128         super.onCreateOptionsMenu(menu);
    129         MenuInflater inflater = getMenuInflater();
    130         inflater.inflate(R.menu.star, menu);
    131         return true;
    132     }
    133 
    134     @Override
    135     public boolean onPrepareOptionsMenu(Menu menu) {
    136         MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
    137         ViewGroup starredContainer = (ViewGroup) getLayoutInflater().inflate(
    138                 R.layout.favorites_star, null, false);
    139         final CheckBox starredView = (CheckBox) starredContainer.findViewById(R.id.star);
    140         starredView.setOnClickListener(new OnClickListener() {
    141             @Override
    142             public void onClick(View v) {
    143                 // Toggle "starred" state
    144                 // Make sure there is a contact
    145                 if (mLookupUri != null) {
    146                     Intent intent = ContactSaveService.createSetStarredIntent(
    147                             ContactDetailActivity.this, mLookupUri, starredView.isChecked());
    148                     ContactDetailActivity.this.startService(intent);
    149                 }
    150             }
    151         });
    152         // If there is contact data, update the starred state
    153         if (mContactData != null) {
    154             ContactDetailDisplayUtils.setStarred(mContactData, starredView);
    155         }
    156         starredMenuItem.setActionView(starredContainer);
    157         return true;
    158     }
    159 
    160     @Override
    161     public boolean onKeyDown(int keyCode, KeyEvent event) {
    162         // First check if the {@link ContactLoaderFragment} can handle the key
    163         if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
    164 
    165         // Otherwise find the correct fragment to handle the event
    166         FragmentKeyListener mCurrentFragment = mContactDetailLayoutController.getCurrentPage();
    167         if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
    168 
    169         // In the last case, give the key event to the superclass.
    170         return super.onKeyDown(keyCode, event);
    171     }
    172 
    173     @Override
    174     protected void onSaveInstanceState(Bundle outState) {
    175         super.onSaveInstanceState(outState);
    176         if (mContactDetailLayoutController != null) {
    177             mContactDetailLayoutController.onSaveInstanceState(outState);
    178         }
    179     }
    180 
    181     private final ContactLoaderFragmentListener mLoaderFragmentListener =
    182             new ContactLoaderFragmentListener() {
    183         @Override
    184         public void onContactNotFound() {
    185             finish();
    186         }
    187 
    188         @Override
    189         public void onDetailsLoaded(final ContactLoader.Result result) {
    190             if (result == null) {
    191                 return;
    192             }
    193             // Since {@link FragmentTransaction}s cannot be done in the onLoadFinished() of the
    194             // {@link LoaderCallbacks}, then post this {@link Runnable} to the {@link Handler}
    195             // on the main thread to execute later.
    196             mHandler.post(new Runnable() {
    197                 @Override
    198                 public void run() {
    199                     // If the activity is destroyed (or will be destroyed soon), don't update the UI
    200                     if (isFinishing()) {
    201                         return;
    202                     }
    203                     mContactData = result;
    204                     mLookupUri = result.getLookupUri();
    205                     invalidateOptionsMenu();
    206                     setupTitle();
    207                     mContactDetailLayoutController.setContactData(mContactData);
    208                 }
    209             });
    210         }
    211 
    212         @Override
    213         public void onEditRequested(Uri contactLookupUri) {
    214             startActivity(new Intent(Intent.ACTION_EDIT, contactLookupUri));
    215             finish();
    216         }
    217 
    218         @Override
    219         public void onDeleteRequested(Uri contactUri) {
    220             ContactDeletionInteraction.start(ContactDetailActivity.this, contactUri, true);
    221         }
    222     };
    223 
    224     /**
    225      * Setup the activity title and subtitle with contact name and company.
    226      */
    227     private void setupTitle() {
    228         CharSequence displayName = ContactDetailDisplayUtils.getDisplayName(this, mContactData);
    229         String company =  ContactDetailDisplayUtils.getCompany(this, mContactData);
    230 
    231         ActionBar actionBar = getActionBar();
    232         actionBar.setTitle(displayName);
    233         actionBar.setSubtitle(company);
    234 
    235         if (!TextUtils.isEmpty(displayName) &&
    236                 AccessibilityManager.getInstance(this).isEnabled()) {
    237             View decorView = getWindow().getDecorView();
    238             decorView.setContentDescription(displayName);
    239             decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
    240         }
    241     }
    242 
    243     private final ContactDetailFragment.Listener mContactDetailFragmentListener =
    244             new ContactDetailFragment.Listener() {
    245         @Override
    246         public void onItemClicked(Intent intent) {
    247             if (intent == null) {
    248                 return;
    249             }
    250             try {
    251                 startActivity(intent);
    252             } catch (ActivityNotFoundException e) {
    253                 Log.e(TAG, "No activity found for intent: " + intent);
    254             }
    255         }
    256 
    257         @Override
    258         public void onCreateRawContactRequested(
    259                 ArrayList<ContentValues> values, AccountWithDataSet account) {
    260             Toast.makeText(ContactDetailActivity.this, R.string.toast_making_personal_copy,
    261                     Toast.LENGTH_LONG).show();
    262             Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
    263                     ContactDetailActivity.this, values, account,
    264                     ContactDetailActivity.class, Intent.ACTION_VIEW);
    265             startService(serviceIntent);
    266 
    267         }
    268     };
    269 
    270     /**
    271      * This interface should be implemented by {@link Fragment}s within this
    272      * activity so that the activity can determine whether the currently
    273      * displayed view is handling the key event or not.
    274      */
    275     public interface FragmentKeyListener {
    276         /**
    277          * Returns true if the key down event will be handled by the implementing class, or false
    278          * otherwise.
    279          */
    280         public boolean handleKeyDown(int keyCode);
    281     }
    282 
    283     @Override
    284     public boolean onOptionsItemSelected(MenuItem item) {
    285 
    286         switch (item.getItemId()) {
    287             case android.R.id.home:
    288                 if (mIgnoreDefaultUpBehavior) {
    289                     finish();
    290                     return true;
    291                 }
    292                 Intent intent = new Intent(this, PeopleActivity.class);
    293                 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    294                 startActivity(intent);
    295                 finish();
    296                 return true;
    297             default:
    298                 break;
    299         }
    300         return super.onOptionsItemSelected(item);
    301     }
    302 }
    303