Android系统原生settings 单双栏显示变化

1,528 阅读2分钟

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;
}
  1. 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;
}
  1. 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);

    }

developer.android.com/guide/topic…