分屏显示

  • 前提概要:
  • 问题1、启动左边显示仪表os、右边显示ivi.
  • 问题2、固定分屏 、不显示recent view画面
  • 问题3、显示home的时候强制修改home的大小
  • 问题4、不支持应用分屏的app,要全屏显示
  • 问题5、config配置是否支持分屏显示

前提概要:

我是做车机ivi开发的,目前有个需求是仿特斯拉的娱乐系统显示,用一个大屏左边来显示仪表os、右边来显示ivi。
我的ivi是基于Android os来发的,所以分屏方案也是基于Android的应用分屏来实现的。

但是原来Android的应用分屏不能完全满足我们的要求:
1、我们要一启动左边显示仪表os、右边显示ivi。
2、左右分屏大小要固定,不能拖拽,不支持用户进入recent view画面,选择recent app。
3、原生的Android不支持home stack分屏显示,我们需要在显示home的时候强制修改home的大小。
4、不支持应用分屏的app,要全屏显示,退出全屏app之后又要回到左边显示仪表os、右边显示ivi home。
5、config配置是否支持分屏显示

基本就是要解决上面几个问题。

问题1、启动左边显示仪表os、右边显示ivi.

首先 Android 提供了分屏的api, 调用ActivityManagerService中setTaskWindowingModeSplitScreenPrimary() 、resizeStack() 来实现分屏。

 // mLeftScreenTask 就是正在运行的要分屏的apk,SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT是分屏模式为分屏apk在上面或者右边,mSplitLeftRect是要分屏的应用占全屏大小mAm.setTaskWindowingModeSplitScreenPrimary(mLeftScreenTask.id,SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,true, true, mSplitLeftRect, false);// 调整分屏apk的占平大小。mAm.resizeStack(mLeftScreenTask.stackId, mSplitLeftRect,false, false, false, -1);

其实我们左边显示的是任意的一个apk,只是起到占位的作用,后面会通过视频流的形式将仪表的os投影过来。

问题2、固定分屏 、不显示recent view画面

这块就注释掉Android原生的一些功能。
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java

   // 显示 recent app的地方public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,boolean animate, int growTarget) {/** case : aiways No need to display the recent app to give users a choice, So comment out the codefinal SystemServicesProxy ssp = Recents.getSystemServices();final MutableBoolean isHomeStackVisible = new MutableBoolean(true);final boolean isRecentsVisible = Recents.getSystemServices().isRecentsActivityVisible(isHomeStackVisible);final boolean fromHome = isHomeStackVisible.value;final boolean launchedWhileDockingTask =Recents.getSystemServices().getSplitScreenPrimaryStack() != null;mTriggeredFromAltTab = triggeredFromAltTab;mDraggingInRecents = draggingInRecents;mLaunchedWhileDocking = launchedWhileDockingTask;if (mFastAltTabTrigger.isAsleep()) {// Fast alt-tab duration has elapsed, fall through to showing Recents and resetmFastAltTabTrigger.stopDozing();} else if (mFastAltTabTrigger.isDozing()) {// Fast alt-tab duration has not elapsed.  If this is triggered by a different// showRecents() call, then ignore that call for now.// TODO: We can not handle quick tabs that happen between the initial showRecents() call//       that started the activity and the activity starting up.  The severity of this//       is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.if (!triggeredFromAltTab) {return;}mFastAltTabTrigger.stopDozing();} else if (triggeredFromAltTab) {// The fast alt-tab detector is not yet running, so start the trigger and wait for the// hideRecents() call, or for the fast alt-tab duration to elapsemFastAltTabTrigger.startDozing();return;}try {// Check if the top task is in the home stack, and start the recents activityfinal boolean forceVisible = launchedWhileDockingTask || draggingInRecents;if (forceVisible || !isRecentsVisible) {ActivityManager.RunningTaskInfo runningTask =ActivityManagerWrapper.getInstance().getRunningTask();startRecentsActivityAndDismissKeyguardIfNeeded(runningTask,isHomeStackVisible.value || fromHome, animate, growTarget);}} catch (ActivityNotFoundException e) {Log.e(TAG, "Failed to launch RecentsActivity", e);}*/}

frameworks/base/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java

    // 这个也是第一次进入分屏要显示empty view,我们不需要,就注释掉了public void showEmptyView(int msgResId) {/** case : aiways No need to display the empty view to give users , So comment out the codemTaskStackView.setVisibility(View.INVISIBLE);mEmptyView.setText(msgResId);mEmptyView.setVisibility(View.VISIBLE);mEmptyView.bringToFront();mStackActionButton.bringToFront(); */}

frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java

     // 这个里面是监听,在home界面的时候会缩进分屏app的大小,我们这里要求分屏大小一直不变,就注释掉了@Overridepublic void onDockedStackMinimizedChanged(boolean minimized, long animDuration,boolean isHomeStackResizable) throws RemoteException {/** case : When the android native function displays the home app, the split screen screen needs to be indented, aiways don't need this function.mHomeStackResizable = isHomeStackResizable;updateMinimizedDockedStack(minimized, animDuration, isHomeStackResizable); */}

frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java

@Override// 这个是提供给用户自由调整分屏大小的地方,我们不需要也注释掉了public boolean onTouch(View v, MotionEvent event) {convertToScreenCoordinates(event);final int action = event.getAction() & MotionEvent.ACTION_MASK;// switch (action) {//     case MotionEvent.ACTION_DOWN://         Log.d("DividerView", "ACTION_DOWN");//         mVelocityTracker = VelocityTracker.obtain();//         mVelocityTracker.addMovement(event);//         mStartX = (int) event.getX();//         mStartY = (int) event.getY();//         boolean result = startDragging(true /* animate */, true /* touching */);//         if (!result) {//             // Weren't able to start dragging successfully, so cancel it again.//             stopDragging();//         }//         mStartPosition = getCurrentPosition();//         mMoving = false;//         return result;//     case MotionEvent.ACTION_MOVE://         Log.d("DividerView", "ACTION_MOVE");//         mVelocityTracker.addMovement(event);//         int x = (int) event.getX();//         int y = (int) event.getY();//         boolean exceededTouchSlop =//                 isHorizontalDivision() && Math.abs(y - mStartY) > mTouchSlop//                         || (!isHorizontalDivision() && Math.abs(x - mStartX) > mTouchSlop);//         if (!mMoving && exceededTouchSlop) {//             mStartX = x;//             mStartY = y;//             mMoving = true;//         }//         if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {//             SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget(//                     mStartPosition, 0 /* velocity */, false /* hardDismiss */);//             resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget);//         }//         break;//     case MotionEvent.ACTION_UP://         Log.d("DividerView", "ACTION_UP");//     case MotionEvent.ACTION_CANCEL://         Log.d("DividerView", "ACTION_CANCEL");//         mVelocityTracker.addMovement(event);//         x = (int) event.getRawX();//         y = (int) event.getRawY();//         mVelocityTracker.computeCurrentVelocity(1000);//         int position = calculatePosition(x, y);//         stopDragging(position, isHorizontalDivision() ? mVelocityTracker.getYVelocity()//                 : mVelocityTracker.getXVelocity(), false /* avoidDismissStart */,//                 true /* log */);//         mMoving = false;//         break;// }return true;}

问题3、显示home的时候强制修改home的大小

这个问题是home stack是一个独立的apk stack,和其他的apk不一样,Android原生的是不支持home 分屏的,所以我们这边在phoneWindowManager里面强制修改了home的显示大小
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

    private void layoutScreenDecorWindows(DisplayFrames displayFrames, Rect pf, Rect df, Rect dcf) {.........// 判断如果是home apk就强制显示为HOME_WIDTHif(win.getAttrs().packageName.equals(HOME_PACKAGE_NAME)){Slog.v(TAG,"laucher,displayFrames.mDisplayCutout:"+displayFrames.mDisplayCutout);// dcf.right = HOME_WIDTH;// of.right = HOME_WIDTH;//   df.right = HOME_WIDTH;//   pf.right = HOME_WIDTH;//   cf.right = HOME_WIDTH;//   vf.right = HOME_WIDTH;dcf.left = HOME_WIDTH;of.left = HOME_WIDTH;df.left = HOME_WIDTH;pf.left = HOME_WIDTH;cf.left = HOME_WIDTH;vf.left = HOME_WIDTH;}win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf, displayFrames.mDisplayCutout,parentFrameWasClippedByDisplayCutout);.......}

问题4、不支持应用分屏的app,要全屏显示

每一个应用的androidmanifest.xml 中可通过android:resizeableActivity=“true” 或 "false"来配置,是否支持分屏。
而我们可以通过监听 onActivityDismissingDockedStack来关闭分屏模式。

private TaskStackListener mTaskStackListener =new TaskStackListener() {@Overridepublic void onTaskStackChanged() {ActivityManager.StackInfo topStack = getTopStackInfo();Log.d(TAG, "onTaskStackChanged topStack.stackId: " + topStack.stackId);Log.d(TAG, "onTaskStackChanged topStack name: " + topStack.topActivity.toString());if (topStack != null) {mCurrentTask = getTaskInfoByActivityName(topStack.topActivity);if (topStack.topActivity.getPackageName().equals(LEFT_SCREEN_PKG_NAME)) {mLeftScreenTask = mCurrentTask;}if (mCurrentTask.resizeMode != ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {showSplitScreen();}}//first to start left screen apk;if (mLeftScreenTask == null) {startLeftScreenActivty();}}@Overridepublic void onTaskCreated(int taskId, ComponentName componentName) {Log.d(TAG, "onTaskCreated taskId: " + taskId);Log.d(TAG, "onTaskCreated componentName: " + componentName.toString());mCurrentTask = getTaskInfoByTaskId(taskId);Log.d(TAG, "onTaskCreated getPackageName: " + mCurrentTask.topActivity.getPackageName());if (mCurrentTask.topActivity.getPackageName().equals(LEFT_SCREEN_PKG_NAME)) {mLeftScreenTask = mCurrentTask;showSplitScreen();}            }@Overridepublic void onTaskMovedToFront(int taskId) {Log.d(TAG, "onTaskMovedToFront taskId: " + taskId);}public void onActivityForcedResizable(String packageName, int taskId,int reason) {Log.d(TAG, "onActivityForcedResizable -> packageName:" + packageName);}@Overridepublic void onActivityDismissingDockedStack() {Log.d(TAG, "onActivityDismissingDockedStack");hideSplitScreen();   // 关闭分屏}@Overridepublic void onActivityLaunchOnSecondaryDisplayFailed() {}};

问题5、config配置是否支持分屏显示

frameworks/base/core/res/res/values/config.xml 里面有一个配置项<!-- True if the device supports at least one form of multi-window.E.g. freeform, split-screen, picture-in-picture. --><bool name="config_supportsMultiWindow">true</bool><!-- True if the device supports split screen as a form of multi-window. --><bool name="config_supportsSplitScreenMultiWindow">true</bool><!-- True if the device supports running activities on secondary displays. --><bool name="config_supportsMultiDisplay">true</bool>

原生的是支持分屏的,但是我们用别的设备时,在device下对 config_supportsSplitScreenMultiWindow做了overlay设置成了false。搞的我们去跟踪源码才找到这个配置项被改为了false,导致不能分屏

<bool name="config_supportsSplitScreenMultiWindow">false</bool>

Android P 分屏显示相关推荐

  1. Android分屏显示(多窗口支持) 开发总结

    最近公司有分屏显示需求,遇到几点问题 ,在此记录,以做备忘. 我所谓的分屏显示,是在同一个界面内,分屏显示两个app的界面 或者是 注意点1: 系统好像没有获取应用显示的左右或者上下位置的方法,所以我 ...

  2. Android分屏显示

    1,定义 Android N以上系统支持的模式,可上下,左右分屏显示,画中画,多窗口模式 2,方式 要是全局分屏,可在application里设置标签resizeableActivity为true & ...

  3. android分屏模式_Android分屏显示总结

    1. 基础原理 1.1 ActivityRecord.TaskRecord.ActivityStack关系 一个ActivityRecord对应着一个Activity,而一个Activity可能对应着 ...

  4. vlc android局域网rtsp,VLC mosaic分屏显示多路RTSP媒体流问题。

    局域网环境内有两台Android机,装了Spydroid来获取传送RTSP媒体流,配置如下: Video Encoder: H.264 Resolution: 640*480 Framerate: 8 ...

  5. 【Android车载系列】第14章 车载渲染-分屏显示的实现

    本章节通过获取Android系统的Display,使用Display+Presentation或Display+Activity实现分屏展示.最后通过MediaProjection录屏采集主屏幕数据, ...

  6. android n进入分屏代码分析_平板电脑全面进入多任务时代,Android N原生支持分屏显示...

    去年十月苹果WWDC上发布iOS9首次原生支持iPad平板电脑的分屏显示,希望通过大屏多任务iPad产品,向微软的Surface为代表的Windows10平板PC发起挑战,撬开商务和企业级市场.近日据 ...

  7. Android系统(23)---Android 应用分屏

    一.应用分屏介绍 Android 7.0以来,安卓系统新增了分屏显示应用--即在同一个屏幕上同时显示两个应用窗口的特性.在支持分屏的应用可以在"分屏模式"中左右并排或上下并排显示. ...

  8. java如何控制分屏显示,intellij idea 分屏设置 与快捷键

    1.找到分屏功能 File -> setting -> keymap,搜索(注意大小写): Split Vertically 水平分屏 Split Horizontally 垂直分屏 2. ...

  9. PreferenceActivity 分屏显示 分析

    先上效果图: PreferenceActivity 设置代码如下,通过getListView 遍历视图结构,主要调整间距与背景色 package com.example.testsettings;im ...

最新文章

  1. Linux nohup命令用法详解
  2. delphi webbrowser 对象不支持_【Python 秘籍】排序不支持原生比较的对象
  3. 英伟达推出GAN“超级缝合体”,输入文字草图语义图都能生成逼真照片
  4. 求带便函数权值的最短路径
  5. linux make怎么运行,Linux Make 命令教程
  6. 【牛客 - 303K第十五届浙江大学宁波理工学院程序设计大赛(同步赛)】Technology Tree(树形dp,tricks)
  7. C语言(CED)gameboy接馅饼问题
  8. ##HttpServletRequest 和 ##HttpServletResponse 基础知识
  9. python selenium 弹出框定位_selenium弹框元素定位-冻结界面
  10. vsftp服务日志不能显示中文临时解决(crontab五秒更新)
  11. php制作日历的代码,php日历制作代码分享_PHP教程
  12. Visio连接线的箭头如何变为直线、双箭头;直线转换为箭头
  13. WinForm大型企业ERP系统
  14. 立创EDA——PCB的走线(五)
  15. sentinel 熔断降级
  16. 新媒体运营教程:教你如何写推广策划案?
  17. 14. Working with Dates and Times in R
  18. 谷歌SEO英文外链建设指南
  19. T(n) = 25T(n/5)+n^2的时间复杂度(转)
  20. 同期对比图_Excel展示两组同期数据,这种左右对比图真好看,只需六步搞定

热门文章

  1. 虚拟机上的Linux系统如何联网?
  2. python大学生信息管理系统_基于Python的高等学校社团信息管理系统
  3. sql server与java连接数据库_Java连接数据库(SQL Server)
  4. restTemplate实现 authorization basic权限认证(带账号密码)
  5. 基于STC51:四轴飞控开源项目原理图与源码(入门级DIY)
  6. JSON.stringify() 详解
  7. Win10 串口编程
  8. Pytorch创建自己的数据集(图像分割)
  9. 联想拯救者y7000怎么配置Java环境_联想拯救者Y7000性能配置如何 用起来怎么样...
  10. TDD--01--ATDD、UTDD