现象:在日历应用中点击添加账户跳转失败,在设置中点击添加账户正常
日历中添加账户入口// vendor/mediatek/proprietary/packages/apps/Calendar/src/com/android/calendar/CalendarSettingsActivity.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_add_account) {
// 这里ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"
Intent nextIntent = new Intent(Settings.ACTION_ADD_ACCOUNT);
final String[] array = { "com.android.calendar" };
// 这里Settings.EXTRA_AUTHORITIES = authorities
nextIntent.putExtra(Settings.EXTRA_AUTHORITIES, array);
nextIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(nextIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
设置中添加账户入口
// packages/apps/Settings/src/com/android/settings/accounts/AccountPreferenceController.java
@Override
public boolean onPreferenceClick(Preference preference) {
final int metricsCategory = mFragment.getMetricsCategory();
// Check the preference
final int count = mProfiles.size();
for (int i = 0; i < count; i++) {
ProfileData profileData = mProfiles.valueAt(i);
if (preference == profileData.addAccountPreference) {
mMetricsFeatureProvider.logClickedPreference(preference, metricsCategory);
// 这里ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS"
Intent intent = new Intent(ACTION_ADD_ACCOUNT);
intent.putExtra(EXTRA_USER, profileData.userInfo.getUserHandle());
// 这里EXTRA_AUTHORITIES = authorities,打印此处的mAuthorities为空
intent.putExtra(EXTRA_AUTHORITIES, mAuthorities);
mContext.startActivity(intent);
return true;
}
// ...
}
return false;
}
这两处都是跳转到 AddAccountSettings.java中,然后又经过一些条件判断调用其中的requestChooseAccount()方法跳转到ChooseAccountActivity.java
// packages/apps/Settings/src/com/android/settings/accounts/AddAccountSettings.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ...
if (um.isUserUnlocked(mUserHandle)) {
requestChooseAccount();
} else {
// If the user is locked by fbe: we couldn't start the authenticator. So we must ask the
// user to unlock it first.
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
if (!helper.launchConfirmationActivity(UNLOCK_WORK_PROFILE_REQUEST,
getString(R.string.unlock_set_unlock_launch_picker_title),false,
mUserHandle.getIdentifier())) {
requestChooseAccount();
}
}
}
// 这里又跳转到ChooseAccountActivity,实际就是拉起ChooseAccountFragment
private void requestChooseAccount() {
final String[] authorities =
getIntent().getStringArrayExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
final String[] accountTypes =
getIntent().getStringArrayExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
final Intent intent = new Intent(this, Settings.ChooseAccountActivity.class);
if (authorities != null) {
intent.putExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY, authorities);
}
if (accountTypes != null) {
intent.putExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY, accountTypes);
}
intent.putExtra(EXTRA_USER, mUserHandle);
startActivityForResult(intent, CHOOSE_ACCOUNT_REQUEST);
}
在ChooseAccountFragment.java中调用ChooseAccountPreferenceController.java的initialize()方法
// packages/apps/Settings/src/com/android/settings/accounts/ChooseAccountFragment.java
@Override
public void onAttach(Context context) {
super.onAttach(context);
// AUTHORITIES_FILTER_KEY = "authorities"
final String[] authorities = getIntent().getStringArrayExtra(
AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
// ACCOUNT_TYPES_FILTER_KEY = "account_types"
final String[] accountTypesFilter = getIntent().getStringArrayExtra(
AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
final UserManager userManager = UserManager.get(getContext());
final UserHandle userHandle = Utils.getSecureTargetUser(getActivity().getActivityToken(),
userManager, null , getIntent().getExtras());
// 这里调用ChooseAccountPreferenceController中的initialize()方法
use(ChooseAccountPreferenceController.class).initialize(authorities, accountTypesFilter,
userHandle, getActivity());
}
最后在ChooseAccountPreferenceController.java判断是否显示可添加的账号类型列表。
// packages/apps/Settings/src/com/android/settings/accounts/ChooseAccountPreferenceController.java
public void initialize(String[] authorities, String[] accountTypesFilter, UserHandle userHandle,
Activity activity) {
mActivity = activity;
mAuthorities = authorities;
mUserHandle = userHandle;
// 如果是从Setting进入,mAuthorities=null;
// 如果是从Calendar进入,mAuthorities=com.android.calendar;
if (accountTypesFilter != null) {
mAccountTypesFilter = new HashSet<>();
for (String accountType : accountTypesFilter) {
mAccountTypesFilter.add(accountType);
}
}
}
// ...
private void updateAuthDescriptions() {
mAuthDescs = AccountManager.get(mContext).getAuthenticatorTypesAsUser(
mUserHandle.getIdentifier());
for (int i = 0; i < mAuthDescs.length; i++) { //这里可能有多个值
//mAuthDescs[i].type的分别为com.android.email和com.android.email.pop3
//mAuthDescs[i]的值分别为
//AuthenticatorDescription {type=com.android.email}
//AuthenticatorDescription {type=com.android.email.pop3}
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
}
onAuthDescriptionsUpdated();
}
private void onAuthDescriptionsUpdated() {
// Create list of providers to show on preference screen
for (int i = 0; i < mAuthDescs.length; i++) {
final String accountType = mAuthDescs[i].type;
final CharSequence providerName = getLabelForType(accountType);
// 此处的providerName值为个人(IMAP)和个人(POP3) 这里可能有多个值
// Skip preferences for authorities not specified. If no authorities specified,
// then include them all.
final List accountAuths = getAuthoritiesForAccountType(accountType);
// 此处的accountAuths的值为com.android.email.provider
boolean addAccountPref = true;
if (mAuthorities != null && mAuthorities.length > 0 && accountAuths != null) {
addAccountPref = false;
for (int k = 0; k < mAuthorities.length; k++) {
if (accountAuths.contains(mAuthorities[k])) {
addAccountPref = true;
break;
}
}
}
// 从Setting中进行添加账户传过来的mAuthorities值为null,跳上面的if;这个时候addAccountPref的值为true
// 从Calendar进行添加账户传过来的mAuthorities值为com.android.calendar,进入上面if中;但是accountAuths和mAuthorities的值不匹配,此时mAuthorities的值为false
if (addAccountPref && mAccountTypesFilter != null
&& !mAccountTypesFilter.contains(accountType)) {
addAccountPref = false;
}
// addAccountPref的值为false,mProviderList.size()==0
if (addAccountPref) {
mProviderList.add(new ProviderEntry(providerName, accountType));
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Skipped pref " + providerName + ": has no authority we need");
}
}
}
final Context context = mScreen.getContext();
if (mProviderList.size() == 1) {
// There's only one provider that matches. If it is disabled by admin show the
// support dialog otherwise run it.
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtilsInternal.checkIfAccountManagementDisabled(
context, mProviderList.get(0).getType(), mUserHandle.getIdentifier());
if (admin != null) {
mActivity.setResult(RESULT_CANCELED,
RestrictedLockUtils.getShowAdminSupportDetailsIntent(
context, admin));
mActivity.finish();
} else {
finishWithAccountType(mProviderList.get(0).getType());
}
} else if (mProviderList.size() > 0) { // mProviderList不为空,显示可添加的账户类型列表
Collections.sort(mProviderList);
for (ProviderEntry pref : mProviderList) {
final Drawable drawable = getDrawableForType(pref.getType());
final ProviderPreference p = new ProviderPreference(context,
pref.getType(), drawable, pref.getName());
p.setKey(pref.getType().toString());
p.checkAccountManagementAndSetDisabled(mUserHandle.getIdentifier());
mScreen.addPreference(p);
}
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
final StringBuilder auths = new StringBuilder();
for (String a : mAuthorities) {
auths.append(a);
auths.append(' ');
}
Log.v(TAG, "No providers found for authorities: " + auths);
}
// mProviderList.size()==0,直接退出
mActivity.setResult(RESULT_CANCELED);
mActivity.finish();
}
}
// ...
所以我们只需修改传过来的mAuthorities的数组中包含com.android.email.provider,或者直接不传值
// vendor/mediatek/proprietary/packages/apps/Calendar/src/com/android/calendar/CalendarSettingsActivity.java
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
} else if (item.getItemId() == R.id.action_add_account) {
Intent nextIntent = new Intent(Settings.ACTION_ADD_ACCOUNT);
// 加入"com.android.email.provider"
final String[] array = { "com.android.calendar", "com.android.email.provider"};
nextIntent.putExtra(Settings.EXTRA_AUTHORITIES, array); // 或者直接注释此行
nextIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(nextIntent);
return true;
}
return super.onOptionsItemSelected(item);
}



