diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f3d5e97e..5482e9f1 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -5,7 +5,7 @@ androidx-activity-compose = "1.10.0"
androidx-appcompat = "1.7.0"
androidx-compose-bom = "2025.02.00"
androidx-compose-ui-test = "1.7.0-alpha08"
-androidx-constraintlayout = "2.2.0"
+androidx-constraintlayout = "2.2.1"
androidx-constraintlayout-compose = "1.1.0"
androidx-coordinator-layout = "1.2.0"
androidx-corektx = "1.16.0-beta01"
@@ -18,10 +18,14 @@ androidx-lifecycle-compose = "2.8.7"
androidx-lifecycle-runtime-compose = "2.8.7"
androidx-navigation = "2.8.7"
androidx-paging = "3.3.6"
+androidx-startup-runtime = "1.2.0"
androidx-test = "1.6.1"
androidx-test-espresso = "3.6.1"
-androidx-window = "1.4.0-beta02"
+androidx-window = "1.4.0-rc01"
+androidx-window-core = "1.4.0-beta02"
+androidx-window-java = "1.3.0"
androidxHiltNavigationCompose = "1.2.0"
+appcompat = "1.7.0"
coil = "2.7.0"
# @keep
compileSdk = "35"
@@ -90,7 +94,7 @@ androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
androidx-compose-ui-util = { module = "androidx.compose.ui:ui-util" }
androidx-compose-ui-viewbinding = { module = "androidx.compose.ui:ui-viewbinding" }
-androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
+androidx-constraintlayout = {module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-constraintlayout-compose = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "androidx-constraintlayout-compose" }
androidx-coordinator-layout = { module = "androidx.coordinatorlayout:coordinatorlayout", version.ref = "androidx-coordinator-layout" }
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "androidx-corektx" }
@@ -116,6 +120,7 @@ androidx-protolayout = { module = "androidx.wear.protolayout:protolayout", versi
androidx-protolayout-expression = { module = "androidx.wear.protolayout:protolayout-expression", version.ref = "protolayout" }
androidx-protolayout-material = { module = "androidx.wear.protolayout:protolayout-material", version.ref = "protolayout" }
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" }
+androidx-startup-runtime = {module = "androidx.startup:startup-runtime", version.ref = "androidx-startup-runtime" }
androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test" }
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-test-espresso" }
androidx-test-runner = "androidx.test:runner:1.6.2"
@@ -126,8 +131,11 @@ androidx-tiles-tooling = { module = "androidx.wear.tiles:tiles-tooling", version
androidx-tiles-tooling-preview = { module = "androidx.wear.tiles:tiles-tooling-preview", version.ref = "tiles" }
androidx-wear = { module = "androidx.wear:wear", version.ref = "wear" }
androidx-wear-tooling-preview = { module = "androidx.wear:wear-tooling-preview", version.ref = "wearToolingPreview" }
-androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window" }
+androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" }
+androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window-core" }
+androidx-window-java = {module = "androidx.window:window-java", version.ref = "androidx-window-java" }
androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.10.0"
+appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
compose-foundation = { module = "androidx.wear.compose:compose-foundation", version.ref = "wearComposeFoundation" }
compose-material = { module = "androidx.wear.compose:compose-material", version.ref = "wearComposeMaterial" }
diff --git a/misc/build.gradle.kts b/misc/build.gradle.kts
index de867bb8..b2619b9e 100644
--- a/misc/build.gradle.kts
+++ b/misc/build.gradle.kts
@@ -63,7 +63,12 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
ksp(libs.hilt.compiler)
+ implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.lifecycle.runtime)
+ implementation(libs.androidx.window)
+ implementation(libs.androidx.startup.runtime)
+ implementation(libs.androidx.window.java)
+ implementation(libs.appcompat)
testImplementation(libs.junit)
androidTestImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.core)
diff --git a/misc/src/main/AndroidManifest.xml b/misc/src/main/AndroidManifest.xml
index 0a7a5c6f..2ad7db1e 100644
--- a/misc/src/main/AndroidManifest.xml
+++ b/misc/src/main/AndroidManifest.xml
@@ -45,6 +45,17 @@
+
+
+
+
-
\ No newline at end of file
+
diff --git a/misc/src/main/java/com/example/snippets/ActivityEmbeddingJavaSnippets.java b/misc/src/main/java/com/example/snippets/ActivityEmbeddingJavaSnippets.java
new file mode 100644
index 00000000..61dd91ce
--- /dev/null
+++ b/misc/src/main/java/com/example/snippets/ActivityEmbeddingJavaSnippets.java
@@ -0,0 +1,376 @@
+package com.example.snippets;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Build.VERSION_CODES;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+import androidx.startup.Initializer;
+import androidx.window.WindowSdkExtensions;
+import androidx.window.core.ExperimentalWindowApi;
+import androidx.window.embedding.ActivityEmbeddingController;
+import androidx.window.embedding.ActivityFilter;
+import androidx.window.embedding.ActivityRule;
+import androidx.window.embedding.DividerAttributes;
+import androidx.window.embedding.EmbeddingAspectRatio;
+import androidx.window.embedding.RuleController;
+import androidx.window.embedding.SplitAttributes;
+import androidx.window.embedding.SplitAttributes.SplitType;
+import androidx.window.embedding.SplitController;
+import androidx.window.embedding.SplitPairFilter;
+import androidx.window.embedding.SplitPairRule;
+import androidx.window.embedding.SplitPinRule;
+import androidx.window.embedding.SplitPlaceholderRule;
+import androidx.window.embedding.SplitRule;
+import androidx.window.java.embedding.SplitControllerCallbackAdapter;
+import androidx.window.layout.FoldingFeature;
+import androidx.window.layout.WindowMetrics;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class ActivityEmbeddingJavaSnippets {
+
+ static class SnippetsActivity extends Activity {
+
+ private Context context;
+
+ @RequiresApi(api=VERSION_CODES.N)
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // [START android_activity_embedding_split_attributes_calculator_java]
+ if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) {
+ SplitController.getInstance(this).setSplitAttributesCalculator(params -> {
+ Configuration parentConfiguration = params.getParentConfiguration();
+ SplitAttributes.Builder builder = new SplitAttributes.Builder();
+ if (parentConfiguration.screenWidthDp >= 840) {
+ // Side-by-side dual-pane layout for wide displays.
+ return builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+ .build();
+ } else if (parentConfiguration.screenHeightDp >= 600) {
+ // Horizontal split for tall displays.
+ return builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP)
+ .build();
+ } else {
+ // Fallback to expand the secondary container.
+ return builder
+ .setSplitType(SplitType.SPLIT_TYPE_EXPAND)
+ .build();
+ }
+ });
+ }
+ // [END android_activity_embedding_split_attributes_calculator_java]
+
+ // [START android_activity_embedding_split_attributes_calculator_tabletop_java]
+ if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 2) {
+ SplitController.getInstance(this).setSplitAttributesCalculator(params -> {
+ String tag = params.getSplitRuleTag();
+ WindowMetrics parentWindowMetrics = params.getParentWindowMetrics();
+ Configuration parentConfiguration = params.getParentConfiguration();
+ List foldingFeatures =
+ params.getParentWindowLayoutInfo().getDisplayFeatures().stream().filter(
+ item -> item instanceof FoldingFeature)
+ .map(item -> (FoldingFeature) item)
+ .collect(Collectors.toList());
+ FoldingFeature feature = foldingFeatures.size() == 1 ? foldingFeatures.get(0) : null;
+ SplitAttributes.Builder builder = new SplitAttributes.Builder();
+ builder.setSplitType(SplitType.SPLIT_TYPE_HINGE);
+ if (feature != null && feature.isSeparating()) {
+ // Horizontal slit for tabletop posture.
+ return builder
+ .setSplitType(SplitType.SPLIT_TYPE_HINGE)
+ .setLayoutDirection(
+ feature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL
+ ? SplitAttributes.LayoutDirection.BOTTOM_TO_TOP
+ : SplitAttributes.LayoutDirection.LOCALE)
+ .build();
+ }
+ else if (parentConfiguration.screenWidthDp >= 840) {
+ // Side-by-side dual-pane layout for wide displays.
+ return builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+ .build();
+ } else {
+ // No split for tall displays.
+ return builder
+ .setSplitType(SplitType.SPLIT_TYPE_EXPAND)
+ .build();
+ }
+ });
+ }
+ // [END android_activity_embedding_split_attributes_calculator_tabletop_java]
+
+ // [START android_activity_embedding_splitPairFilter_java]
+ SplitPairFilter splitPairFilter = new SplitPairFilter(
+ new ComponentName(this, ListActivity.class),
+ new ComponentName(this, DetailActivity.class),
+ null
+ );
+ // [END android_activity_embedding_splitPairFilter_java]
+
+ // [START android_activity_embedding_filterSet_java]
+ Set filterSet = new HashSet<>();
+ filterSet.add(splitPairFilter);
+ // [END android_activity_embedding_filterSet_java]
+
+ // [START android_activity_embedding_splitAttributes_java]
+ SplitAttributes splitAttributes = new SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+ .build();
+ // [END android_activity_embedding_splitAttributes_java]
+
+ // [START android_activity_embedding_splitPairRule_java]
+ SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet)
+ .setDefaultSplitAttributes(splitAttributes)
+ .setMinWidthDp(840)
+ .setMinSmallestWidthDp(600)
+ .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
+ .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
+ .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
+ .setClearTop(false)
+ .build();
+ // [END android_activity_embedding_splitPairRule_java]
+
+ // [START android_activity_embedding_ruleController_java]
+ RuleController ruleController = RuleController.getInstance(this);
+ ruleController.addRule(splitPairRule);
+ // [END android_activity_embedding_ruleController_java]
+
+ // [START android_activity_embedding_placeholderActivityFilter_java]
+ ActivityFilter placeholderActivityFilter = new ActivityFilter(
+ new ComponentName(this, ListActivity.class),
+ null
+ );
+ // [END android_activity_embedding_placeholderActivityFilter_java]
+
+ // [START android_activity_embedding_placeholderActivityFilterSet_java]
+ Set placeholderActivityFilterSet = new HashSet<>();
+ placeholderActivityFilterSet.add(placeholderActivityFilter);
+ // [END android_activity_embedding_placeholderActivityFilterSet_java]
+
+ // [START android_activity_embedding_splitPlaceholderRule_java]
+ SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder(
+ placeholderActivityFilterSet,
+ new Intent(this, PlaceholderActivity.class)
+ ).setDefaultSplitAttributes(splitAttributes)
+ .setMinWidthDp(840)
+ .setMinSmallestWidthDp(600)
+ .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
+ .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
+ .setSticky(false)
+ .build();
+ // [END android_activity_embedding_splitPlaceholderRule_java]
+
+ // [START android_activity_embedding_addRuleSplitPlaceholderRule_java]
+ ruleController.addRule(splitPlaceholderRule);
+ // [END android_activity_embedding_addRuleSplitPlaceholderRule_java]
+
+ // [START android_activity_embedding_expandedActivityFilter_java]
+ ActivityFilter expandedActivityFilter = new ActivityFilter(
+ new ComponentName(this, ExpandedActivity.class),
+ null
+ );
+ // [END android_activity_embedding_expandedActivityFilter_java]
+
+ // [START android_activity_embedding_expandedActivityFilterSet_java]
+ Set expandedActivityFilterSet = new HashSet<>();
+ expandedActivityFilterSet.add(expandedActivityFilter);
+ // [END android_activity_embedding_expandedActivityFilterSet_java]
+
+ // [START android_activity_embedding_activityRule_java]
+ ActivityRule activityRule = new ActivityRule.Builder(
+ expandedActivityFilterSet
+ ).setAlwaysExpand(true)
+ .build();
+ // [END android_activity_embedding_activityRule_java]
+
+ // [START android_activity_embedding_addRuleActivityRule_java]
+ ruleController.addRule(activityRule);
+ // [END android_activity_embedding_addRuleActivityRule_java]
+
+ // [START android_activity_embedding_splitAttributesBuilder_java]
+ SplitAttributes.Builder _splitAttributesBuilder = new SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT);
+
+ if (WindowSdkExtensions.getInstance().getExtensionVersion() >= 6) {
+ _splitAttributesBuilder.setDividerAttributes(
+ new DividerAttributes.DraggableDividerAttributes.Builder()
+ .setColor(ContextCompat.getColor(this, R.color.divider_color))
+ .setWidthDp(4)
+ .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
+ .build()
+ );
+ }
+ SplitAttributes _splitAttributes = _splitAttributesBuilder.build();
+ // [END android_activity_embedding_splitAttributesBuilder_java]
+
+ }
+
+
+ // [START android_activity_embedding_isActivityEmbedded_java]
+ boolean isActivityEmbedded(Activity activity) {
+ return ActivityEmbeddingController.getInstance(context).isActivityEmbedded(activity);
+ }
+ // [END android_activity_embedding_isActivityEmbedded_java]
+
+ }
+
+
+ /** @noinspection InnerClassMayBeStatic */
+ // [START android_activity_embedding_DetailActivity_class_java]
+ public class DetailActivity extends AppCompatActivity {
+ void onOpenSubdetail() {
+ startActivity(new Intent(this, SubdetailActivity.class));
+ }
+ }
+ // [END android_activity_embedding_DetailActivity_class_java]
+
+
+ /** @noinspection InnerClassMayBeStatic */
+ // [START android_activity_embedding_SplitInitializer_class_java]
+ public class SplitInitializer implements Initializer {
+
+ @NonNull
+ @Override
+ public RuleController create(@NonNull Context context) {
+ RuleController ruleController = RuleController.getInstance(context);
+ ruleController.setRules(
+ RuleController.parseRules(context, R.xml.main_split_config)
+ );
+ return ruleController;
+ }
+
+ @NonNull
+ @Override
+ public List>> dependencies() {
+ return Collections.emptyList();
+ }
+ }
+ // [END android_activity_embedding_SplitInitializer_class_java]
+
+
+ /**
+ * Function used by snippet.
+ */
+ private Class> classForItem(int item) { return Class.class; }
+
+ /** @noinspection InnerClassMayBeStatic */
+ // [START android_activity_embedding_MenuActivity_class_java]
+ public class MenuActivity extends AppCompatActivity{
+ void onMenuItemSelected(int selectedMenuItem) {
+ startActivity(new Intent(this, classForItem(selectedMenuItem)));
+ }
+ }
+ // [END android_activity_embedding_MenuActivity_class_java]
+
+
+ /** @noinspection InnerClassMayBeStatic */
+ // [START android_activity_embedding_B_class_java]
+ public class B extends AppCompatActivity{
+ void onOpenC() {
+ startActivity(new Intent(this, C.class));
+ }
+ }
+ // [END android_activity_embedding_B_class_java]
+
+
+ static class SnippetActivity2 extends Activity {
+
+ private Set filterSet = new HashSet<>();
+
+ // [START android_activity_embedding_onCreate_RuleController_java]
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ RuleController.getInstance(this)
+ .addRule(new SplitPairRule.Builder(filterSet).build());
+ startActivity(new Intent(this, DetailActivity.class));
+ }
+ // [END android_activity_embedding_onCreate_RuleController_java]
+
+ }
+
+
+ static class SnippetActivity3 extends AppCompatActivity {
+
+ @OptIn(markerClass = ExperimentalWindowApi.class)
+ // [START android_activity_embedding_onCreate_SplitControllerCallbackAdapter_java]
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ new SplitControllerCallbackAdapter(SplitController.getInstance(this))
+ .addSplitListener(
+ this,
+ Runnable::run,
+ splitInfoList -> {
+ View layout = getLayoutInflater().inflate(R.layout.activity_main, null);
+ layout.findViewById(R.id.infoButton).setVisibility(
+ splitInfoList.isEmpty() ? View.VISIBLE : View.GONE);
+ });
+ }
+ // [END android_activity_embedding_onCreate_SplitControllerCallbackAdapter_java]
+
+ }
+
+ static class SnippetActivity4 extends Activity {
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ // [START android_activity_embedding_pinButton_java]
+ Button pinButton = findViewById(R.id.pinButton);
+ pinButton.setOnClickListener( (view) -> {
+ SplitAttributes splitAttributes = new SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+ .build();
+
+ SplitPinRule pinSplitRule = new SplitPinRule.Builder()
+ .setSticky(true)
+ .setDefaultSplitAttributes(splitAttributes)
+ .build();
+
+ SplitController.getInstance(
+ getApplicationContext()).pinTopActivityStack(getTaskId(),
+ pinSplitRule);
+ });
+ // [END android_activity_embedding_pinButton_java]
+
+ // [START android_activity_embedding_getSplitSupportStatus_java]
+ if (SplitController.getInstance(this).getSplitSupportStatus() ==
+ SplitController.SplitSupportStatus.SPLIT_AVAILABLE) {
+ // Device supports split activity features.
+ }
+ // [END android_activity_embedding_getSplitSupportStatus_java]
+
+ }
+ }
+
+
+ // Classes used by snippets.
+ static class ListActivity {}
+ static class SubdetailActivity {}
+ static class PlaceholderActivity {}
+ static class ExpandedActivity {}
+ static class C {}
+
+}
diff --git a/misc/src/main/java/com/example/snippets/ActivityEmbeddingKotlinSnippets.kt b/misc/src/main/java/com/example/snippets/ActivityEmbeddingKotlinSnippets.kt
new file mode 100644
index 00000000..a2c90e0f
--- /dev/null
+++ b/misc/src/main/java/com/example/snippets/ActivityEmbeddingKotlinSnippets.kt
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2025 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
+ *
+ * https://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.example.snippets
+
+import android.app.Activity
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.os.Build.VERSION_CODES
+import android.os.Bundle
+import android.view.View
+import android.widget.Button
+import androidx.annotation.RequiresApi
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import androidx.startup.Initializer
+import androidx.window.WindowSdkExtensions
+import androidx.window.core.ExperimentalWindowApi
+import androidx.window.embedding.ActivityEmbeddingController
+import androidx.window.embedding.ActivityFilter
+import androidx.window.embedding.ActivityRule
+import androidx.window.embedding.DividerAttributes
+import androidx.window.embedding.EmbeddingAspectRatio
+import androidx.window.embedding.RuleController
+import androidx.window.embedding.SplitAttributes
+import androidx.window.embedding.SplitAttributes.SplitType.Companion.SPLIT_TYPE_EXPAND
+import androidx.window.embedding.SplitAttributes.SplitType.Companion.SPLIT_TYPE_HINGE
+import androidx.window.embedding.SplitController
+import androidx.window.embedding.SplitPairFilter
+import androidx.window.embedding.SplitPairRule
+import androidx.window.embedding.SplitPinRule
+import androidx.window.embedding.SplitPlaceholderRule
+import androidx.window.embedding.SplitRule
+import androidx.window.layout.FoldingFeature
+import kotlinx.coroutines.launch
+
+class ActivityEmbeddingKotlinSnippets {
+
+ class SnippetActivity : Activity() {
+
+ private val context = this
+
+ @RequiresApi(api = VERSION_CODES.N)
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // [START android_activity_embedding_split_attributes_calculator_kotlin]
+ if (WindowSdkExtensions.getInstance().extensionVersion >= 2) {
+ SplitController.getInstance(this).setSplitAttributesCalculator { params ->
+ val parentConfiguration = params.parentConfiguration
+ val builder = SplitAttributes.Builder()
+ return@setSplitAttributesCalculator if (parentConfiguration.screenWidthDp >= 840) {
+ // Side-by-side dual-pane layout for wide displays.
+ builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+ .build()
+ } else if (parentConfiguration.screenHeightDp >= 600) {
+ // Horizontal split for tall displays.
+ builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.BOTTOM_TO_TOP)
+ .build()
+ } else {
+ // Fallback to expand the secondary container.
+ builder
+ .setSplitType(SPLIT_TYPE_EXPAND)
+ .build()
+ }
+ }
+ }
+ // [END android_activity_embedding_split_attributes_calculator_kotlin]
+
+ // [START android_activity_embedding_split_attributes_calculator_tabletop_kotlin]
+ if (WindowSdkExtensions.getInstance().extensionVersion >= 2) {
+ SplitController.getInstance(this).setSplitAttributesCalculator { params ->
+ val tag = params.splitRuleTag
+ val parentWindowMetrics = params.parentWindowMetrics
+ val parentConfiguration = params.parentConfiguration
+ val foldingFeatures =
+ params.parentWindowLayoutInfo.displayFeatures.filterIsInstance()
+ val feature = if (foldingFeatures.size == 1) foldingFeatures[0] else null
+ val builder = SplitAttributes.Builder()
+ builder.setSplitType(SPLIT_TYPE_HINGE)
+ return@setSplitAttributesCalculator if (feature?.isSeparating == true) {
+ // Horizontal split for tabletop posture.
+ builder
+ .setSplitType(SPLIT_TYPE_HINGE)
+ .setLayoutDirection(
+ if (feature.orientation == FoldingFeature.Orientation.HORIZONTAL) {
+ SplitAttributes.LayoutDirection.BOTTOM_TO_TOP
+ } else {
+ SplitAttributes.LayoutDirection.LOCALE
+ }
+ )
+ .build()
+ } else if (parentConfiguration.screenWidthDp >= 840) {
+ // Side-by-side dual-pane layout for wide displays.
+ builder
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LOCALE)
+ .build()
+ } else {
+ // No split for tall displays.
+ builder
+ .setSplitType(SPLIT_TYPE_EXPAND)
+ .build()
+ }
+ }
+ }
+ // [END android_activity_embedding_split_attributes_calculator_tabletop_kotlin]
+
+ // [START android_activity_embedding_splitPairFilter_kotlin]
+ val splitPairFilter = SplitPairFilter(
+ ComponentName(this, ListActivity::class.java),
+ ComponentName(this, DetailActivity::class.java),
+ null
+ )
+ // [END android_activity_embedding_splitPairFilter_kotlin]
+
+ // [START android_activity_embedding_filterSet_kotlin]
+ val filterSet = setOf(splitPairFilter)
+ // [END android_activity_embedding_filterSet_kotlin]
+
+ // [START android_activity_embedding_splitAttributes_kotlin]
+ val splitAttributes: SplitAttributes = SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+ .build()
+ // [END android_activity_embedding_splitAttributes_kotlin]
+
+ // [START android_activity_embedding_splitPairRule_kotlin]
+ val splitPairRule = SplitPairRule.Builder(filterSet)
+ .setDefaultSplitAttributes(splitAttributes)
+ .setMinWidthDp(840)
+ .setMinSmallestWidthDp(600)
+ .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
+ .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER)
+ .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS)
+ .setClearTop(false)
+ .build()
+ // [END android_activity_embedding_splitPairRule_kotlin]
+
+ // [START android_activity_embedding_ruleController_kotlin]
+ val ruleController = RuleController.getInstance(this)
+ ruleController.addRule(splitPairRule)
+ // [END android_activity_embedding_ruleController_kotlin]
+
+ // [START android_activity_embedding_placeholderActivityFilter_kotlin]
+ val placeholderActivityFilter = ActivityFilter(
+ ComponentName(this, ListActivity::class.java),
+ null
+ )
+ // [END android_activity_embedding_placeholderActivityFilter_kotlin]
+
+ // [START android_activity_embedding_placeholderActivityFilterSet_kotlin]
+ val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
+ // [END android_activity_embedding_placeholderActivityFilterSet_kotlin]
+
+ // [START android_activity_embedding_splitPlaceholderRule_kotlin]
+ val splitPlaceholderRule = SplitPlaceholderRule.Builder(
+ placeholderActivityFilterSet,
+ Intent(context, PlaceholderActivity::class.java)
+ ).setDefaultSplitAttributes(splitAttributes)
+ .setMinWidthDp(840)
+ .setMinSmallestWidthDp(600)
+ .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f))
+ .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS)
+ .setSticky(false)
+ .build()
+ // [END android_activity_embedding_splitPlaceholderRule_kotlin]
+
+ // [START android_activity_embedding_addRuleSplitPlaceholderRule_kotlin]
+ ruleController.addRule(splitPlaceholderRule)
+ // [END android_activity_embedding_addRuleSplitPlaceholderRule_kotlin]
+
+ // [START android_activity_embedding_expandedActivityFilter_kotlin]
+ val expandedActivityFilter = ActivityFilter(
+ ComponentName(this, ExpandedActivity::class.java),
+ null
+ )
+ // [END android_activity_embedding_expandedActivityFilter_kotlin]
+
+ // [START android_activity_embedding_expandedActivityFilterSet_kotlin]
+ val expandedActivityFilterSet = setOf(expandedActivityFilter)
+ // [END android_activity_embedding_expandedActivityFilterSet_kotlin]
+
+ // [START android_activity_embedding_activityRule_kotlin]
+ val activityRule = ActivityRule.Builder(expandedActivityFilterSet)
+ .setAlwaysExpand(true)
+ .build()
+ // [END android_activity_embedding_activityRule_kotlin]
+
+ // [START android_activity_embedding_addRuleActivityRule_kotlin]
+ ruleController.addRule(activityRule)
+ // [END android_activity_embedding_addRuleActivityRule_kotlin]
+
+ // [START android_activity_embedding_splitAttributesBuilder_kotlin]
+ val _splitAttributesBuilder: SplitAttributes.Builder = SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.33f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+
+ if (WindowSdkExtensions.getInstance().extensionVersion >= 6) {
+ _splitAttributesBuilder.setDividerAttributes(
+ DividerAttributes.DraggableDividerAttributes.Builder()
+ .setColor(getColor(R.color.divider_color))
+ .setWidthDp(4)
+ .setDragRange(DividerAttributes.DragRange.DRAG_RANGE_SYSTEM_DEFAULT)
+ .build()
+ )
+ }
+ val _splitAttributes: SplitAttributes = _splitAttributesBuilder.build()
+ // [END android_activity_embedding_splitAttributesBuilder_kotlin]
+
+ // [START android_activity_embedding_isActivityEmbedded_kotlin]
+ fun isActivityEmbedded(activity: Activity): Boolean {
+ return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity)
+ }
+ // [END android_activity_embedding_isActivityEmbedded_kotlin]
+ }
+ }
+
+ // [START android_activity_embedding_DetailActivity_class_kotlin]
+ class DetailActivity : AppCompatActivity() {
+ fun onOpenSubdetail() {
+ startActivity(Intent(this, SubdetailActivity::class.java))
+ }
+ }
+ // [END android_activity_embedding_DetailActivity_class_kotlin]
+
+ // [START android_activity_embedding_SplitInitializer_class_kotlin]
+ class SplitInitializer : Initializer {
+
+ override fun create(context: Context): RuleController {
+ return RuleController.getInstance(context).apply {
+ setRules(RuleController.parseRules(context, R.xml.main_split_config))
+ }
+ }
+
+ override fun dependencies(): List>> {
+ return emptyList()
+ }
+ }
+ // [END android_activity_embedding_SplitInitializer_class_kotlin]
+
+ /**
+ * Function used by snippet.
+ */
+ fun classForItem(item: Int): Class<*> { return Class::class.java }
+
+ // [START android_activity_embedding_MenuActivity_class_kotlin]
+ inner class MenuActivity : AppCompatActivity() {
+ fun onMenuItemSelected(selectedMenuItem: Int) {
+ startActivity(Intent(this, classForItem(selectedMenuItem)))
+ }
+ }
+ // [END android_activity_embedding_MenuActivity_class_kotlin]
+
+ // [START android_activity_embedding_B_class_kotlin]
+ class B : AppCompatActivity() {
+ fun onOpenC() {
+ startActivity(Intent(this, C::class.java))
+ }
+ }
+ // [END android_activity_embedding_B_class_kotlin]
+
+ class SnippetActivity2 : Activity() {
+
+ private val filterSet = HashSet()
+
+ // [START android_activity_embedding_onCreate_RuleController_kotlin]
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ RuleController.getInstance(this)
+ .addRule(SplitPairRule.Builder(filterSet).build())
+ startActivity(Intent(this, DetailActivity::class.java))
+ }
+ // [END android_activity_embedding_onCreate_RuleController_kotlin]
+ }
+
+ class SplitDeviceActivity : AppCompatActivity() {
+
+ @OptIn(ExperimentalWindowApi::class)
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val splitController = SplitController.getInstance(this)
+ // [START android_activity_embedding_onCreate_SplitControllerCallbackAdapter_kotlin]
+ val layout = layoutInflater.inflate(R.layout.activity_main, null)
+ val view = layout.findViewById(R.id.infoButton)
+ lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.STARTED) {
+ splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance.
+ .collect { list ->
+ view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
+ }
+ }
+ }
+ // [END android_activity_embedding_onCreate_SplitControllerCallbackAdapter_kotlin]
+ }
+ }
+
+ class SnippetActivity3 : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+ // [START android_activity_embedding_pinButton_kotlin]
+ val pinButton: Button = findViewById(R.id.pinButton)
+ pinButton.setOnClickListener {
+ val splitAttributes: SplitAttributes = SplitAttributes.Builder()
+ .setSplitType(SplitAttributes.SplitType.ratio(0.66f))
+ .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT)
+ .build()
+
+ val pinSplitRule = SplitPinRule.Builder()
+ .setSticky(true)
+ .setDefaultSplitAttributes(splitAttributes)
+ .build()
+
+ SplitController.getInstance(applicationContext).pinTopActivityStack(taskId, pinSplitRule)
+ }
+ // [END android_activity_embedding_pinButton_kotlin]
+
+ // [START android_activity_embedding_getSplitSupportStatus_kotlin]
+ if (SplitController.getInstance(this).splitSupportStatus ==
+ SplitController.SplitSupportStatus.SPLIT_AVAILABLE
+ ) {
+ // Device supports split activity features.
+ }
+ // [END android_activity_embedding_getSplitSupportStatus_kotlin]
+ }
+ }
+
+ // Classes used by snippets.
+ class ListActivity
+ class SubdetailActivity
+ class PlaceholderActivity
+ class ExpandedActivity
+ class C
+}
diff --git a/misc/src/main/res/layout/activity_main.xml b/misc/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..59cbc1b4
--- /dev/null
+++ b/misc/src/main/res/layout/activity_main.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
diff --git a/misc/src/main/res/values/colors.xml b/misc/src/main/res/values/colors.xml
index f8c6127d..61944aef 100644
--- a/misc/src/main/res/values/colors.xml
+++ b/misc/src/main/res/values/colors.xml
@@ -7,4 +7,6 @@
#FF018786
#FF000000
#FFFFFFFF
-
\ No newline at end of file
+
+ #FFFFAA00
+
diff --git a/misc/src/main/res/xml/main_split_config.xml b/misc/src/main/res/xml/main_split_config.xml
new file mode 100644
index 00000000..2113dc80
--- /dev/null
+++ b/misc/src/main/res/xml/main_split_config.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file