Merge RP1A.200204.001
Change-Id: I82126a1eed36def1a786bfff86664a2309aa07d7
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e0814c1..f7136a2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -514,7 +514,6 @@
android:label="@string/sim_import_title"
android:theme="@style/PeopleThemeAppCompat.FullScreenDialog.SimImportActivity"/>
-
<service
android:name=".vcard.VCardService"
android:exported="false"/>
diff --git a/res/menu/people_options.xml b/res/menu/people_options.xml
index 5fb0f2e..18707e3 100644
--- a/res/menu/people_options.xml
+++ b/res/menu/people_options.xml
@@ -45,4 +45,9 @@
android:title="@string/menu_joinAggregate"
contacts:showAsAction="ifRoom"/>
+ <item
+ android:id="@+id/menu_select_all"
+ android:title="@string/menu_select_all"
+ contacts:showAsAction="never"/>
+
</menu>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 6702431..6b5b190 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -92,6 +92,7 @@
<string name="multipleContactDeleteConfirmation" msgid="2970218685653877287">"删除此联系人也将删除多个帐号中的相关详细信息。"</string>
<string name="deleteConfirmation" msgid="3727809366015979585">"要删除此联系人吗?"</string>
<string name="deleteConfirmation_positive_button" msgid="1604511403421785160">"删除"</string>
+ <string name="delete_contacts_title">删除联系人</string>
<string name="invalidContactMessage" msgid="6204402264821083362">"该联系人不存在。"</string>
<string name="createContactShortcutSuccessful_NoName" msgid="532242135930208299">"已将该联系人添加到主屏幕。"</string>
<string name="createContactShortcutSuccessful" msgid="6980032407920515698">"已将<xliff:g id="NAME">%s</xliff:g>添加到主屏幕。"</string>
@@ -135,6 +136,7 @@
<string name="missing_app" msgid="5674389915738964148">"未找到可处理此操作的应用。"</string>
<string name="menu_share" msgid="6343022811796001773">"分享"</string>
<string name="menu_add_contact" msgid="5822356185421997656">"添加到通讯录"</string>
+ <string name="menu_select_all">全选</string>
<string name="menu_add_contacts" msgid="7114262784903366463">"添加"</string>
<plurals name="title_share_via" formatted="false" msgid="3868648642107664607">
<item quantity="other">通过以下应用分享联系人</item>
@@ -163,6 +165,7 @@
<string name="contact_directory_description" msgid="1773630547110881835">"目录类型:<xliff:g id="TYPE">%1$s</xliff:g>"</string>
<string name="activity_title_settings" msgid="4004290638426915162">"设置"</string>
<string name="menu_settings" msgid="3524924670246877187">"设置"</string>
+ <string name="menu_sim_contacts">"SIM卡联系人"</string>
<string name="menu_help" msgid="287801702920372292">"帮助和反馈"</string>
<string name="organization_company_and_title" msgid="7197631449041284518">"<xliff:g id="COMPANY_0">%2$s</xliff:g>,<xliff:g id="COMPANY_1">%1$s</xliff:g>"</string>
<string name="non_phone_caption" msgid="7343449684187013327">"电话号码"</string>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index a4b8b4b..751d667 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -25,6 +25,9 @@
<!-- For ContactMultiDeletionInteraction -->
<item type="id" name="dialog_delete_multiple_contact_loader_id" />
+ <!-- For ContactMultiShareInteraction -->
+ <item type="id" name="dialog_share_multiple_contact_loader_id" />
+
<!-- For PhoneNumberInteraction -->
<item type="id" name="dialog_phone_number_call_disambiguation"/>
@@ -71,6 +74,9 @@
<!-- Menu ID for Settings menu -->
<item type="id" name="nav_settings" />
+ <!-- Menu ID for SIM contacts menu -->
+ <item type="id" name="nav_sim_contacts" />
+
<!-- Menu ID for help & feedback menu -->
<item type="id" name="nav_help" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 56c4aaa..96a5731 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -232,6 +232,9 @@
<!-- Positive button text of confirmation dialog contents after users selects to delete a Writable contact. [CHAR LIMIT=30] -->
<string name="deleteConfirmation_positive_button">Delete</string>
+ <!-- Deleting dialog, shown after users selects to delete multiple contacts writable contacts. [CHAR LIMIT=NONE] -->
+ <string name="delete_contacts_title">Deleting contacts</string>
+
<!-- Message displayed in a toast when you try to view the details of a contact that
for some reason doesn't exist anymore. [CHAR LIMIT=NONE]-->
<string name="invalidContactMessage">The contact doesn\'t exist.</string>
@@ -366,6 +369,9 @@
<!-- The menu item to share the currently viewed contact [CHAR LIMIT=30] -->
<string name="menu_share">Share</string>
+ <!-- The menu item to select all contacts -->
+ <string name="menu_select_all">Select all</string>
+
<!-- The menu item to add the the currently viewed contact to your contacts [CHAR LIMIT=30] -->
<string name="menu_add_contact">Add to contacts</string>
@@ -449,6 +455,9 @@
<!-- Menu item for the settings activity [CHAR LIMIT=64] -->
<string name="menu_settings" msgid="377929915873428211">Settings</string>
+ <!-- Menu item for the sim contacts-->
+ <string name="menu_sim_contacts">SIM contacts</string>
+
<!-- Menu item for invoking contextual Help & Feedback [CHAR LIMIT=64] -->
<string name="menu_help">Help & feedback</string>
@@ -1533,4 +1542,4 @@
<!-- Text of Negative Button in dialog -->
<string name="no_button">No</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index e5f808d..4e1afaa 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -473,7 +473,6 @@
loadThumbnail(view, photoId, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR);
}
-
/**
* Load photo into the supplied image view. If the photo is already cached,
* it is displayed immediately. Otherwise a request is sent to load the photo
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
old mode 100755
new mode 100644
index 9f25726..4372488
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -166,6 +166,9 @@
public static final int RESULT_UNKNOWN = 0;
public static final int RESULT_SUCCESS = 1;
public static final int RESULT_FAILURE = 2;
+ public static final int CONTACTS_DELETE_STARTED = 0;
+ public static final int CONTACTS_DELETE_INCREMENT = 1;
+ public static final int CONTACTS_DELETE_COMPLETE = 2;
private static final HashSet<String> ALLOWED_DATA_COLUMNS = Sets.newHashSet(
Data.MIMETYPE,
@@ -561,7 +564,7 @@
// removed if all information was removed, we need to do a special query to
// get the lookup URI for the profile contact (if it still exists).
Cursor c = resolver.query(Profile.CONTENT_URI,
- new String[] {Contacts._ID, Contacts.LOOKUP_KEY},
+ new String[]{Contacts._ID, Contacts.LOOKUP_KEY},
null, null, null);
if (c == null) {
continue;
@@ -577,7 +580,7 @@
}
} else {
final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
- rawContactId);
+ rawContactId);
lookupUri = RawContacts.getContactLookupUri(resolver, rawContactUri);
}
if (lookupUri != null && Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -1183,10 +1186,19 @@
*/
public static Intent createDeleteMultipleContactsIntent(Context context,
long[] contactIds, final String[] names) {
+ return createDeleteMultipleContactsIntent(context, contactIds, names, /* receiver = */null);
+ }
+
+ /**
+ * Creates an intent that can be sent to this service to delete multiple contacts.
+ */
+ public static Intent createDeleteMultipleContactsIntent(Context context,
+ long[] contactIds, final String[] names, ResultReceiver receiver) {
Intent serviceIntent = new Intent(context, ContactSaveService.class);
serviceIntent.setAction(ContactSaveService.ACTION_DELETE_MULTIPLE_CONTACTS);
serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_IDS, contactIds);
serviceIntent.putExtra(ContactSaveService.EXTRA_DISPLAY_NAME_ARRAY, names);
+ serviceIntent.putExtra(ContactSaveService.EXTRA_RESULT_RECEIVER, receiver);
return serviceIntent;
}
@@ -1206,9 +1218,13 @@
Log.e(TAG, "Invalid arguments for deleteMultipleContacts request");
return;
}
+ final ResultReceiver receiver = intent.getParcelableExtra(
+ ContactSaveService.EXTRA_RESULT_RECEIVER);
+ notifyActionProgress(CONTACTS_DELETE_STARTED, receiver);
for (long contactId : contactIds) {
final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
getContentResolver().delete(contactUri, null, null);
+ notifyActionProgress(CONTACTS_DELETE_INCREMENT, receiver);
}
final String[] names = intent.getStringArrayExtra(
ContactSaveService.EXTRA_DISPLAY_NAME_ARRAY);
@@ -1227,6 +1243,7 @@
R.string.contacts_deleted_many_named_toast, (Object[]) names);
}
+ notifyActionProgress(CONTACTS_DELETE_COMPLETE, receiver);
mMainHandler.post(new Runnable() {
@Override
public void run() {
@@ -1236,6 +1253,12 @@
});
}
+ private void notifyActionProgress(int state, ResultReceiver receiver){
+ if (receiver != null) {
+ receiver.send(state, new Bundle());
+ }
+ }
+
/**
* Creates an intent that can be sent to this service to split a contact into it's constituent
* pieces. This will set the raw contact ids to {@link AggregationExceptions#TYPE_AUTOMATIC} so
diff --git a/src/com/android/contacts/ShortcutIntentBuilder.java b/src/com/android/contacts/ShortcutIntentBuilder.java
index 5ea6b7e..22d0f9c 100644
--- a/src/com/android/contacts/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/ShortcutIntentBuilder.java
@@ -157,7 +157,6 @@
protected String mLookupKey;
protected byte[] mBitmapData;
protected long mPhotoId;
-
public LoadingAsyncTask(Uri uri) {
mUri = uri;
}
@@ -193,6 +192,7 @@
}
private final class ContactLoadingAsyncTask extends LoadingAsyncTask {
+
public ContactLoadingAsyncTask(Uri uri) {
super(uri);
}
diff --git a/src/com/android/contacts/SimImportFragment.java b/src/com/android/contacts/SimImportFragment.java
index cee1b1a..0039f2b 100644
--- a/src/com/android/contacts/SimImportFragment.java
+++ b/src/com/android/contacts/SimImportFragment.java
@@ -438,6 +438,8 @@
return contact.getPhone();
} else if (contact.hasEmails()) {
return contact.getEmails()[0];
+ } else if(contact.hasAnrs()) {
+ return contact.getAnrs()[0];
} else {
// This isn't really possible because we skip empty SIM contacts during loading
return "";
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 243ec00..84924ae 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -736,7 +736,7 @@
fragment.updateStatus(mProviderStatus);
}
if (!transaction.isEmpty()) {
- transaction.commit();
+ transaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
@@ -1195,6 +1195,16 @@
}
@Override
+ public void onLaunchSimContactsManagement() {
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ startActivity(ImplicitIntentsUtil.getIntentForSimContactsManagement());
+ }
+ }, DRAWER_CLOSE_DELAY);
+ }
+
+ @Override
public void onGroupViewSelected(GroupListItem groupListItem) {
onGroupMenuItemClicked(groupListItem.getGroupId());
}
diff --git a/src/com/android/contacts/database/SimContactDaoImpl.java b/src/com/android/contacts/database/SimContactDaoImpl.java
index 5ba6bd5..36ad9f2 100644
--- a/src/com/android/contacts/database/SimContactDaoImpl.java
+++ b/src/com/android/contacts/database/SimContactDaoImpl.java
@@ -82,6 +82,7 @@
public static String NAME = "name";
public static String NUMBER = "number";
public static String EMAILS = "emails";
+ public static String ANRS = "anrs";
private final Context mContext;
private final ContentResolver mResolver;
@@ -292,7 +293,7 @@
final int colName = cursor.getColumnIndex(NAME);
final int colNumber = cursor.getColumnIndex(NUMBER);
final int colEmails = cursor.getColumnIndex(EMAILS);
-
+ final int colAnrs = cursor.getColumnIndex(ANRS);
final ArrayList<SimContact> result = new ArrayList<>();
while (cursor.moveToNext()) {
@@ -300,10 +301,14 @@
final String name = cursor.getString(colName);
final String number = cursor.getString(colNumber);
final String emails = cursor.getString(colEmails);
-
- final SimContact contact = new SimContact(id, name, number, parseEmails(emails));
+ String anrs = "";
+ if (colAnrs >=0 )
+ anrs = cursor.getString(colAnrs);
+ final SimContact contact = new SimContact(id, name, number, parseEmails(emails),
+ parseAnrs(anrs));
// Only include contact if it has some useful data
- if (contact.hasName() || contact.hasPhone() || contact.hasEmails()) {
+ if (contact.hasName() || contact.hasPhone() || contact.hasEmails()
+ || contact.hasAnrs()) {
result.add(contact);
}
}
@@ -396,6 +401,10 @@
return !TextUtils.isEmpty(emails) ? emails.split(",") : null;
}
+ private String[] parseAnrs(String anrs) {
+ return !TextUtils.isEmpty(anrs) ? anrs.split(":") : null;
+ }
+
private boolean hasTelephony() {
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
}
diff --git a/src/com/android/contacts/drawer/DrawerAdapter.java b/src/com/android/contacts/drawer/DrawerAdapter.java
index b5a1ea7..4631c16 100644
--- a/src/com/android/contacts/drawer/DrawerAdapter.java
+++ b/src/com/android/contacts/drawer/DrawerAdapter.java
@@ -33,6 +33,7 @@
import com.android.contacts.model.account.AccountDisplayInfo;
import com.android.contacts.model.account.AccountDisplayInfoFactory;
import com.android.contacts.util.SharedPreferenceUtil;
+import com.android.contacts.util.ImplicitIntentsUtil;
import com.android.contactsbind.HelpUtils;
import com.android.contactsbind.ObjectFactory;
@@ -115,6 +116,11 @@
mMiscItems.add(new DividerItem());
mMiscItems.add(new MiscItem(R.id.nav_settings, R.string.menu_settings,
R.drawable.quantum_ic_settings_vd_theme_24));
+ if (ImplicitIntentsUtil.checkIntentIfExists(mActivity,
+ ImplicitIntentsUtil.getIntentForSimContactsManagement())) {
+ mMiscItems.add(new MiscItem(R.id.nav_sim_contacts, R.string.menu_sim_contacts,
+ R.drawable.quantum_ic_sim_card_vd_theme_24));
+ }
if (HelpUtils.isHelpAndFeedbackAvailable()) {
mMiscItems.add(new MiscItem(R.id.nav_help, R.string.menu_help,
R.drawable.quantum_ic_help_vd_theme_24));
@@ -283,6 +289,11 @@
final ImageView icon = (ImageView) result.findViewById(R.id.icon);
icon.setScaleType(ImageView.ScaleType.FIT_CENTER);
icon.setImageDrawable(displayableAccount.getIcon());
+ if (account.accountName != null) {
+ textView.setText(account.accountName);
+ }else {
+ textView.setText(displayableAccount.getNameLabel());
+ }
result.setTag(account);
result.setActivated(activated);
diff --git a/src/com/android/contacts/drawer/DrawerFragment.java b/src/com/android/contacts/drawer/DrawerFragment.java
index 485513a..bcd1856 100644
--- a/src/com/android/contacts/drawer/DrawerFragment.java
+++ b/src/com/android/contacts/drawer/DrawerFragment.java
@@ -256,6 +256,8 @@
mListener.onCreateLabelButtonClicked();
} else if (viewId == R.id.nav_settings) {
mListener.onOpenSettings();
+ } else if (viewId == R.id.nav_sim_contacts) {
+ mListener.onLaunchSimContactsManagement();
} else if (viewId == R.id.nav_help) {
mListener.onLaunchHelpFeedback();
} else {
@@ -313,6 +315,7 @@
void onCreateLabelButtonClicked();
void onOpenSettings();
void onLaunchHelpFeedback();
+ void onLaunchSimContactsManagement();
}
private class WindowInsetsListener implements View.OnApplyWindowInsetsListener {
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
old mode 100755
new mode 100644
diff --git a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
index 47b76a5..b9c4023 100644
--- a/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactMultiDeletionInteraction.java
@@ -18,14 +18,19 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.ProgressDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.LoaderManager.LoaderCallbacks;
+import android.os.Handler;
+import android.support.v4.os.ResultReceiver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Loader;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract.RawContacts;
@@ -82,6 +87,7 @@
private TreeSet<Long> mContactIds;
private Context mContext;
private AlertDialog mDialog;
+ private ProgressDialog mProgressDialog;
private MultiContactDeleteListener mListener;
/**
@@ -125,6 +131,12 @@
mDialog.dismiss();
mDialog = null;
}
+
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.setOnDismissListener(null);
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
}
public void setContactIds(TreeSet<Long> contactIds) {
@@ -165,19 +177,17 @@
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
final TreeSet<Long> contactIds = (TreeSet<Long>) args.getSerializable(ARG_CONTACT_IDS);
final Object[] parameterObject = contactIds.toArray();
- final String[] parameters = new String[contactIds.size()];
- final StringBuilder builder = new StringBuilder();
+ final StringBuilder builder = new StringBuilder(RawContacts.CONTACT_ID + " in (");
for (int i = 0; i < contactIds.size(); i++) {
- parameters[i] = String.valueOf(parameterObject[i]);
- builder.append(RawContacts.CONTACT_ID + " =?");
- if (i == contactIds.size() -1) {
- break;
+ if (i > 0){
+ builder.append(",");
}
- builder.append(" OR ");
+ builder.append(String.valueOf(parameterObject[i]));
}
+ builder.append(")");
return new CursorLoader(mContext, RawContacts.CONTENT_URI, RAW_CONTACT_PROJECTION,
- builder.toString(), parameters, null);
+ builder.toString(), null, null);
}
@Override
@@ -310,13 +320,66 @@
}
}
+ private void showProgressDialog(){
+ CharSequence title = getString(R.string.delete_contacts_title);
+
+ mProgressDialog = new ProgressDialog(mContext);
+ mProgressDialog.setTitle(title);
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ mProgressDialog.setProgress(0);
+ mProgressDialog.setMax(mContactIds.size());
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+ mProgressDialog = null;
+ }
+ });
+ mProgressDialog.show();
+ lockScreen();
+ }
+
protected void doDeleteContact(long[] contactIds, final String[] names) {
+ ResultReceiver receiver = new ResultReceiver(new Handler()){
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ super.onReceiveResult(resultCode, resultData);
+ switch (resultCode){
+ case ContactSaveService.CONTACTS_DELETE_STARTED:
+ showProgressDialog();
+ break;
+ case ContactSaveService.CONTACTS_DELETE_INCREMENT:
+ if (mProgressDialog != null){
+ mProgressDialog.incrementProgressBy(1);
+ }
+ break;
+ case ContactSaveService.CONTACTS_DELETE_COMPLETE:
+ if (mProgressDialog != null){
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ break;
+ }
+ }
+ };
+
mContext.startService(ContactSaveService.createDeleteMultipleContactsIntent(mContext,
- contactIds, names));
+ contactIds, names, receiver));
mListener.onDeletionFinished();
}
public void setListener(MultiContactDeleteListener listener) {
mListener = listener;
}
+
+ private void lockScreen(){
+ Configuration configuration = getActivity().getResources().getConfiguration();
+ int ori = configuration.orientation;
+ if (ori == configuration.ORIENTATION_LANDSCAPE) {
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ } else if (ori == configuration.ORIENTATION_PORTRAIT) {
+ getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+ }
}
diff --git a/src/com/android/contacts/interactions/ContactMultiShareInteraction.java b/src/com/android/contacts/interactions/ContactMultiShareInteraction.java
new file mode 100644
index 0000000..559a2e2
--- /dev/null
+++ b/src/com/android/contacts/interactions/ContactMultiShareInteraction.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (C) 2015 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.contacts.interactions;
+
+import android.content.Intent;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.provider.ContactsContract;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.ContentUris;
+import android.content.AsyncTaskLoader;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Loader;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.android.contacts.ContactSaveService;
+import com.android.contacts.R;
+
+import java.util.List;
+import java.util.TreeSet;
+/**
+ * An interaction invoked to share multiple contacts.
+ */
+public class ContactMultiShareInteraction extends Fragment
+ implements LoaderCallbacks<String> {
+
+ private static final int ACTIVITY_REQUEST_CODE_SHARE = 0;
+
+ private static final String FRAGMENT_TAG = "shareMultipleContacts";
+ private static final String TAG = "ContactMultiShare";
+ private static final String KEY_ACTIVE = "active";
+ private static final String KEY_CONTACTS_IDS = "contactIds";
+ public static final String ARG_CONTACT_IDS = "contactIds";
+
+ private boolean mIsLoaderActive;
+ private TreeSet<Long> mContactIds;
+ private Context mContext;
+ private static ProgressDialog mProgressDialog;
+
+ /**
+ * Starts the interaction.
+ *
+ * @param hostFragment the fragment within which to start the interaction
+ * @param contactIds the IDs of contacts to be shared
+ * @return the newly created interaction
+ */
+ public static ContactMultiShareInteraction start(
+ Fragment hostFragment, TreeSet<Long> contactIds) {
+ if (contactIds == null) {
+ return null;
+ }
+
+ final FragmentManager fragmentManager = hostFragment.getFragmentManager();
+ ContactMultiShareInteraction fragment =
+ (ContactMultiShareInteraction) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
+ if (fragment == null) {
+ fragment = new ContactMultiShareInteraction();
+ fragment.setContactIds(contactIds);
+ fragmentManager.beginTransaction().add(fragment, FRAGMENT_TAG)
+ .commitAllowingStateLoss();
+ } else {
+ fragment.setContactIds(contactIds);
+ }
+ return fragment;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mContext = activity;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mProgressDialog != null && mProgressDialog.isShowing()) {
+ mProgressDialog.setOnDismissListener(null);
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ }
+
+ public void setContactIds(TreeSet<Long> contactIds) {
+ mContactIds = contactIds;
+ mIsLoaderActive = true;
+ if (isStarted()) {
+ Bundle args = new Bundle();
+ args.putSerializable(ARG_CONTACT_IDS, mContactIds);
+ getLoaderManager().restartLoader(R.id.dialog_share_multiple_contact_loader_id,
+ args, this);
+ showDialog();
+ }
+ }
+
+ private boolean isStarted() {
+ return isAdded();
+ }
+
+ @Override
+ public void onStart() {
+ if (mIsLoaderActive) {
+ Bundle args = new Bundle();
+ args.putSerializable(ARG_CONTACT_IDS, mContactIds);
+ getLoaderManager().initLoader(
+ R.id.dialog_share_multiple_contact_loader_id, args, this);
+ showDialog();
+ }
+ super.onStart();
+ }
+
+ @Override
+ public Loader<String> onCreateLoader(int id, Bundle args) {
+ final TreeSet<Long> contactIds = (TreeSet<Long>) args.getSerializable(ARG_CONTACT_IDS);
+ return new ShareContactsLoader(mContext, contactIds);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<String> loader, String uriList) {
+ if (mProgressDialog != null){
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+
+ if (!mIsLoaderActive) {
+ return;
+ }
+
+ if (TextUtils.isEmpty(uriList)) {
+ Log.e(TAG, "Failed to load contacts");
+ return;
+ }
+
+ final Uri uri = Uri.withAppendedPath(
+ ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
+ Uri.encode(uriList));
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(ContactsContract.Contacts.CONTENT_VCARD_TYPE);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ try {
+ startActivityForResult(Intent.createChooser(intent, mContext.getResources().getQuantityString(
+ R.plurals.title_share_via,/* quantity */ mContactIds.size()))
+ , ACTIVITY_REQUEST_CODE_SHARE);
+ } catch (final ActivityNotFoundException ex) {
+ Toast.makeText(getContext(), R.string.share_error, Toast.LENGTH_SHORT).show();
+ }
+
+ // We don't want onLoadFinished() calls any more, which may come when the database is
+ // updating.
+ getLoaderManager().destroyLoader(R.id.dialog_share_multiple_contact_loader_id);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<String> loader) {
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putBoolean(KEY_ACTIVE, mIsLoaderActive);
+ outState.putSerializable(KEY_CONTACTS_IDS, mContactIds);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState != null) {
+ mIsLoaderActive = savedInstanceState.getBoolean(KEY_ACTIVE);
+ mContactIds = (TreeSet<Long>) savedInstanceState.getSerializable(KEY_CONTACTS_IDS);
+ }
+ }
+
+ private void cancelLoad(){
+ if(isStarted()){
+ Loader loader = getLoaderManager()
+ .getLoader(R.id.dialog_share_multiple_contact_loader_id);
+ if (loader != null){
+ loader.cancelLoad();
+ }
+ }
+ }
+
+ private void showDialog(){
+ CharSequence title = getString(R.string.exporting_contact_list_title);
+
+ mProgressDialog = new ProgressDialog(mContext);
+ mProgressDialog.setTitle(title);
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,
+ getString(android.R.string.cancel), (OnClickListener)null);
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setProgress(0);
+ mProgressDialog.setMax(mContactIds.size());
+ mProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ cancelLoad();
+ mIsLoaderActive = false;
+ mProgressDialog = null;
+ }
+ });
+
+ mProgressDialog.show();
+ }
+
+ private static class ShareContactsLoader extends AsyncTaskLoader<String>{
+ private TreeSet<Long> mSelectedContactIds;
+ private int mProgress;
+
+ public ShareContactsLoader(Context context, TreeSet<Long> contactIds){
+ super(context);
+ mSelectedContactIds = contactIds;
+ }
+
+ @Override
+ protected void onStartLoading() {
+ forceLoad();
+ }
+
+ @Override
+ public String loadInBackground() {
+ final StringBuilder uriListBuilder = new StringBuilder();
+ for (Long contactId : mSelectedContactIds) {
+ if (!isLoadInBackgroundCanceled()) {
+ updateProgress();
+ final Uri contactUri = ContentUris.withAppendedId(
+ ContactsContract.Contacts.CONTENT_URI, contactId);
+ final Uri lookupUri = ContactsContract.Contacts.getLookupUri(
+ getContext().getContentResolver(), contactUri);
+ if (lookupUri == null) {
+ continue;
+ }
+ final List<String> pathSegments = lookupUri.getPathSegments();
+ if (pathSegments.size() < 2) {
+ continue;
+ }
+ final String lookupKey = pathSegments.get(pathSegments.size() - 2);
+ if (uriListBuilder.length() > 0) {
+ uriListBuilder.append(':');
+ }
+ uriListBuilder.append(Uri.encode(lookupKey));
+ }
+
+ }
+ return uriListBuilder.toString();
+ }
+
+ private void updateProgress(){
+ mProgress++;
+ if (mProgressDialog != null) {
+ mProgressDialog.setProgress(mProgress);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/interactions/ExportDialogFragment.java b/src/com/android/contacts/interactions/ExportDialogFragment.java
index c7ce072..ac391f9 100644
--- a/src/com/android/contacts/interactions/ExportDialogFragment.java
+++ b/src/com/android/contacts/interactions/ExportDialogFragment.java
@@ -41,6 +41,7 @@
import com.android.contacts.R;
import com.android.contacts.util.ImplicitIntentsUtil;
import com.android.contacts.vcard.ExportVCardActivity;
+import com.android.contacts.model.SimCard;
import com.android.contacts.vcard.ShareVCardActivity;
import com.android.contacts.vcard.VCardCommonArguments;
@@ -61,7 +62,6 @@
};
private SubscriptionManager mSubscriptionManager;
-
/** Preferred way to show this dialog */
public static void show(FragmentManager fragmentManager, Class callingActivity,
int exportMode) {
@@ -91,7 +91,6 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final String callingActivity = getArguments().getString(
VCardCommonArguments.ARG_CALLING_ACTIVITY);
-
// Adapter that shows a list of string resources
final ArrayAdapter<AdapterEntry> adapter = new ArrayAdapter<AdapterEntry>(getActivity(),
R.layout.select_dialog_item) {
@@ -217,18 +216,18 @@
private static class AdapterEntry {
public final CharSequence mLabel;
public final int mChoiceResourceId;
- public final int mSubscriptionId;
+ public final SimCard mSim;
- public AdapterEntry(CharSequence label, int resId, int subId) {
+ public AdapterEntry(CharSequence label, int resId, SimCard sim) {
mLabel = label;
mChoiceResourceId = resId;
- mSubscriptionId = subId;
+ mSim = sim;
}
public AdapterEntry(String label, int resId) {
// Store a nonsense value for mSubscriptionId. If this constructor is used,
// the mSubscriptionId value should not be read later.
- this(label, resId, /* subId = */ -1);
+ this(label, resId, /* subId = */ null);
}
}
}
diff --git a/src/com/android/contacts/interactions/ImportDialogFragment.java b/src/com/android/contacts/interactions/ImportDialogFragment.java
index 41b1c71..6e05f08 100644
--- a/src/com/android/contacts/interactions/ImportDialogFragment.java
+++ b/src/com/android/contacts/interactions/ImportDialogFragment.java
@@ -35,6 +35,7 @@
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.contacts.R;
import com.android.contacts.activities.SimImportActivity;
@@ -48,6 +49,7 @@
import com.android.contacts.model.account.AccountInfo;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.util.AccountSelectionUtil;
+import com.android.contacts.util.ImplicitIntentsUtil;
import com.google.common.util.concurrent.Futures;
import java.util.List;
@@ -237,16 +239,20 @@
adapter.add(new AdapterEntry(getString(R.string.import_from_vcf_file),
R.string.import_from_vcf_file));
}
- final List<SimCard> sims = mSimDao.getSimCards();
+ if (!ImplicitIntentsUtil.checkIntentIfExists(getActivity(),
+ ImplicitIntentsUtil.getIntentForSimContactsManagement())) {
+ final List<SimCard> sims = mSimDao.getSimCards();
- if (sims.size() == 1) {
- adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
- R.string.import_from_sim, sims.get(0)));
- return;
- }
- for (int i = 0; i < sims.size(); i++) {
- final SimCard sim = sims.get(i);
- adapter.add(new AdapterEntry(getSimDescription(sim, i), R.string.import_from_sim, sim));
+ if (sims.size() == 1) {
+ adapter.add(new AdapterEntry(getString(R.string.import_from_sim),
+ R.string.import_from_sim, sims.get(0)));
+ return;
+ }
+ for (int i = 0; i < sims.size(); i++) {
+ final SimCard sim = sims.get(i);
+ adapter.add(new AdapterEntry(getSimDescription(sim, i),
+ R.string.import_from_sim, sim));
+ }
}
}
@@ -259,6 +265,11 @@
* Handle "import from SD".
*/
private void handleImportRequest(int resId, int subscriptionId) {
+ //if the accounts is not initial complete, give a toast here.
+ if (mAccountsFuture == null) {
+ Toast.makeText(getActivity(), R.string.vcard_import_failed, Toast.LENGTH_SHORT).show();
+ return;
+ }
// Get the accounts. Because this only happens after a user action this should pretty
// much never block since it will usually be at least several seconds before the user
// interacts with the view
diff --git a/src/com/android/contacts/lettertiles/LetterTileDrawable.java b/src/com/android/contacts/lettertiles/LetterTileDrawable.java
old mode 100644
new mode 100755
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index b508dda..5d46fa4 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -710,7 +710,6 @@
if (!cursor.isNull(photoIdColumn)) {
photoId = cursor.getLong(photoIdColumn);
}
-
QuickContactBadge quickContact = view.getQuickContact();
quickContact.assignContactUri(
getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index cb63f53..95ce6fe 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -50,7 +50,7 @@
Contacts.PHOTO_THUMBNAIL_URI, // 5
Contacts.LOOKUP_KEY, // 6
Contacts.PHONETIC_NAME, // 7
- Contacts.STARRED, // 9
+ Contacts.STARRED, // 8
};
private static final String[] CONTACT_PROJECTION_ALTERNATIVE = new String[] {
@@ -252,7 +252,6 @@
if (!cursor.isNull(ContactQuery.CONTACT_PHOTO_ID)) {
photoId = cursor.getLong(ContactQuery.CONTACT_PHOTO_ID);
}
-
if (photoId != 0) {
getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
getCircularPhotos(), null);
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 9851d2b..b4f748c 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -62,6 +62,7 @@
import com.android.contacts.activities.ActionBarAdapter;
import com.android.contacts.activities.PeopleActivity;
import com.android.contacts.compat.CompatUtils;
+import com.android.contacts.interactions.ContactMultiShareInteraction;
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
@@ -1015,8 +1016,10 @@
&& getSelectedContactIds().size() != 0;
makeMenuItemVisible(menu, R.id.menu_share, showSelectedContactOptions);
makeMenuItemVisible(menu, R.id.menu_delete, showSelectedContactOptions);
+ makeMenuItemVisible(menu, R.id.menu_select_all, !isSearchOrSelectionMode);
final boolean showLinkContactsOptions = mActionBarAdapter.isSelectionMode()
- && getSelectedContactIds().size() > 1;
+ && getSelectedContactIds().size() > 1
+ && getSelectedContactIds().size() <= 9;
makeMenuItemVisible(menu, R.id.menu_join, showLinkContactsOptions);
// Debug options need to be visible even in search mode.
@@ -1085,6 +1088,10 @@
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
ImplicitIntentsUtil.startActivityOutsideApp(getContext(), intent);
return true;
+ } else if (id == R.id.menu_select_all){
+ mActionBarAdapter.setSelectionMode(true);
+ mActivity.invalidateOptionsMenu();
+ setSelectedAll();
}
return super.onOptionsItemSelected(item);
}
@@ -1094,41 +1101,9 @@
* handling large numbers of contacts. I don't expect this to be a problem.
*/
private void shareSelectedContacts() {
- final StringBuilder uriListBuilder = new StringBuilder();
- for (Long contactId : getSelectedContactIds()) {
- final Uri contactUri = ContentUris.withAppendedId(
- ContactsContract.Contacts.CONTENT_URI, contactId);
- final Uri lookupUri = ContactsContract.Contacts.getLookupUri(
- getContext().getContentResolver(), contactUri);
- if (lookupUri == null) {
- continue;
- }
- final List<String> pathSegments = lookupUri.getPathSegments();
- if (pathSegments.size() < 2) {
- continue;
- }
- final String lookupKey = pathSegments.get(pathSegments.size() - 2);
- if (uriListBuilder.length() > 0) {
- uriListBuilder.append(':');
- }
- uriListBuilder.append(Uri.encode(lookupKey));
- }
- if (uriListBuilder.length() == 0) {
- return;
- }
- final Uri uri = Uri.withAppendedPath(
- ContactsContract.Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(uriListBuilder.toString()));
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(ContactsContract.Contacts.CONTENT_VCARD_TYPE);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- try {
- startActivityForResult(Intent.createChooser(intent, getResources().getQuantityString(
- R.plurals.title_share_via,/* quantity */ getSelectedContactIds().size()))
- , ACTIVITY_REQUEST_CODE_SHARE);
- } catch (final ActivityNotFoundException ex) {
- Toast.makeText(getContext(), R.string.share_error, Toast.LENGTH_SHORT).show();
- }
+ final ContactMultiShareInteraction multiShareInteraction =
+ ContactMultiShareInteraction.start(this, getSelectedContactIds());
+ mActionBarAdapter.setSelectionMode(false);
}
private void joinSelectedContacts() {
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
old mode 100644
new mode 100755
diff --git a/src/com/android/contacts/list/JoinContactListAdapter.java b/src/com/android/contacts/list/JoinContactListAdapter.java
old mode 100644
new mode 100755
diff --git a/src/com/android/contacts/list/MultiSelectContactsListFragment.java b/src/com/android/contacts/list/MultiSelectContactsListFragment.java
index 5e7f9e8..1d6b900 100644
--- a/src/com/android/contacts/list/MultiSelectContactsListFragment.java
+++ b/src/com/android/contacts/list/MultiSelectContactsListFragment.java
@@ -189,6 +189,23 @@
}
}
+ /**
+ * @param selected all contacts
+ */
+ public void setSelectedAll() {
+ TreeSet<Long> allContactIds = new TreeSet<Long>();
+ for (int i = 0; i < getAdapter().getCount(); i++) {
+ final long contactId = getContactId(i);
+ if (contactId < 0) {
+ return;
+ }
+ allContactIds.add(contactId);
+ }
+ if (getAdapter().isDisplayingCheckBoxes()) {
+ getAdapter().setSelectedContactIds(allContactIds);
+ }
+ }
+
private long getContactId(int position) {
final int contactIdColumnIndex = getAdapter().getContactColumnIdIndex();
diff --git a/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java b/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java
index a0b4f3c..32cfff1 100644
--- a/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java
+++ b/src/com/android/contacts/list/MultiSelectEntryContactListAdapter.java
@@ -165,7 +165,7 @@
* @param displayNameColumn Index of the display name column
*/
protected void bindPhoto(final ContactListItemView view, final Cursor cursor,
- final int photoIdColumn, final int lookUpKeyColumn, final int displayNameColumn) {
+ final int photoIdColumn, final int lookUpKeyColumn, final int displayNameColumn) {
final long photoId = cursor.isNull(photoIdColumn)
? 0 : cursor.getLong(photoIdColumn);
final ContactPhotoManager.DefaultImageRequest imageRequest = photoId == 0
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index d459d47..4d17aeb 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -540,7 +540,6 @@
if (!cursor.isNull(PhoneQuery.PHOTO_ID)) {
photoId = cursor.getLong(PhoneQuery.PHOTO_ID);
}
-
if (photoId != 0) {
getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
getCircularPhotos(), null);
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 196e67f..7bab0be 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -100,7 +100,7 @@
public boolean apply(@Nullable AccountInfo input) {
return input != null && input.getType().isGroupMembershipEditable();
}
- };
+ },
}
/**
diff --git a/src/com/android/contacts/model/RawContactDelta.java b/src/com/android/contacts/model/RawContactDelta.java
old mode 100644
new mode 100755
diff --git a/src/com/android/contacts/model/RawContactModifier.java b/src/com/android/contacts/model/RawContactModifier.java
old mode 100644
new mode 100755
index 789bd10..171a810
--- a/src/com/android/contacts/model/RawContactModifier.java
+++ b/src/com/android/contacts/model/RawContactModifier.java
@@ -1038,10 +1038,30 @@
return;
}
+ boolean supportPrefix = false;
+ boolean supportFamilyName = false;
+ boolean supportMiddleName = false;
+ boolean supportGivenName = false;
+ boolean supportSuffix = false;
boolean supportPhoneticFamilyName = false;
boolean supportPhoneticMiddleName = false;
boolean supportPhoneticGivenName = false;
for (EditField editField : newDataKind.fieldList) {
+ if (StructuredName.PREFIX.equals(editField.column)) {
+ supportPrefix = true;
+ }
+ if (StructuredName.FAMILY_NAME.equals(editField.column)) {
+ supportFamilyName = true;
+ }
+ if (StructuredName.MIDDLE_NAME.equals(editField.column)) {
+ supportMiddleName = true;
+ }
+ if (StructuredName.GIVEN_NAME.equals(editField.column)) {
+ supportGivenName = true;
+ }
+ if (StructuredName.SUFFIX.equals(editField.column)) {
+ supportSuffix = true;
+ }
if (StructuredName.PHONETIC_FAMILY_NAME.equals(editField.column)) {
supportPhoneticFamilyName = true;
}
@@ -1053,6 +1073,21 @@
}
}
+ if (!supportPrefix) {
+ values.remove(StructuredName.PREFIX);
+ }
+ if (!supportFamilyName) {
+ values.remove(StructuredName.FAMILY_NAME);
+ }
+ if (!supportMiddleName) {
+ values.remove(StructuredName.MIDDLE_NAME);
+ }
+ if (!supportGivenName) {
+ values.remove(StructuredName.GIVEN_NAME);
+ }
+ if (!supportSuffix) {
+ values.remove(StructuredName.SUFFIX);
+ }
if (!supportPhoneticFamilyName) {
values.remove(StructuredName.PHONETIC_FAMILY_NAME);
}
diff --git a/src/com/android/contacts/model/SimContact.java b/src/com/android/contacts/model/SimContact.java
index 7babe27..d6cc13e 100644
--- a/src/com/android/contacts/model/SimContact.java
+++ b/src/com/android/contacts/model/SimContact.java
@@ -47,20 +47,26 @@
private final String mName;
private final String mPhone;
private final String[] mEmails;
+ private final String[] mAnrs;
public SimContact(long id, String name, String phone) {
this(id, name, phone, null);
}
public SimContact(long id, String name, String phone, String[] emails) {
+ this(id, name, phone, emails, null);
+ }
+
+ public SimContact(long id, String name, String phone, String[] emails, String[] anrs) {
mId = id;
mName = name;
mPhone = phone == null ? "" : phone.trim();
mEmails = emails;
+ mAnrs = anrs;
}
public SimContact(SimContact other) {
- this(other.mId, other.mName, other.mPhone, other.mEmails);
+ this(other.mId, other.mName, other.mPhone, other.mEmails, other.mAnrs);
}
public long getId() {
@@ -79,10 +85,14 @@
return mEmails;
}
+ public String[] getAnrs() {
+ return mAnrs;
+ }
+
public void appendCreateContactOperations(List<ContentProviderOperation> ops,
AccountWithDataSet targetAccount) {
// There is nothing to save so skip it.
- if (!hasName() && !hasPhone() && !hasEmails()) return;
+ if (!hasName() && !hasPhone() && !hasEmails() && !hasAnrs()) return;
final int rawContactOpIndex = ops.size();
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
@@ -105,6 +115,12 @@
Email.ADDRESS, email));
}
}
+ if (mAnrs != null) {
+ for (String anr : mAnrs) {
+ ops.add(createInsertOp(rawContactOpIndex, Phone.CONTENT_ITEM_TYPE,
+ Phone.NUMBER, anr));
+ }
+ }
}
private ContentProviderOperation createInsertOp(int rawContactOpIndex, String mimeType,
@@ -134,6 +150,10 @@
return mEmails != null && mEmails.length > 0;
}
+ public boolean hasAnrs() {
+ return mAnrs != null && mAnrs.length > 0;
+ }
+
/**
* Generate a "fake" lookup key. This is needed because
* {@link ContactPhotoManager} will only generate a letter avatar
@@ -167,7 +187,8 @@
final SimContact that = (SimContact) o;
return mId == that.mId && Objects.equals(mName, that.mName) &&
- Objects.equals(mPhone, that.mPhone) && Arrays.equals(mEmails, that.mEmails);
+ Objects.equals(mPhone, that.mPhone) && Arrays.equals(mEmails, that.mEmails)
+ && Arrays.equals(mAnrs, that.mAnrs);
}
@Override
@@ -176,6 +197,7 @@
result = 31 * result + (mName != null ? mName.hashCode() : 0);
result = 31 * result + (mPhone != null ? mPhone.hashCode() : 0);
result = 31 * result + Arrays.hashCode(mEmails);
+ result = 31 * result + Arrays.hashCode(mAnrs);
return result;
}
@@ -190,6 +212,7 @@
dest.writeString(mName);
dest.writeString(mPhone);
dest.writeStringArray(mEmails);
+ dest.writeStringArray(mAnrs);
}
public static final Creator<SimContact> CREATOR = new Creator<SimContact>() {
@@ -199,7 +222,8 @@
final String name = source.readString();
final String phone = source.readString();
final String[] emails = source.createStringArray();
- return new SimContact(id, name, phone, emails);
+ final String[] anrs = source.createStringArray();
+ return new SimContact(id, name, phone, emails, anrs);
}
@Override
diff --git a/src/com/android/contacts/model/account/SimAccountType.java b/src/com/android/contacts/model/account/SimAccountType.java
index 360e944..b0efef4 100644
--- a/src/com/android/contacts/model/account/SimAccountType.java
+++ b/src/com/android/contacts/model/account/SimAccountType.java
@@ -17,6 +17,8 @@
import android.accounts.AuthenticatorDescription;
import android.content.Context;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
@@ -32,19 +34,22 @@
*/
public class SimAccountType extends BaseAccountType {
+ public static final String ACCOUNT_TYPE = "com.android.sim";
+
public SimAccountType(Context context) {
- this.titleRes = R.string.account_sim;
- this.iconRes = R.drawable.quantum_ic_sim_card_vd_theme_24;
+ this(context, null);
+ }
+
+ public SimAccountType(Context context, String resPackageName) {
+ this.accountType = ACCOUNT_TYPE;
+ this.resourcePackageName = resPackageName;
+ this.syncAdapterPackageName = resPackageName;
try {
addDataKindStructuredName(context);
addDataKindName(context);
- final DataKind phoneKind = addDataKindPhone(context);
- phoneKind.typeOverallMax = 1;
- // SIM card contacts don't necessarily support separate types (based on data exposed
- // in Samsung and LG Contacts Apps.
- phoneKind.typeList = Collections.emptyList();
-
+ addDataKindPhone(context);
+ addDataKindEmail(context);
mIsInitialized = true;
} catch (DefinitionException e) {
// Just fail fast. Because we're explicitly adding the fields in this class this
@@ -66,6 +71,7 @@
@Override
public void initializeFieldsFromAuthenticator(AuthenticatorDescription authenticator) {
// Do nothing. We want to use our local icon and title
+ super.initializeFieldsFromAuthenticator(authenticator);
}
@Override
@@ -75,14 +81,9 @@
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
kind.typeOverallMax = 1;
-
-
kind.fieldList = Lists.newArrayList();
- kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
+ kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.nameLabelsGroup,
FLAGS_PERSON_NAME));
- kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
- FLAGS_PERSON_NAME));
-
return kind;
}
@@ -98,18 +99,33 @@
context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
kind.fieldList = Lists.newArrayList();
- if (!displayOrderPrimary) {
- kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
- FLAGS_PERSON_NAME));
- kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
- FLAGS_PERSON_NAME));
- } else {
- kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME, R.string.name_given,
- FLAGS_PERSON_NAME));
- kind.fieldList.add(new EditField(StructuredName.FAMILY_NAME, R.string.name_family,
- FLAGS_PERSON_NAME));
- }
+ kind.fieldList.add(new EditField(StructuredName.GIVEN_NAME,
+ R.string.nameLabelsGroup, FLAGS_PERSON_NAME));
+ return kind;
+ }
+ @Override
+ protected DataKind addDataKindPhone(Context context) throws DefinitionException {
+ final DataKind kind = super.addDataKindPhone(context);
+ kind.typeOverallMax = 2;
+ kind.typeColumn = Phone.TYPE;
+ kind.typeList = Lists.newArrayList();
+ kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
+ kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));// This is used to save ANR records
+ kind.fieldList = Lists.newArrayList();
+ kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
+
+ return kind;
+ }
+
+ @Override
+ protected DataKind addDataKindEmail(Context context) throws DefinitionException {
+ final DataKind kind = super.addDataKindEmail(context);
+
+ kind.typeOverallMax = 1;
+ kind.typeList = Collections.emptyList();
+ kind.fieldList = Lists.newArrayList();
+ kind.fieldList.add(new EditField(Email.ADDRESS, R.string.emailLabelsGroup, FLAGS_EMAIL));
return kind;
}
@@ -118,7 +134,7 @@
// Use the "SIM" type label for the name as well because on OEM phones the "name" is
// not always user-friendly
return new AccountInfo(
- new AccountDisplayInfo(account, getDisplayLabel(context), getDisplayLabel(context),
+ new AccountDisplayInfo(account, account.name, getDisplayLabel(context),
getDisplayIcon(context), true), this);
}
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 6d206b6..d6128b4 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -2319,7 +2319,6 @@
ContactDisplayUtils.configureStarredMenuItem(starredMenuItem,
mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
mContactData.getStarred());
-
// Configure edit MenuItem
final MenuItem editMenuItem = menu.findItem(R.id.menu_edit);
editMenuItem.setVisible(true);
diff --git a/src/com/android/contacts/util/ImageViewDrawableSetter.java b/src/com/android/contacts/util/ImageViewDrawableSetter.java
index b90cf1f..a197a32 100644
--- a/src/com/android/contacts/util/ImageViewDrawableSetter.java
+++ b/src/com/android/contacts/util/ImageViewDrawableSetter.java
@@ -30,7 +30,6 @@
import com.android.contacts.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.lettertiles.LetterTileDrawable;
import com.android.contacts.model.Contact;
-
import java.util.Arrays;
/**
diff --git a/src/com/android/contacts/util/ImplicitIntentsUtil.java b/src/com/android/contacts/util/ImplicitIntentsUtil.java
index 0d00519..a7b503c 100644
--- a/src/com/android/contacts/util/ImplicitIntentsUtil.java
+++ b/src/com/android/contacts/util/ImplicitIntentsUtil.java
@@ -23,6 +23,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.ComponentName;
import android.net.Uri;
import android.os.Build;
import android.provider.ContactsContract;
@@ -175,6 +176,18 @@
return intent;
}
+ /**
+ * Returns an Intent to manage SIM contacts.
+ */
+ public static Intent getIntentForSimContactsManagement() {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ ComponentName cn = new ComponentName("com.qualcomm.qti.simcontacts",
+ "com.qualcomm.qti.simcontacts.activities.SimCardsSelectionActivity");
+ intent.setComponent(cn);
+ return intent;
+ }
+
public static Intent getIntentForQuickContactLauncherShortcut(Context context, Uri contactUri) {
final Intent intent = composeQuickContactIntent(context, contactUri,
QuickContact.MODE_LARGE, ScreenType.UNKNOWN);
@@ -197,6 +210,12 @@
return intent;
}
+ public static boolean checkIntentIfExists(Context context, Intent intent){
+ List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent,
+ PackageManager.GET_ACTIVITIES);
+ return list != null && list.size() > 0;
+ }
+
/**
* Returns a copy of {@param intent} with a class name set, if a class inside this app
* has a corresponding intent filter.
diff --git a/src/com/android/contacts/vcard/ImportVCardActivity.java b/src/com/android/contacts/vcard/ImportVCardActivity.java
old mode 100644
new mode 100755
index 2c69cdf..0353716
--- a/src/com/android/contacts/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ImportVCardActivity.java
@@ -595,6 +595,8 @@
if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
mAccount = new AccountWithDataSet(accountName, accountType, dataSet);
+ } if (accountName == null && accountType == null && dataSet == null){
+ mAccount = AccountWithDataSet.getNullAccount();
} else {
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(this);
final List<AccountWithDataSet> accountList = accountTypes.blockForWritableAccounts();