Android12L之后 系统对大屏设备显示进行了优化,比如settings从原来的单列变成双列显示。 依靠的是Activity 嵌入这一原理。
在settings中决定是否嵌入式显示在SettingsHomepageActivity的onCreate中
涉及的类有 ActivityEmbeddingUtils和FeatureFlagUtils
onCreate
src/com/android/settings/homepage/SettingsHomepageActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 关注这里
mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this);
if (mIsEmbeddingActivityEnabled) {
final UserManager um = getSystemService(UserManager.class);
final UserInfo userInfo = um.getUserInfo(getUserId());
if (userInfo.isManagedProfile()) {
final Intent intent = new Intent(getIntent())
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
.putExtra(EXTRA_USER_HANDLE, getUser())
.putExtra(EXTRA_INITIAL_REFERRER, getCurrentReferrer());
if (TextUtils.equals(intent.getAction(), ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY)
&& this instanceof DeepLinkHomepageActivity) {
intent.setClass(this, DeepLinkHomepageActivityInternal.class);
}
intent.removeFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityAsUser(intent, um.getProfileParent(userInfo.id).getUserHandle());
finish();
return;
}
}
setContentView(R.layout.settings_homepage_container);
mIsTwoPane = ActivityEmbeddingUtils.isAlreadyEmbedded(this);
// Launch the intent from deep link for large screen devices.
if (shouldLaunchDeepLinkIntentToRight()) {
launchDeepLinkIntentToRight();
}
// Settings app may be launched on an existing task. Reset SplitPairRule of SubSettings here
// to prevent SplitPairRule of an existing task applied on a new started Settings app.
if (mIsEmbeddingActivityEnabled
&& (getIntent().getFlags() & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
initSplitPairRules();
}
}
ActivityEmbeddingUtils.java #isEmbeddingActivityEnabled
可以看出 !isSettingsSplitEnabled(context)和FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_SUPPORT_LARGE_SCREEN)决定是否进入嵌入模式(双栏显示)
实际上是
settings_support_large_screen 和 persist.settings.large_screen_opt.enabled 这两个值决定是否可以进入嵌入模式。
public static boolean isEmbeddingActivityEnabled(Context context) {
// Activity Embedding feature is not enabled if Settings doesn't enable large screen
// optimization or the device is not supported.
if (!isSettingsSplitEnabled(context)) { // (1)
Log.d(TAG, "isSettingsSplitSupported = false");
return false;
}
// Activity Embedding feature is not enabled if a user chooses to disable the feature.
if (!FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_SUPPORT_LARGE_SCREEN)) { //(2)
Log.d(TAG, "isFlagEnabled = false");
return false;
}
// Don't enable Activity embedding for setup wizard.
if (!WizardManagerHelper.isUserSetupComplete(context)) {
Log.d(TAG, "isUserSetupComplete = false");
return false;
}
Log.d(TAG, "isEmbeddingActivityEnabled = true");
return true;
}
- isSettingsSplitEnabled
SHOULD_ENABLE_LARGE_SCREEN_OPTIMIZATION 即 persist.settings.large_screen_opt.enabled
public static boolean isSettingsSplitEnabled(Context context) {
return SHOULD_ENABLE_LARGE_SCREEN_OPTIMIZATION
&& SplitController.getInstance(context).getSplitSupportStatus()
== SplitController.SplitSupportStatus.SPLIT_AVAILABLE;
}
- FeatureFlagUtils.java # isEnabled()
frameworks/base/core/java/android/util/FeatureFlagUtils.java
public static final String SETTINGS_SUPPORT_LARGE_SCREEN = "settings_support_large_screen";
public static boolean isEnabled(Context context, String feature) {
// Step 1: check if feature flag is set in Settings.Global.
String value;
if (context != null) {
value = Settings.Global.getString(context.getContentResolver(), feature);
if (!TextUtils.isEmpty(value)) {
return Boolean.parseBoolean(value);
}
}
// Step 2: check if feature flag has any override.
// Flag name: [persist.]sys.fflag.override.<feature>
value = SystemProperties.get(getSystemPropertyPrefix(feature) + feature);
if (!TextUtils.isEmpty(value)) {
return Boolean.parseBoolean(value);
}
// Step 3: check if feature flag has any default value.
value = getAllFeatureFlags().get(feature);
return Boolean.parseBoolean(value);
}
截止以上是我用五毛钱买的csdn别人的文章的大部分逻辑,只不过他写的甚至还没我细。
目前没有真机不好debug,暂时放到这
唯一一个指定Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY的intent位置。看起来原生系统没有太多直接跳转settings具体页面( 蓝牙 wifi之类的)并且左侧index需要对应的场景。
frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
void launchBluetoothPairing(View view) {
Intent launchIntent =
new Intent(ACTION_BLUETOOTH_PAIRING_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
final Intent deepLinkIntent =
new Intent(Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY);
if (deepLinkIntent.resolveActivity(mContext.getPackageManager()) != null) {
Log.d(TAG, "Device support split mode, launch page with deep link");
deepLinkIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
deepLinkIntent.putExtra(
Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI,
launchIntent.toUri(Intent.URI_INTENT_SCHEME));
deepLinkIntent.putExtra(
Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY,
PAGE_CONNECTED_DEVICES_KEY);
mActivityStarter.startActivity(deepLinkIntent, true, controller);
return;
}
mActivityStarter.startActivity(launchIntent, true, controller);
}