diff options
8 files changed, 117 insertions, 41 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml index c3df2457..77c38d7d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -421,8 +421,11 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <!-- Action string for selecting SIM for importing contacts --> <string name="import_from_sim">Import from SIM card</string> - <!-- Action string for selecting SIM for importing contacts, when more than one SIM card --> - <string name="import_from_sim_number">Import from SIM card #<xliff:g id="sim_number" example="2">%d</xliff:g></string> + <!-- Action string for selecting a SIM subscription for importing contacts --> + <string name="import_from_sim_summary">Import from SIM <xliff:g id="sim_name">%1$s</xliff:g> - <xliff:g id="sim_number">%2$s</xliff:g></string> + + <!-- Action string for selecting a SIM subscription for importing contacts, without a phone number --> + <string name="import_from_sim_summary_no_number">Import from SIM <xliff:g id="sim_name">%1$s</xliff:g></string> <!-- Action string for selecting (USB) storage for importing contacts [CHAR LIMIT=30] --> <string name="import_from_sdcard" product="default">Import from storage</string> diff --git a/res/values/styles.xml b/res/values/styles.xml index 54d5f8c8..802b8b7a 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -78,7 +78,7 @@ background and text color. See also android:style/Widget.Holo.TextView.ListSepar <item name="android:layout_height">match_parent</item> </style> - <style name="BackgroundOnlyTheme" parent="@android:style/Theme.Holo.Light"> + <style name="BackgroundOnlyTheme" parent="@android:style/Theme.Material.Light"> <item name="android:windowBackground">@null</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@null</item> diff --git a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java index 8d87714b..99b8df58 100644 --- a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java +++ b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java @@ -28,7 +28,10 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract.Contacts; +import android.telephony.SubInfoRecord; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -47,6 +50,7 @@ import com.android.contacts.common.vcard.ExportVCardActivity; import com.android.contacts.common.vcard.VCardCommonArguments; import com.android.dialerbind.analytics.AnalyticsDialogFragment; +import java.util.Collections; import java.util.List; /** @@ -57,6 +61,7 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment public static final String TAG = "ImportExportDialogFragment"; private static final String KEY_RES_ID = "resourceId"; + private static final String KEY_SUBSCRIPTION_ID = "subscriptionId"; private static final String ARG_CONTACTS_ARE_AVAILABLE = "CONTACTS_ARE_AVAILABLE"; private final String[] LOOKUP_PROJECTION = new String[] { @@ -91,15 +96,14 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment VCardCommonArguments.ARG_CALLING_ACTIVITY); // Adapter that shows a list of string resources - final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(getActivity(), + final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(), R.layout.select_dialog_item) { @Override public View getView(int position, View convertView, ViewGroup parent) { final TextView result = (TextView)(convertView != null ? convertView : dialogInflater.inflate(R.layout.select_dialog_item, parent, false)); - final int resId = getItem(position); - result.setText(resId); + result.setText(getItem(position).mLabel); return result; } }; @@ -107,21 +111,32 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment final TelephonyManager manager = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); - if (manager != null && manager.hasIccCard() - && res.getBoolean(R.bool.config_allow_sim_import)) { - adapter.add(R.string.import_from_sim); - } if (res.getBoolean(R.bool.config_allow_import_from_sdcard)) { - adapter.add(R.string.import_from_sdcard); + adapter.add(new AdapterEntry(getString(R.string.import_from_sdcard), + R.string.import_from_sdcard)); + } + if (manager != null && res.getBoolean(R.bool.config_allow_sim_import)) { + final List<SubInfoRecord> subInfoRecords = getAllSubInfoList(); + if (subInfoRecords.size() == 1) { + adapter.add(new AdapterEntry(getString(R.string.import_from_sim), + R.string.import_from_sim, subInfoRecords.get(0).subId)); + } else { + for (SubInfoRecord record : subInfoRecords) { + adapter.add(new AdapterEntry(getSubDescription(record), + R.string.import_from_sim, record.subId)); + } + } } if (res.getBoolean(R.bool.config_allow_export_to_sdcard)) { if (contactsAreAvailable) { - adapter.add(R.string.export_to_sdcard); + adapter.add(new AdapterEntry(getString(R.string.export_to_sdcard), + R.string.export_to_sdcard)); } } if (res.getBoolean(R.bool.config_allow_share_visible_contacts)) { if (contactsAreAvailable) { - adapter.add(R.string.share_visible_contacts); + adapter.add(new AdapterEntry(getString(R.string.share_visible_contacts), + R.string.share_visible_contacts)); } } @@ -130,11 +145,12 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment @Override public void onClick(DialogInterface dialog, int which) { boolean dismissDialog; - final int resId = adapter.getItem(which); + final int resId = adapter.getItem(which).mChoiceResourceId; switch (resId) { case R.string.import_from_sim: case R.string.import_from_sdcard: { - dismissDialog = handleImportRequest(resId); + dismissDialog = handleImportRequest(resId, + adapter.getItem(which).mSubscriptionId); break; } case R.string.export_to_sdcard: { @@ -207,7 +223,7 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment * * @return {@code true} if the dialog show be closed. {@code false} otherwise. */ - private boolean handleImportRequest(int resId) { + private boolean handleImportRequest(int resId, long subscriptionId) { // There are three possibilities: // - more than one accounts -> ask the user // - just one account -> use the account without asking the user @@ -219,6 +235,7 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment // Send over to the account selector final Bundle args = new Bundle(); args.putInt(KEY_RES_ID, resId); + args.putLong(KEY_SUBSCRIPTION_ID, subscriptionId); SelectAccountDialogFragment.show( getFragmentManager(), this, R.string.dialog_new_contact_account, @@ -231,7 +248,7 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment } AccountSelectionUtil.doImport(getActivity(), resId, - (size == 1 ? accountList.get(0) : null)); + (size == 1 ? accountList.get(0) : null), subscriptionId); return true; // Close the dialog. } @@ -240,7 +257,8 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment */ @Override public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) { - AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID), account); + AccountSelectionUtil.doImport(getActivity(), extraArgs.getInt(KEY_RES_ID), + account, extraArgs.getLong(KEY_SUBSCRIPTION_ID)); // At this point the dialog is still showing (which is why we can use getActivity() above) // So close it. @@ -252,4 +270,49 @@ public class ImportExportDialogFragment extends AnalyticsDialogFragment // See onAccountChosen() -- at this point the dialog is still showing. Close it. dismiss(); } + + /** + * Return the same values as {@link SubscriptionManager#getAllSubInfoList()} without relying + * on any hidden methods. + */ + // TODO: replace with a method that doesn't make assumptions about the number of SIM slots + private static List<SubInfoRecord> getAllSubInfoList() { + final List<SubInfoRecord> subInfoRecords0 = SubscriptionManager.getSubInfoUsingSlotId(0); + final List<SubInfoRecord> subInfoRecords1 = SubscriptionManager.getSubInfoUsingSlotId(1); + if (subInfoRecords0 == null && subInfoRecords1 != null) { + return subInfoRecords1; + } + if (subInfoRecords0 != null && subInfoRecords1 == null) { + return subInfoRecords0; + } + if (subInfoRecords0 == null && subInfoRecords1 == null) { + return Collections.EMPTY_LIST; + } + subInfoRecords0.addAll(subInfoRecords1); + return subInfoRecords0; + } + + private String getSubDescription(SubInfoRecord record) { + if (TextUtils.isEmpty(record.number)) { + // Don't include the phone number in the description, since we don't know the number. + return getString(R.string.import_from_sim_summary_no_number, record.displayName); + } + return getString(R.string.import_from_sim_summary, record.displayName, record.number); + } + + private static class AdapterEntry { + public final String mLabel; + public final int mChoiceResourceId; + public final long mSubscriptionId; + + public AdapterEntry(String label, int resId, long subscriptionId) { + mLabel = label; + mChoiceResourceId = resId; + mSubscriptionId = subscriptionId; + } + + public AdapterEntry(String label, int resId) { + this(label, resId, SubscriptionManager.INVALID_SUB_ID); + } + } } diff --git a/src/com/android/contacts/common/list/ContactTileAdapter.java b/src/com/android/contacts/common/list/ContactTileAdapter.java index 04f415dc..789ca026 100644 --- a/src/com/android/contacts/common/list/ContactTileAdapter.java +++ b/src/com/android/contacts/common/list/ContactTileAdapter.java @@ -562,7 +562,8 @@ public class ContactTileAdapter extends BaseAdapter { // Just line up children horizontally. for (int i = 0; i < count; i++) { - final View child = getChildAt(i); + final int rtlAdjustedIndex = isLayoutRtl() ? count - i - 1 : i; + final View child = getChildAt(rtlAdjustedIndex); // Note MeasuredWidth includes the padding. final int childWidth = child.getMeasuredWidth(); diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java index ab327369..68217b94 100644 --- a/src/com/android/contacts/common/util/AccountSelectionUtil.java +++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; +import android.telephony.SubscriptionManager; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; @@ -54,22 +55,31 @@ public class AccountSelectionUtil { final private Context mContext; final private int mResId; + final private long mSubscriptionId; final protected List<AccountWithDataSet> mAccountList; public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList, - int resId) { + int resId, long subscriptionId) { if (accountList == null || accountList.size() == 0) { Log.e(LOG_TAG, "The size of Account list is 0."); } mContext = context; mAccountList = accountList; mResId = resId; + mSubscriptionId = subscriptionId; + } + + public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList, + int resId) { + // Subscription id is only needed for importing from SIM card. We can safely ignore + // its value for SD card importing. + this(context, accountList, resId, SubscriptionManager.INVALID_SUB_ID); } public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); - doImport(mContext, mResId, mAccountList.get(which)); + doImport(mContext, mResId, mAccountList.get(which), mSubscriptionId); } } @@ -150,10 +160,11 @@ public class AccountSelectionUtil { .create(); } - public static void doImport(Context context, int resId, AccountWithDataSet account) { + public static void doImport(Context context, int resId, AccountWithDataSet account, + long subscriptionId) { switch (resId) { case R.string.import_from_sim: { - doImportFromSim(context, account); + doImportFromSim(context, account, subscriptionId); break; } case R.string.import_from_sdcard: { @@ -163,7 +174,8 @@ public class AccountSelectionUtil { } } - public static void doImportFromSim(Context context, AccountWithDataSet account) { + public static void doImportFromSim(Context context, AccountWithDataSet account, + long subscriptionId) { Intent importIntent = new Intent(Intent.ACTION_VIEW); importIntent.setType("vnd.android.cursor.item/sim-contact"); if (account != null) { @@ -171,6 +183,7 @@ public class AccountSelectionUtil { importIntent.putExtra("account_type", account.type); importIntent.putExtra("data_set", account.dataSet); } + importIntent.putExtra("subscription_id", subscriptionId); importIntent.setClassName("com.android.phone", "com.android.phone.SimContacts"); context.startActivity(importIntent); } diff --git a/src/com/android/contacts/common/vcard/ImportProcessor.java b/src/com/android/contacts/common/vcard/ImportProcessor.java index 37128755..219ec144 100644 --- a/src/com/android/contacts/common/vcard/ImportProcessor.java +++ b/src/com/android/contacts/common/vcard/ImportProcessor.java @@ -194,14 +194,14 @@ public class ImportProcessor extends ProcessorBase implements VCardEntryHandler Log.i(LOG_TAG, "Successfully finished importing one vCard file: " + uri); List<Uri> uris = committer.getCreatedUris(); if (mListener != null) { - if (uris != null && uris.size() > 0) { - // TODO: construct intent showing a list of imported contact list. + if (uris != null && uris.size() == 1) { mListener.onImportFinished(mImportRequest, mJobId, uris.get(0)); } else { - // Not critical, but suspicious. - Log.w(LOG_TAG, - "Created Uris is null or 0 length " + - "though the creation itself is successful."); + if (uris == null || uris.size() == 0) { + // Not critical, but suspicious. + Log.w(LOG_TAG, "Created Uris is null or 0 length " + + "though the creation itself is successful."); + } mListener.onImportFinished(mImportRequest, mJobId, null); } } diff --git a/src/com/android/contacts/common/vcard/ImportVCardActivity.java b/src/com/android/contacts/common/vcard/ImportVCardActivity.java index 70c98215..62e8431c 100644 --- a/src/com/android/contacts/common/vcard/ImportVCardActivity.java +++ b/src/com/android/contacts/common/vcard/ImportVCardActivity.java @@ -109,8 +109,6 @@ public class ImportVCardActivity extends Activity { final static String CACHED_URIS = "cached_uris"; - private AccountSelectionUtil.AccountSelectedListener mAccountSelectionListener; - private AccountWithDataSet mAccount; private ProgressDialog mProgressDialogForScanVCard; @@ -891,14 +889,6 @@ public class ImportVCardActivity extends Activity { @Override protected Dialog onCreateDialog(int resId, Bundle bundle) { switch (resId) { - case R.string.import_from_sdcard: { - if (mAccountSelectionListener == null) { - throw new NullPointerException( - "mAccountSelectionListener must not be null."); - } - return AccountSelectionUtil.getSelectAccountDialog(this, resId, - mAccountSelectionListener, mCancelListener); - } case R.id.dialog_searching_vcard: { if (mProgressDialogForScanVCard == null) { String message = getString(R.string.searching_vcard_message); diff --git a/src/com/android/contacts/common/vcard/NotificationImportExportListener.java b/src/com/android/contacts/common/vcard/NotificationImportExportListener.java index 41f6a50f..a85825f1 100644 --- a/src/com/android/contacts/common/vcard/NotificationImportExportListener.java +++ b/src/com/android/contacts/common/vcard/NotificationImportExportListener.java @@ -26,6 +26,7 @@ import android.content.Intent; import android.net.Uri; import android.os.Handler; import android.os.Message; +import android.provider.ContactsContract; import android.provider.ContactsContract.RawContacts; import android.widget.Toast; @@ -125,7 +126,8 @@ public class NotificationImportExportListener implements VCardImportExportListen RawContacts.CONTENT_URI, rawContactId)); intent = new Intent(Intent.ACTION_VIEW, contactUri); } else { - intent = null; + intent = new Intent(Intent.ACTION_VIEW); + intent.setType(ContactsContract.Contacts.CONTENT_TYPE); } final Notification notification = NotificationImportExportListener.constructFinishNotification(mContext, @@ -220,6 +222,7 @@ public class NotificationImportExportListener implements VCardImportExportListen .setProgress(totalCount, currentCount, totalCount == - 1) .setTicker(tickerText) .setContentTitle(description) + .setColor(context.getResources().getColor(R.color.dialtacts_theme_color)) .setSmallIcon(type == VCardService.TYPE_IMPORT ? android.R.drawable.stat_sys_download : android.R.drawable.stat_sys_upload) @@ -243,6 +246,7 @@ public class NotificationImportExportListener implements VCardImportExportListen return new Notification.Builder(context) .setAutoCancel(true) .setSmallIcon(android.R.drawable.stat_notify_error) + .setColor(context.getResources().getColor(R.color.dialtacts_theme_color)) .setContentTitle(description) .setContentText(description) .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0)) @@ -260,6 +264,7 @@ public class NotificationImportExportListener implements VCardImportExportListen Context context, String title, String description, Intent intent) { return new Notification.Builder(context) .setAutoCancel(true) + .setColor(context.getResources().getColor(R.color.dialtacts_theme_color)) .setSmallIcon(android.R.drawable.stat_sys_download_done) .setContentTitle(title) .setContentText(description) @@ -278,6 +283,7 @@ public class NotificationImportExportListener implements VCardImportExportListen Context context, String reason) { return new Notification.Builder(context) .setAutoCancel(true) + .setColor(context.getResources().getColor(R.color.dialtacts_theme_color)) .setSmallIcon(android.R.drawable.stat_notify_error) .setContentTitle(context.getString(R.string.vcard_import_failed)) .setContentText(reason) |