Android P 分屏显示
分屏显示
- 前提概要:
- 问题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 分屏显示相关推荐
- Android分屏显示(多窗口支持) 开发总结
最近公司有分屏显示需求,遇到几点问题 ,在此记录,以做备忘. 我所谓的分屏显示,是在同一个界面内,分屏显示两个app的界面 或者是 注意点1: 系统好像没有获取应用显示的左右或者上下位置的方法,所以我 ...
- Android分屏显示
1,定义 Android N以上系统支持的模式,可上下,左右分屏显示,画中画,多窗口模式 2,方式 要是全局分屏,可在application里设置标签resizeableActivity为true & ...
- android分屏模式_Android分屏显示总结
1. 基础原理 1.1 ActivityRecord.TaskRecord.ActivityStack关系 一个ActivityRecord对应着一个Activity,而一个Activity可能对应着 ...
- vlc android局域网rtsp,VLC mosaic分屏显示多路RTSP媒体流问题。
局域网环境内有两台Android机,装了Spydroid来获取传送RTSP媒体流,配置如下: Video Encoder: H.264 Resolution: 640*480 Framerate: 8 ...
- 【Android车载系列】第14章 车载渲染-分屏显示的实现
本章节通过获取Android系统的Display,使用Display+Presentation或Display+Activity实现分屏展示.最后通过MediaProjection录屏采集主屏幕数据, ...
- android n进入分屏代码分析_平板电脑全面进入多任务时代,Android N原生支持分屏显示...
去年十月苹果WWDC上发布iOS9首次原生支持iPad平板电脑的分屏显示,希望通过大屏多任务iPad产品,向微软的Surface为代表的Windows10平板PC发起挑战,撬开商务和企业级市场.近日据 ...
- Android系统(23)---Android 应用分屏
一.应用分屏介绍 Android 7.0以来,安卓系统新增了分屏显示应用--即在同一个屏幕上同时显示两个应用窗口的特性.在支持分屏的应用可以在"分屏模式"中左右并排或上下并排显示. ...
- java如何控制分屏显示,intellij idea 分屏设置 与快捷键
1.找到分屏功能 File -> setting -> keymap,搜索(注意大小写): Split Vertically 水平分屏 Split Horizontally 垂直分屏 2. ...
- PreferenceActivity 分屏显示 分析
先上效果图: PreferenceActivity 设置代码如下,通过getListView 遍历视图结构,主要调整间距与背景色 package com.example.testsettings;im ...
最新文章
- Linux nohup命令用法详解
- delphi webbrowser 对象不支持_【Python 秘籍】排序不支持原生比较的对象
- 英伟达推出GAN“超级缝合体”,输入文字草图语义图都能生成逼真照片
- 求带便函数权值的最短路径
- linux make怎么运行,Linux Make 命令教程
- 【牛客 - 303K第十五届浙江大学宁波理工学院程序设计大赛(同步赛)】Technology Tree(树形dp,tricks)
- C语言(CED)gameboy接馅饼问题
- ##HttpServletRequest 和 ##HttpServletResponse 基础知识
- python selenium 弹出框定位_selenium弹框元素定位-冻结界面
- vsftp服务日志不能显示中文临时解决(crontab五秒更新)
- php制作日历的代码,php日历制作代码分享_PHP教程
- Visio连接线的箭头如何变为直线、双箭头;直线转换为箭头
- WinForm大型企业ERP系统
- 立创EDA——PCB的走线(五)
- sentinel 熔断降级
- 新媒体运营教程:教你如何写推广策划案?
- 14. Working with Dates and Times in R
- 谷歌SEO英文外链建设指南
- T(n) = 25T(n/5)+n^2的时间复杂度(转)
- 同期对比图_Excel展示两组同期数据,这种左右对比图真好看,只需六步搞定
热门文章
- 虚拟机上的Linux系统如何联网?
- python大学生信息管理系统_基于Python的高等学校社团信息管理系统
- sql server与java连接数据库_Java连接数据库(SQL Server)
- restTemplate实现 authorization basic权限认证(带账号密码)
- 基于STC51:四轴飞控开源项目原理图与源码(入门级DIY)
- JSON.stringify() 详解
- Win10 串口编程
- Pytorch创建自己的数据集(图像分割)
- 联想拯救者y7000怎么配置Java环境_联想拯救者Y7000性能配置如何 用起来怎么样...
- TDD--01--ATDD、UTDD