/* * Copyright (C) 2007 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 android.accounts.Account; import android.app.ActionBar; import android.app.ProgressDialog; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentValues; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.RemoteException; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; import android.util.Log; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.CursorAdapter; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import java.util.ArrayList; /** * SIM Address Book UI for the Phone app. */ public class SimContacts extends ADNList { private static final String LOG_TAG = "SimContacts"; private static final String UP_ACTIVITY_PACKAGE = "com.android.contacts"; private static final String UP_ACTIVITY_CLASS = "com.android.contacts.activities.PeopleActivity"; static final ContentValues sEmptyContentValues = new ContentValues(); private static final int MENU_IMPORT_ONE = 1; private static final int MENU_IMPORT_ALL = 2; private ProgressDialog mProgressDialog; private Account mAccount; private static class NamePhoneTypePair { final String name; final int phoneType; public NamePhoneTypePair(String nameWithPhoneType) { // Look for /W /H /M or /O at the end of the name signifying the type int nameLen = nameWithPhoneType.length(); if (nameLen - 2 >= 0 && nameWithPhoneType.charAt(nameLen - 2) == '/') { char c = Character.toUpperCase(nameWithPhoneType.charAt(nameLen - 1)); if (c == 'W') { phoneType = Phone.TYPE_WORK; } else if (c == 'M' || c == 'O') { phoneType = Phone.TYPE_MOBILE; } else if (c == 'H') { phoneType = Phone.TYPE_HOME; } else { phoneType = Phone.TYPE_OTHER; } name = nameWithPhoneType.substring(0, nameLen - 2); } else { phoneType = Phone.TYPE_OTHER; name = nameWithPhoneType; } } } private class ImportAllSimContactsThread extends Thread implements OnCancelListener, OnClickListener { boolean mCanceled = false; public ImportAllSimContactsThread() { super("ImportAllSimContactsThread"); } @Override public void run() { final ContentValues emptyContentValues = new ContentValues(); final ContentResolver resolver = getContentResolver(); mCursor.moveToPosition(-1); while (!mCanceled && mCursor.moveToNext()) { actuallyImportOneSimContact(mCursor, resolver, mAccount); mProgressDialog.incrementProgressBy(1); } mProgressDialog.dismiss(); finish(); } public void onCancel(DialogInterface dialog) { mCanceled = true; } public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_NEGATIVE) { mCanceled = true; mProgressDialog.dismiss(); } else { Log.e(LOG_TAG, "Unknown button event has come: " + dialog.toString()); } } } private static void actuallyImportOneSimContact( final Cursor cursor, final ContentResolver resolver, Account account) { final NamePhoneTypePair namePhoneTypePair = new NamePhoneTypePair(cursor.getString(NAME_COLUMN)); final String name = namePhoneTypePair.name; final int phoneType = namePhoneTypePair.phoneType; final String phoneNumber = cursor.getString(NUMBER_COLUMN); final String emailAddresses = cursor.getString(EMAILS_COLUMN); final String[] emailAddressArray; if (!TextUtils.isEmpty(emailAddresses)) { emailAddressArray = emailAddresses.split(","); } else { emailAddressArray = null; } final ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI); String myGroupsId = null; if (account != null) { builder.withValue(RawContacts.ACCOUNT_NAME, account.name); builder.withValue(RawContacts.ACCOUNT_TYPE, account.type); } else { builder.withValues(sEmptyContentValues); } operationList.add(builder.build()); builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); builder.withValue(StructuredName.DISPLAY_NAME, name); operationList.add(builder.build()); builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); builder.withValue(Phone.TYPE, phoneType); builder.withValue(Phone.NUMBER, phoneNumber); builder.withValue(Data.IS_PRIMARY, 1); operationList.add(builder.build()); if (emailAddresses != null) { for (String emailAddress : emailAddressArray) { builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(Email.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); builder.withValue(Email.TYPE, Email.TYPE_MOBILE); builder.withValue(Email.DATA, emailAddress); operationList.add(builder.build()); } } if (myGroupsId != null) { builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); builder.withValue(GroupMembership.GROUP_SOURCE_ID, myGroupsId); operationList.add(builder.build()); } try { resolver.applyBatch(ContactsContract.AUTHORITY, operationList); } catch (RemoteException e) { Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); } } private void importOneSimContact(int position) { final ContentResolver resolver = getContentResolver(); if (mCursor.moveToPosition(position)) { actuallyImportOneSimContact(mCursor, resolver, mAccount); } else { Log.e(LOG_TAG, "Failed to move the cursor to the position \"" + position + "\""); } } /* Followings are overridden methods */ @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); Intent intent = getIntent(); if (intent != null) { final String accountName = intent.getStringExtra("account_name"); final String accountType = intent.getStringExtra("account_type"); if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { mAccount = new Account(accountName, accountType); } } registerForContextMenu(getListView()); ActionBar actionBar = getActionBar(); if (actionBar != null) { // android.R.id.home will be triggered in onOptionsItemSelected() actionBar.setDisplayHomeAsUpEnabled(true); } } @Override protected CursorAdapter newAdapter() { return new SimpleCursorAdapter(this, R.layout.sim_import_list_entry, mCursor, new String[] { "name" }, new int[] { android.R.id.text1 }); } @Override protected Uri resolveIntent() { Intent intent = getIntent(); intent.setData(Uri.parse("content://icc/adn")); if (Intent.ACTION_PICK.equals(intent.getAction())) { // "index" is 1-based mInitialSelection = intent.getIntExtra("index", 0) - 1; } return intent.getData(); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, MENU_IMPORT_ALL, 0, R.string.importAllSimEntries); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item = menu.findItem(MENU_IMPORT_ALL); if (item != null) { item.setVisible(mCursor != null && mCursor.getCount() > 0); } return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: Intent intent = new Intent(); intent.setClassName(UP_ACTIVITY_PACKAGE, UP_ACTIVITY_CLASS); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); return true; case MENU_IMPORT_ALL: CharSequence title = getString(R.string.importAllSimEntries); CharSequence message = getString(R.string.importingSimContacts); ImportAllSimContactsThread thread = new ImportAllSimContactsThread(); // TODO: need to show some error dialog. if (mCursor == null) { Log.e(LOG_TAG, "cursor is null. Ignore silently."); break; } mProgressDialog = new ProgressDialog(this); mProgressDialog.setTitle(title); mProgressDialog.setMessage(message); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), thread); mProgressDialog.setProgress(0); mProgressDialog.setMax(mCursor.getCount()); mProgressDialog.show(); thread.start(); return true; } return super.onOptionsItemSelected(item); } @Override public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case MENU_IMPORT_ONE: ContextMenu.ContextMenuInfo menuInfo = item.getMenuInfo(); if (menuInfo instanceof AdapterView.AdapterContextMenuInfo) { int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position; importOneSimContact(position); return true; } } return super.onContextItemSelected(item); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { if (menuInfo instanceof AdapterView.AdapterContextMenuInfo) { AdapterView.AdapterContextMenuInfo itemInfo = (AdapterView.AdapterContextMenuInfo) menuInfo; TextView textView = (TextView) itemInfo.targetView.findViewById(android.R.id.text1); if (textView != null) { menu.setHeaderTitle(textView.getText()); } menu.add(0, MENU_IMPORT_ONE, 0, R.string.importSimEntry); } } @Override public void onListItemClick(ListView l, View v, int position, long id) { importOneSimContact(position); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_CALL: { if (mCursor != null && mCursor.moveToPosition(getSelectedItemPosition())) { String phoneNumber = mCursor.getString(NUMBER_COLUMN); if (phoneNumber == null || !TextUtils.isGraphic(phoneNumber)) { // There is no number entered. //TODO play error sound or something... return true; } Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts(Constants.SCHEME_TEL, phoneNumber, null)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent); finish(); return true; } } } return super.onKeyDown(keyCode, event); } }