diff options
Diffstat (limited to 'src/com/android/phone/EditFdnContactScreen.java')
-rwxr-xr-x | src/com/android/phone/EditFdnContactScreen.java | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/src/com/android/phone/EditFdnContactScreen.java b/src/com/android/phone/EditFdnContactScreen.java new file mode 100755 index 00000000..2992b7dc --- /dev/null +++ b/src/com/android/phone/EditFdnContactScreen.java @@ -0,0 +1,458 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.phone; + +import static android.view.Window.PROGRESS_VISIBILITY_OFF; +import static android.view.Window.PROGRESS_VISIBILITY_ON; + +import android.app.Activity; +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Intent; +import android.content.res.Resources; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.provider.Contacts.PeopleColumns; +import android.provider.Contacts.PhonesColumns; +import android.telephony.PhoneNumberUtils; +import android.text.Selection; +import android.text.Spannable; +import android.text.TextUtils; +import android.text.method.DialerKeyListener; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +/** + * Activity to let the user add or edit an FDN contact. + */ +public class EditFdnContactScreen extends Activity { + private static final String LOG_TAG = PhoneGlobals.LOG_TAG; + private static final boolean DBG = false; + + // Menu item codes + private static final int MENU_IMPORT = 1; + private static final int MENU_DELETE = 2; + + private static final String INTENT_EXTRA_NAME = "name"; + private static final String INTENT_EXTRA_NUMBER = "number"; + + private static final int PIN2_REQUEST_CODE = 100; + + private String mName; + private String mNumber; + private String mPin2; + private boolean mAddContact; + private QueryHandler mQueryHandler; + + private EditText mNameField; + private EditText mNumberField; + private LinearLayout mPinFieldContainer; + private Button mButton; + + private Handler mHandler = new Handler(); + + /** + * Constants used in importing from contacts + */ + /** request code when invoking subactivity */ + private static final int CONTACTS_PICKER_CODE = 200; + /** projection for phone number query */ + private static final String NUM_PROJECTION[] = {PeopleColumns.DISPLAY_NAME, + PhonesColumns.NUMBER}; + /** static intent to invoke phone number picker */ + private static final Intent CONTACT_IMPORT_INTENT; + static { + CONTACT_IMPORT_INTENT = new Intent(Intent.ACTION_GET_CONTENT); + CONTACT_IMPORT_INTENT.setType(android.provider.Contacts.Phones.CONTENT_ITEM_TYPE); + } + /** flag to track saving state */ + private boolean mDataBusy; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + + resolveIntent(); + + getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS); + setContentView(R.layout.edit_fdn_contact_screen); + setupView(); + setTitle(mAddContact ? + R.string.add_fdn_contact : R.string.edit_fdn_contact); + + displayProgress(false); + } + + /** + * We now want to bring up the pin request screen AFTER the + * contact information is displayed, to help with user + * experience. + * + * Also, process the results from the contact picker. + */ + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent intent) { + if (DBG) log("onActivityResult request:" + requestCode + " result:" + resultCode); + + switch (requestCode) { + case PIN2_REQUEST_CODE: + Bundle extras = (intent != null) ? intent.getExtras() : null; + if (extras != null) { + mPin2 = extras.getString("pin2"); + if (mAddContact) { + addContact(); + } else { + updateContact(); + } + } else if (resultCode != RESULT_OK) { + // if they cancelled, then we just cancel too. + if (DBG) log("onActivityResult: cancelled."); + finish(); + } + break; + + // look for the data associated with this number, and update + // the display with it. + case CONTACTS_PICKER_CODE: + if (resultCode != RESULT_OK) { + if (DBG) log("onActivityResult: cancelled."); + return; + } + Cursor cursor = null; + try { + cursor = getContentResolver().query(intent.getData(), + NUM_PROJECTION, null, null, null); + if ((cursor == null) || (!cursor.moveToFirst())) { + Log.w(LOG_TAG,"onActivityResult: bad contact data, no results found."); + return; + } + mNameField.setText(cursor.getString(0)); + mNumberField.setText(cursor.getString(1)); + } finally { + if (cursor != null) { + cursor.close(); + } + } + break; + } + } + + /** + * Overridden to display the import and delete commands. + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + + Resources r = getResources(); + + // Added the icons to the context menu + menu.add(0, MENU_IMPORT, 0, r.getString(R.string.importToFDNfromContacts)) + .setIcon(R.drawable.ic_menu_contact); + menu.add(0, MENU_DELETE, 0, r.getString(R.string.menu_delete)) + .setIcon(android.R.drawable.ic_menu_delete); + return true; + } + + /** + * Allow the menu to be opened ONLY if we're not busy. + */ + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + boolean result = super.onPrepareOptionsMenu(menu); + return mDataBusy ? false : result; + } + + /** + * Overridden to allow for handling of delete and import. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case MENU_IMPORT: + startActivityForResult(CONTACT_IMPORT_INTENT, CONTACTS_PICKER_CODE); + return true; + + case MENU_DELETE: + deleteSelected(); + return true; + } + + return super.onOptionsItemSelected(item); + } + + private void resolveIntent() { + Intent intent = getIntent(); + + mName = intent.getStringExtra(INTENT_EXTRA_NAME); + mNumber = intent.getStringExtra(INTENT_EXTRA_NUMBER); + + mAddContact = TextUtils.isEmpty(mNumber); + } + + /** + * We have multiple layouts, one to indicate that the user needs to + * open the keyboard to enter information (if the keybord is hidden). + * So, we need to make sure that the layout here matches that in the + * layout file. + */ + private void setupView() { + mNameField = (EditText) findViewById(R.id.fdn_name); + if (mNameField != null) { + mNameField.setOnFocusChangeListener(mOnFocusChangeHandler); + mNameField.setOnClickListener(mClicked); + } + + mNumberField = (EditText) findViewById(R.id.fdn_number); + if (mNumberField != null) { + mNumberField.setKeyListener(DialerKeyListener.getInstance()); + mNumberField.setOnFocusChangeListener(mOnFocusChangeHandler); + mNumberField.setOnClickListener(mClicked); + } + + if (!mAddContact) { + if (mNameField != null) { + mNameField.setText(mName); + } + if (mNumberField != null) { + mNumberField.setText(mNumber); + } + } + + mButton = (Button) findViewById(R.id.button); + if (mButton != null) { + mButton.setOnClickListener(mClicked); + } + + mPinFieldContainer = (LinearLayout) findViewById(R.id.pinc); + + } + + private String getNameFromTextField() { + return mNameField.getText().toString(); + } + + private String getNumberFromTextField() { + return mNumberField.getText().toString(); + } + + private Uri getContentURI() { + return Uri.parse("content://icc/fdn"); + } + + /** + * @param number is voice mail number + * @return true if number length is less than 20-digit limit + * + * TODO: Fix this logic. + */ + private boolean isValidNumber(String number) { + return (number.length() <= 20); + } + + + private void addContact() { + if (DBG) log("addContact"); + + final String number = PhoneNumberUtils.convertAndStrip(getNumberFromTextField()); + + if (!isValidNumber(number)) { + handleResult(false, true); + return; + } + + Uri uri = getContentURI(); + + ContentValues bundle = new ContentValues(3); + bundle.put("tag", getNameFromTextField()); + bundle.put("number", number); + bundle.put("pin2", mPin2); + + mQueryHandler = new QueryHandler(getContentResolver()); + mQueryHandler.startInsert(0, null, uri, bundle); + displayProgress(true); + showStatus(getResources().getText(R.string.adding_fdn_contact)); + } + + private void updateContact() { + if (DBG) log("updateContact"); + + final String name = getNameFromTextField(); + final String number = PhoneNumberUtils.convertAndStrip(getNumberFromTextField()); + + if (!isValidNumber(number)) { + handleResult(false, true); + return; + } + Uri uri = getContentURI(); + + ContentValues bundle = new ContentValues(); + bundle.put("tag", mName); + bundle.put("number", mNumber); + bundle.put("newTag", name); + bundle.put("newNumber", number); + bundle.put("pin2", mPin2); + + mQueryHandler = new QueryHandler(getContentResolver()); + mQueryHandler.startUpdate(0, null, uri, bundle, null, null); + displayProgress(true); + showStatus(getResources().getText(R.string.updating_fdn_contact)); + } + + /** + * Handle the delete command, based upon the state of the Activity. + */ + private void deleteSelected() { + // delete ONLY if this is NOT a new contact. + if (!mAddContact) { + Intent intent = new Intent(); + intent.setClass(this, DeleteFdnContactScreen.class); + intent.putExtra(INTENT_EXTRA_NAME, mName); + intent.putExtra(INTENT_EXTRA_NUMBER, mNumber); + startActivity(intent); + } + finish(); + } + + private void authenticatePin2() { + Intent intent = new Intent(); + intent.setClass(this, GetPin2Screen.class); + startActivityForResult(intent, PIN2_REQUEST_CODE); + } + + private void displayProgress(boolean flag) { + // indicate we are busy. + mDataBusy = flag; + getWindow().setFeatureInt( + Window.FEATURE_INDETERMINATE_PROGRESS, + mDataBusy ? PROGRESS_VISIBILITY_ON : PROGRESS_VISIBILITY_OFF); + // make sure we don't allow calls to save when we're + // not ready for them. + mButton.setClickable(!mDataBusy); + } + + /** + * Removed the status field, with preference to displaying a toast + * to match the rest of settings UI. + */ + private void showStatus(CharSequence statusMsg) { + if (statusMsg != null) { + Toast.makeText(this, statusMsg, Toast.LENGTH_LONG) + .show(); + } + } + + private void handleResult(boolean success, boolean invalidNumber) { + if (success) { + if (DBG) log("handleResult: success!"); + showStatus(getResources().getText(mAddContact ? + R.string.fdn_contact_added : R.string.fdn_contact_updated)); + } else { + if (DBG) log("handleResult: failed!"); + if (invalidNumber) { + showStatus(getResources().getText(R.string.fdn_invalid_number)); + } else { + // There's no way to know whether the failure is due to incorrect PIN2 or + // an inappropriate phone number. + showStatus(getResources().getText(R.string.pin2_or_fdn_invalid)); + } + } + + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + finish(); + } + }, 2000); + + } + + private final View.OnClickListener mClicked = new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mPinFieldContainer.getVisibility() != View.VISIBLE) { + return; + } + + if (v == mNameField) { + mNumberField.requestFocus(); + } else if (v == mNumberField) { + mButton.requestFocus(); + } else if (v == mButton) { + // Authenticate the pin AFTER the contact information + // is entered, and if we're not busy. + if (!mDataBusy) { + authenticatePin2(); + } + } + } + }; + + private final View.OnFocusChangeListener mOnFocusChangeHandler = + new View.OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + if (hasFocus) { + TextView textView = (TextView) v; + Selection.selectAll((Spannable) textView.getText()); + } + } + }; + + private class QueryHandler extends AsyncQueryHandler { + public QueryHandler(ContentResolver cr) { + super(cr); + } + + @Override + protected void onQueryComplete(int token, Object cookie, Cursor c) { + } + + @Override + protected void onInsertComplete(int token, Object cookie, Uri uri) { + if (DBG) log("onInsertComplete"); + displayProgress(false); + handleResult(uri != null, false); + } + + @Override + protected void onUpdateComplete(int token, Object cookie, int result) { + if (DBG) log("onUpdateComplete"); + displayProgress(false); + handleResult(result > 0, false); + } + + @Override + protected void onDeleteComplete(int token, Object cookie, int result) { + } + } + + private void log(String msg) { + Log.d(LOG_TAG, "[EditFdnContact] " + msg); + } +} |