android11实现代码进入分屏、代码退出分屏功能

引言

自android7开始,分屏功能官方就已经实现了。Android11的操作方式是点击rescent键,选择一个应用进入分屏,然后系统会自动在下半屏显示另一个应用。
然后客户是客制化的系统,没有任务栏和状态栏。所以需要开发通过代码进入分屏的方式,并且客户希望可以自由开启一个应用进入上分屏或下分屏,自由退出上分屏或下分屏。这些原生Android11都是没有的,只能新开发。

新开发功能

  • 从taskId进入分屏
  • 启动intent进入分屏
  • 从taskId退出分屏
  • 自由退出分屏
    功能演示

分屏原理说明

首先看一个未分屏状态下的activity栈状态,执行命令

adb shell dumpsys activity activities
  Task display areas in top down Z order:
    TaskDisplayArea DefaultTaskDisplayArea
      mLastOrientationSource=Task{
   
   5ebffec #12 visible=true type=standard mode=fullscreen translucent=false A=10099:com.android.dialer U=0 StackId=12 sz=1}
      mPreferredTopFocusableStack=Task{
   
   5ebffec #12 visible=true type=standard mode=fullscreen translucent=false A=10099:com.android.dialer U=0 StackId=12 sz=1}
      mLastFocusedStack=Task{
   
   5ebffec #12 visible=true type=standard mode=fullscreen translucent=false A=10099:com.android.dialer U=0 StackId=12 sz=1}
      Application tokens in top down Z order:
      * Task{
   
   5ebffec #12 visible=true type=standard mode=fullscreen translucent=false A=10099:com.android.dialer U=0 StackId=12 sz=1}
        mLastOrientationSource=ActivityRecord{
   
   e499cf9 u0 com.android.dialer/.main.impl.MainActivity t12}
        bounds=[0,0][720,1280]
        * ActivityRecord{
   
   e499cf9 u0 com.android.dialer/.main.impl.MainActivity t12}
      * Task{
   
   d0d36ff #1 visible=true type=home mode=fullscreen translucent=false I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 StackId=1 sz=1}
        mLastOrientationSource=Task{
   
   da384a7 #10 visible=true type=home mode=fullscreen translucent=false I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 StackId=1 sz=1}
        bounds=[0,0][720,1280]
        * Task{
   
   da384a7 #10 visible=true type=home mode=fullscreen translucent=false I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 StackId=1 sz=1}
          mLastOrientationSource=ActivityRecord{
   
   c16f68e u0 com.android.launcher3/.uioverrides.QuickstepLauncher t10}
          bounds=[0,0][720,1280]
          * ActivityRecord{
   
   c16f68e u0 com.android.launcher3/.uioverrides.QuickstepLauncher t10}
      * Task{
   
   c140c5 #3 visible=false type=undefined mode=split-screen-primary translucent=true ?? U=0 StackId=3 sz=0}
        bounds=[0,0][720,606]
      * Task{
   
   b689f28 #4 visible=false type=undefined mode=split-screen-secondary translucent=true ?? U=0 StackId=4 sz=0}
        bounds=[0,626][720,1280]

看最后两个task,他们分属于不同的stackId,且都有不同的mode和bounds,mode分别是split-screen-primary和split-screen-secondary。split-screen-primary表示上半屏,且bounds=[0,0][720,606]就是处在上半屏的位置;split-screen-secondary表示下半屏,bounds=[0,626][720,1280]就是处在下半屏的位置。
Android系统其实就是根据stack来实现分屏的,系统启动之初就创建好了几个主要的stack,每个stack规定了自己的bounds和mode,bounds即大小和显示位置,mode即显示模式。Android系统中的每一个Activity都位于一个Task中,每个task都位于一个ActivityStack中。
全屏模式下大部分activity都处于fullscreen模式下的activityStack,把要分屏显示的activity的task移入分屏ActivityStack即可分屏显示。

从taskId进入分屏

原生android11只支持设置一个taskId显示在上半屏进入分屏状态,我这里实现的可以根据参数设置一个taskId进入上分屏或下分屏。
有四个方法可以实现,分别是:

1 ActivityTaskManager.setTaskWindowingMode(int taskId, int windowingMode, boolean toTop)
2 ActivityTaskManager.setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, boolean animate, Rect initialBounds, boolean showRecents)
3
//注:原生android11只支持进入上分屏
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(true ? WINDOWING_MODE_SPLIT_SCREEN_PRIMARY : WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
options.setSplitScreenCreateMode(true ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
ActivityTaskManager.getService().startActivityFromRecents(getTaskId(), options.toBundle())
4
//注:此方法只适合在已经分屏状态下启动activity进入下半屏
Intent intent = new Intent("android.settings.SETTINGS");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
startActivity(intent);

启动intent进入分屏

原生android11只支持在已经分屏状态下启动activity显示在另半屏,我这里实现的可以根据参数设置启动intent进入上分屏或下分屏。

Intent intent = new Intent(this, SubActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT_ARBITRARY);
intent.putExtra("showOnSpliteScreenPrimary", inflate.cbShowInSplitePrimary.isChecked());
startActivity(intent);

从taskId退出分屏

//第二个参数是WindowConfiguration.WINDOWING_MODE_FULLSCREEN
ActivityTaskManager.setTaskWindowingMode(int taskId, int windowingMode, boolean toTop)

自由退出分屏

//此功能新增的,show_splitScreenPrimary指定全屏显示上半屏幕或下半屏。
ActivityTaskManager.getService().exitSpliteScreenMode(show_splitScreenPrimary);

功能实现

上面是罗列客户端的使用接口,下面贴出修改点。
关键修改类:

frameworks/base/core/java/android/content/Intent.java
frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
frameworks/base/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java

修改如下:

diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 24d59a0826c8..8fd92d171cf6 100644
--- a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值