diff options
author | Walter Jang <wjang@google.com> | 2016-11-07 16:46:56 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-11-07 16:46:56 +0000 |
commit | f5a9e9aa15495fbf458d311038774e6c40253450 (patch) | |
tree | 352da7f8901b20d4c7c8cd1c9291ed9c9a9fba5a | |
parent | d7864dcef870115dcf2058b9611e9786bb65241f (diff) | |
parent | 7050d9a2430d386bde4301d0892df186fb7be15f (diff) | |
download | android_packages_apps_ContactsCommon-f5a9e9aa15495fbf458d311038774e6c40253450.tar.gz android_packages_apps_ContactsCommon-f5a9e9aa15495fbf458d311038774e6c40253450.tar.bz2 android_packages_apps_ContactsCommon-f5a9e9aa15495fbf458d311038774e6c40253450.zip |
resolve merge conflicts of e20a370 to mnc-dev am: 4718349e14
am: 7050d9a243
Change-Id: Iba89f60da7ac77bdd2ef684d0ead09b35872e14e
7 files changed, 164 insertions, 28 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml index fab8e973..95199fe0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -431,6 +431,9 @@ a ren't members of any other group. [CHAR LIMIT=25] --> <!-- Action string for selecting a .vcf file to import contacts from [CHAR LIMIT=30] --> <string name="import_from_vcf_file" product="default">Import from .vcf file</string> + <!-- Dialog message asking the user for confirmation before starting to import contacts from a .vcf file. [CHAR LIMIT=NONE] --> + <string name="import_from_vcf_file_confirmation_message" product="default">Import contacts from vCard?</string> + <!-- Message shown in a Dialog confirming a user's cancel request toward existing vCard import. The argument is file name for the vCard import the user wants to cancel. [CHAR LIMIT=128] --> diff --git a/src/com/android/contacts/common/activity/RequestImportVCardPermissionsActivity.java b/src/com/android/contacts/common/activity/RequestImportVCardPermissionsActivity.java index f3baf0ba..1c313f96 100644 --- a/src/com/android/contacts/common/activity/RequestImportVCardPermissionsActivity.java +++ b/src/com/android/contacts/common/activity/RequestImportVCardPermissionsActivity.java @@ -46,9 +46,11 @@ public class RequestImportVCardPermissionsActivity extends RequestPermissionsAct * to prompt the user for these permissions. Moreover, finish the current activity. * * This is designed to be called inside {@link android.app.Activity#onCreate} + * + * @param isCallerSelf whether the vcard import was started from the contacts app itself. */ - public static boolean startPermissionActivity(Activity activity) { - return startPermissionActivity(activity, REQUIRED_PERMISSIONS, + public static boolean startPermissionActivity(Activity activity, boolean isCallerSelf) { + return startPermissionActivity(activity, REQUIRED_PERMISSIONS, isCallerSelf, RequestImportVCardPermissionsActivity.class); } }
\ No newline at end of file diff --git a/src/com/android/contacts/common/activity/RequestPermissionsActivityBase.java b/src/com/android/contacts/common/activity/RequestPermissionsActivityBase.java index 5f78ec79..a692ab96 100644 --- a/src/com/android/contacts/common/activity/RequestPermissionsActivityBase.java +++ b/src/com/android/contacts/common/activity/RequestPermissionsActivityBase.java @@ -39,6 +39,9 @@ import java.util.Arrays; */ public abstract class RequestPermissionsActivityBase extends Activity { public static final String PREVIOUS_ACTIVITY_INTENT = "previous_intent"; + + protected static final String EXTRA_IS_CALLER_SELF = "is_caller_self"; + private static final int PERMISSIONS_REQUEST_ALL_PERMISSIONS = 1; /** @@ -55,10 +58,14 @@ public abstract class RequestPermissionsActivityBase extends Activity { private Intent mPreviousActivityIntent; + /** If true then start the target activity "for result" after permissions are granted. */ + protected boolean mIsCallerSelf; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mPreviousActivityIntent = (Intent) getIntent().getExtras().get(PREVIOUS_ACTIVITY_INTENT); + mIsCallerSelf = getIntent().getBooleanExtra(EXTRA_IS_CALLER_SELF, false); // Only start a requestPermissions() flow when first starting this activity the first time. // The process is likely to be restarted during the permission flow (necessary to enable @@ -76,9 +83,16 @@ public abstract class RequestPermissionsActivityBase extends Activity { */ protected static boolean startPermissionActivity(Activity activity, String[] requiredPermissions, Class<?> newActivityClass) { + return startPermissionActivity(activity, requiredPermissions, /* isCallerSelf */ false, + newActivityClass); + } + + protected static boolean startPermissionActivity(Activity activity, + String[] requiredPermissions, boolean isCallerSelf, Class<?> newActivityClass) { if (!RequestPermissionsActivity.hasPermissions(activity, requiredPermissions)) { final Intent intent = new Intent(activity, newActivityClass); intent.putExtra(PREVIOUS_ACTIVITY_INTENT, activity.getIntent()); + intent.putExtra(EXTRA_IS_CALLER_SELF, isCallerSelf); activity.startActivity(intent); activity.finish(); return true; @@ -99,7 +113,11 @@ public abstract class RequestPermissionsActivityBase extends Activity { if (permissions != null && permissions.length > 0 && isAllGranted(permissions, grantResults)) { mPreviousActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - startActivity(mPreviousActivityIntent); + if (mIsCallerSelf) { + startActivityForResult(mPreviousActivityIntent, 0); + } else { + startActivity(mPreviousActivityIntent); + } finish(); overridePendingTransition(0, 0); } else { diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java index ccbc2046..631242d4 100644 --- a/src/com/android/contacts/common/util/AccountSelectionUtil.java +++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java @@ -16,6 +16,7 @@ package com.android.contacts.common.util; +import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; @@ -52,53 +53,53 @@ public class AccountSelectionUtil { public static class AccountSelectedListener implements DialogInterface.OnClickListener { - final private Context mContext; + final private Activity mActivity; final private int mResId; final private int mSubscriptionId; final protected List<AccountWithDataSet> mAccountList; - public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList, + public AccountSelectedListener(Activity activity, List<AccountWithDataSet> accountList, int resId, int subscriptionId) { if (accountList == null || accountList.size() == 0) { Log.e(LOG_TAG, "The size of Account list is 0."); } - mContext = context; + mActivity = activity; mAccountList = accountList; mResId = resId; mSubscriptionId = subscriptionId; } - public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList, + public AccountSelectedListener(Activity activity, 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, /* subscriptionId = */ -1); + this(activity, accountList, resId, /* subscriptionId = */ -1); } public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); - doImport(mContext, mResId, mAccountList.get(which), mSubscriptionId); + doImport(mActivity, mResId, mAccountList.get(which), mSubscriptionId); } } - public static Dialog getSelectAccountDialog(Context context, int resId) { - return getSelectAccountDialog(context, resId, null, null); + public static Dialog getSelectAccountDialog(Activity activity, int resId) { + return getSelectAccountDialog(activity, resId, null, null); } - public static Dialog getSelectAccountDialog(Context context, int resId, + public static Dialog getSelectAccountDialog(Activity activity, int resId, DialogInterface.OnClickListener onClickListener) { - return getSelectAccountDialog(context, resId, onClickListener, null); + return getSelectAccountDialog(activity, resId, onClickListener, null); } /** * When OnClickListener or OnCancelListener is null, uses a default listener. * The default OnCancelListener just closes itself with {@link Dialog#dismiss()}. */ - public static Dialog getSelectAccountDialog(Context context, int resId, + public static Dialog getSelectAccountDialog(Activity activity, int resId, DialogInterface.OnClickListener onClickListener, DialogInterface.OnCancelListener onCancelListener) { - final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context); + final AccountTypeManager accountTypes = AccountTypeManager.getInstance(activity); final List<AccountWithDataSet> writableAccountList = accountTypes.getAccounts(true); Log.i(LOG_TAG, "The number of available accounts: " + writableAccountList.size()); @@ -107,11 +108,11 @@ public class AccountSelectionUtil { // Wrap our context to inflate list items using correct theme final Context dialogContext = new ContextThemeWrapper( - context, android.R.style.Theme_Light); + activity, android.R.style.Theme_Light); final LayoutInflater dialogInflater = (LayoutInflater)dialogContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); final ArrayAdapter<AccountWithDataSet> accountAdapter = - new ArrayAdapter<AccountWithDataSet>(context, android.R.layout.simple_list_item_2, + new ArrayAdapter<AccountWithDataSet>(activity, android.R.layout.simple_list_item_2, writableAccountList) { @Override @@ -142,7 +143,7 @@ public class AccountSelectionUtil { if (onClickListener == null) { AccountSelectedListener accountSelectedListener = - new AccountSelectedListener(context, writableAccountList, resId); + new AccountSelectedListener(activity, writableAccountList, resId); onClickListener = accountSelectedListener; } if (onCancelListener == null) { @@ -152,22 +153,22 @@ public class AccountSelectionUtil { } }; } - return new AlertDialog.Builder(context) + return new AlertDialog.Builder(activity) .setTitle(R.string.dialog_new_contact_account) .setSingleChoiceItems(accountAdapter, 0, onClickListener) .setOnCancelListener(onCancelListener) .create(); } - public static void doImport(Context context, int resId, AccountWithDataSet account, + public static void doImport(Activity activity, int resId, AccountWithDataSet account, int subscriptionId) { switch (resId) { case R.string.import_from_sim: { - doImportFromSim(context, account, subscriptionId); + doImportFromSim(activity, account, subscriptionId); break; } case R.string.import_from_vcf_file: { - doImportFromVcfFile(context, account); + doImportFromVcfFile(activity, account); break; } } @@ -187,8 +188,8 @@ public class AccountSelectionUtil { context.startActivity(importIntent); } - public static void doImportFromVcfFile(Context context, AccountWithDataSet account) { - Intent importIntent = new Intent(context, ImportVCardActivity.class); + public static void doImportFromVcfFile(Activity activity, AccountWithDataSet account) { + Intent importIntent = new Intent(activity, ImportVCardActivity.class); if (account != null) { importIntent.putExtra("account_name", account.name); importIntent.putExtra("account_type", account.type); @@ -201,6 +202,6 @@ public class AccountSelectionUtil { } mVCardShare = false; mPath = null; - context.startActivity(importIntent); + activity.startActivityForResult(importIntent, 0); } } diff --git a/src/com/android/contacts/common/vcard/ExportVCardActivity.java b/src/com/android/contacts/common/vcard/ExportVCardActivity.java index 06448ebc..bd29fc8f 100644 --- a/src/com/android/contacts/common/vcard/ExportVCardActivity.java +++ b/src/com/android/contacts/common/vcard/ExportVCardActivity.java @@ -72,7 +72,8 @@ public class ExportVCardActivity extends Activity implements ServiceConnection, protected void onCreate(Bundle bundle) { super.onCreate(bundle); - if (RequestImportVCardPermissionsActivity.startPermissionActivity(this)) { + if (RequestImportVCardPermissionsActivity.startPermissionActivity(this, + /* isCallerSelf */ false)) { return; } diff --git a/src/com/android/contacts/common/vcard/ImportVCardActivity.java b/src/com/android/contacts/common/vcard/ImportVCardActivity.java index 85b1417e..82969e9a 100644 --- a/src/com/android/contacts/common/vcard/ImportVCardActivity.java +++ b/src/com/android/contacts/common/vcard/ImportVCardActivity.java @@ -74,7 +74,7 @@ import java.util.List; * any Dialog in the instance. So this code is careless about the management around managed * dialogs stuffs (like how onCreateDialog() is used). */ -public class ImportVCardActivity extends Activity { +public class ImportVCardActivity extends Activity implements ImportVCardDialogFragment.Listener { private static final String LOG_TAG = "VCardImport"; private static final int SELECT_ACCOUNT = 0; @@ -497,7 +497,8 @@ public class ImportVCardActivity extends Activity { protected void onCreate(Bundle bundle) { super.onCreate(bundle); - if (RequestImportVCardPermissionsActivity.startPermissionActivity(this)) { + if (RequestImportVCardPermissionsActivity.startPermissionActivity(this, + isCallerSelf(this))) { return; } @@ -529,10 +530,44 @@ public class ImportVCardActivity extends Activity { } } + if (isCallerSelf(this)) { + startImport(); + } else { + ImportVCardDialogFragment.show(this); + } + } + + private static boolean isCallerSelf(Activity activity) { + // {@link Activity#getCallingActivity()} is a safer alternative to + // {@link Activity#getCallingPackage()} that works around a + // framework bug where getCallingPackage() can sometimes return null even when the + // current activity *was* in fact launched via a startActivityForResult() call. + // + // (The bug happens if the task stack needs to be re-created by the framework after + // having been killed due to memory pressure or by the "Don't keep activities" + // developer option; see bug 7494866 for the full details.) + // + // Turns out that {@link Activity#getCallingActivity()} *does* return correct info + // even in the case where getCallingPackage() is broken, so the workaround is simply + // to get the package name from getCallingActivity().getPackageName() instead. + final ComponentName callingActivity = activity.getCallingActivity(); + if (callingActivity == null) return false; + final String packageName = callingActivity.getPackageName(); + if (packageName == null) return false; + return packageName.equals(activity.getApplicationContext().getPackageName()); + } + + @Override + public void onImportVCardConfirmed() { startImport(); } @Override + public void onImportVCardDenied() { + finish(); + } + + @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == SELECT_ACCOUNT) { if (resultCode == Activity.RESULT_OK) { diff --git a/src/com/android/contacts/common/vcard/ImportVCardDialogFragment.java b/src/com/android/contacts/common/vcard/ImportVCardDialogFragment.java new file mode 100644 index 00000000..ae8ebbc9 --- /dev/null +++ b/src/com/android/contacts/common/vcard/ImportVCardDialogFragment.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 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.common.vcard; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.os.Bundle; + +import com.android.contacts.common.R; + +/** Asks for confirmation before importing contacts from a vcard. */ +public class ImportVCardDialogFragment extends DialogFragment { + + /** Callbacks for hosts of the {@link ImportVCardDialogFragment}. */ + public interface Listener { + + /** Invoked after the user has confirmed that contacts should be imported. */ + void onImportVCardConfirmed(); + + /** Invoked after the user has rejected importing contacts. */ + void onImportVCardDenied(); + } + + /** Displays the dialog asking for confirmation before importing contacts. */ + public static void show(Activity activity) { + if (!(activity instanceof Listener)) { + throw new IllegalArgumentException( + "Activity must implement " + Listener.class.getName()); + } + + final ImportVCardDialogFragment dialog = new ImportVCardDialogFragment(); + dialog.show(activity.getFragmentManager(), "importVCardDialogFragment"); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setIconAttribute(android.R.attr.alertDialogIcon) + .setMessage(R.string.import_from_vcf_file_confirmation_message) + .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + final Listener listener = (Listener) getActivity(); + if (listener != null) { + listener.onImportVCardConfirmed(); + } + } + }) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int whichButton) { + final Listener listener = (Listener) getActivity(); + if (listener != null) { + listener.onImportVCardDenied(); + } + } + }) + .create(); + } +} |