概述

Android实现双屏异显的实现方式有2种。

方式一:在Android4.2及以上平台上,按照标准Android SDK提供的API,使用Presentation类,将一个APP的相关内容显示到指定的屏幕上,具体请参考https://developer.android.com/reference/android/app/Presentation.html。这种方式实现的是应用内的异显,也是View级别的异显。

方式二:通过修改Framework层的am,wm,display相关代码,从而在不同的显示设备上运行不同的应用,这种多任务的双屏异显方法实现了不同应用之间的异显,本文重点讲解这种双屏异显方法的实现方式。这种实现方式是基于某芯片厂商系列芯片,Android 6.0平台开发的。

这需要解决如下几个问题:

1.如何获取所有的TaskID?

在IActivityManager.java添加接口,public List getAllTaskIds() throws RemoteException。

ActivityManagerNative.java种实现了IActivityManger接口,具体实现如下:

@Override

public List getAllTaskIds() throws RemoteException{

List taskIds = new ArrayList();

List stackInfos = getAllStackInfos();

if(stackInfos != null && stackInfos.size() > 0){

for(StackInfo info : stackInfos){

int[] taskIdArray = info.taskIds;

reverseArray(taskIdArray);

if(taskIdArray != null && taskIdArray.length > 0){

for(int taskId : taskIdArray)

taskIds.add(taskId);

}

}

}

return taskIds;

}

2.如何确保两个应用同时运行,同时保持Resume状态?如何确保副屏Activity不会随着主屏应用同时销毁?在ActivityStack.java下activityPausedLocked方法添加如下代码:

if(r.task != null && r.task.taskId == mService.getSecondDisplayTaskId())

return;

上述代码禁止副屏应用进入Pased状态,副屏应用将一直保持Resume状态

3.主屏与副屏的应用如何切换,同显与异显如何切换?这是通过操作主屏与副屏的窗口实现的,WindowManagerService.java添加如下代码:

public void setOnlyShowInExtendDisplay(Session session,IWindow client,int transit){

long origId = Binder.clearCallingIdentity();

synchronized(mWindowMap){

if(mDisplayContents == null || mDisplayContents.size() <= 1){

return;

}

final int displayCount = mDisplayContents.size();

DisplayContent defaultContent = getDefaultDisplayContentLocked();

int displayId = 0;

DisplayContent secondDisplayContent = null;

for(int i = 0; i < displayCount;i++){

final DisplayContent content = mDisplayContents.valueAt(i);

if(content != defaultContent){

secondDisplayContent = content;

displayId = secondDisplayContent.getDisplayId();

break;

}

}

if(secondDisplayContent == null){

return;

}

if(!okToDisplay()){

return;

}

WindowState current = windowForClientLocked(session, client, false);

if(isHomeWindow(current)){

return;

}

AppWindowToken wtoken = current.mAppToken;

if(wtoken == null){

return;

}

int groupId = wtoken.mTask.mTaskId;

mH.sendMessage(mH.obtainMessage(H.DO_TASK_DISPLAY_CHANGED, groupId, -1));

}

Binder.restoreCallingIdentity(origId);

}

/**

move window to second display

*/

public void moveTransitionToSecondDisplay(int groupId,int transit){

//if(!isShowDualScreen()){

//    mSecondTaskIds.clear();

//}

//Settings.System.putInt(mContext.getContentResolver(), Settings.DUAL_SCREEN_ICON_USED, 0);

List allTaskIds = null;

try{

allTaskIds = mActivityManager.getAllTaskIds();

}catch (Exception e){

Log.i("DualScreen", "WindowManagerService->getAllTaskIds->e:" + e);

}

if(allTaskIds == null || allTaskIds.size() < 2)

return;

if(isShowDualScreen()){

moveWindowToSecondDisplayWithDualShow();

return;

}

long origId = Binder.clearCallingIdentity();

int curMoveTaskId = -1;

synchronized(mWindowMap){

if(mDisplayContents == null || mDisplayContents.size() <= 1){

return;

}

final int displayCount = mDisplayContents.size();

DisplayContent defaultContent = getDefaultDisplayContentLocked();

int displayId = 0;

DisplayContent secondDisplayContent = null;

for(int i = 0; i < displayCount;i++){

final DisplayContent content = mDisplayContents.valueAt(i);

if(content != defaultContent){

secondDisplayContent = content;

displayId = secondDisplayContent.getDisplayId();

break;

}

}

if(secondDisplayContent == null){

return;

}

if(!okToDisplay()){

return;

}

SurfaceControl.openTransaction();

WindowState win = null;

WindowList defaultWindows = defaultContent.getWindowList();

try{

WindowList secondDisplayAddList = new WindowList();

WindowList secondDisplayWindows = secondDisplayContent.getWindowList();

int topTaskId = -1;

if(allTaskIds != null && allTaskIds.size() > 0){

topTaskId = allTaskIds.get(0);

//mSecondTaskIds.add(topTaskId);

}

for(int i= defaultWindows.size()-1;i>=0;i--){

win = defaultWindows.get(i);

if(win == null){

continue;

}

if (win.mAppToken == null){

continue;

}

if(win.mAppToken.mTask == null){

continue;

}

int windowTaskId = win.mAppToken.mTask.mTaskId;

if(windowTaskId == topTaskId){

win.setPrimaryDisplay(true);

defaultWindows.remove(win);

mTempWindowList.add(win);

win.mDisplayContent = secondDisplayContent;

if(win.mWinAnimator != null){

int layerStack = secondDisplayContent.getDisplay().getLayerStack();

if(win.mWinAnimator.mSurfaceControl!= null){

win.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);

}

}

secondDisplayAddList.add(0,win);

}

}

secondDisplayWindows.clear();

secondDisplayWindows.addAll(secondDisplayAddList);

for (int i = 0; i < displayCount; i++) {

final DisplayContent content = mDisplayContents.valueAt(i);

assignLayersLocked(content.getWindowList());

content.layoutNeeded = true;

}

Log.i("DualScreen", "WindowManagerService->allTaskIds:" + allTaskIds);

ArrayList allStacks = getAllStacks();

Log.i("DualScreen", "moveTransitionToSecondDisplay->allStacks:" + allStacks);

boolean isFind = false;

for(int i = allStacks.size() - 1; i >= 0; --i){

ActivityStack itemStack = allStacks.get(i);

//ArrayList getAllTasks()

List itemTasks = itemStack.getAllTasks();

if(itemTasks != null && itemTasks.size() > 0){

for(int k = itemTasks.size() - 1; k >= 0; --k){

TaskRecord itemTask = itemTasks.get(k);

List itemActivities = itemTask.mActivities;

for(int j = itemActivities.size() - 1; j >= 0; --j){

ActivityRecord itemActivity = itemActivities.get(j);

if(/*itemActivity.state == ActivityState.RESUMED && */itemTask.taskId != topTaskId){

curMoveTaskId = itemTask.taskId;

isFind = true;

break;

}

}

if(isFind)

break;

}

}

if(isFind)

break;

}

mSecondDisplayTaskId = topTaskId;

Log.i("DualScreen", "WindowManagerService->curMoveTaskId:" + curMoveTaskId);

misMovingToSecond = true;

Settings.System.putInt(mContext.getContentResolver(), Settings.DUAL_SCREEN_ICON_USED, 1);

switchFocusWindow(curMoveTaskId);

updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false);

mAppTransition.setReady();

performLayoutAndPlaceSurfacesLocked();

}finally{

SurfaceControl.closeTransaction();

}

//shouldAppMoveBack(-1);

}

Binder.restoreCallingIdentity(origId);

}

public void moveWindowToSecondDisplayWithDualShow(){

long origId = Binder.clearCallingIdentity();

int secondDisplayTaskId = getSecondDisplayTaskId();

int currentFocusedTaskId = -1;

int curMoveTaskId = secondDisplayTaskId;

if(mFocusedApp != null && mFocusedApp.mTask != null)

currentFocusedTaskId = mFocusedApp.mTask.mTaskId;

Log.i("DualScreen", "WindowManagerService->moveWindowToSecondDisplayWithDualShow->currentFocusedTaskId:" + currentFocusedTaskId);

//mSecondDisplayTaskId = currentFocusedTaskId;

synchronized(mWindowMap){

if(mDisplayContents == null || mDisplayContents.size() <= 1){

return;

}

final int displayCount = mDisplayContents.size();

DisplayContent defaultContent = getDefaultDisplayContentLocked();

int displayId = 0;

DisplayContent secondDisplayContent = null;

for(int i = 0; i < displayCount;i++){

final DisplayContent content = mDisplayContents.valueAt(i);

if(content != defaultContent){

secondDisplayContent = content;

displayId = secondDisplayContent.getDisplayId();

Log.d("DualScreen", "WindowManagerService->moveWindowToSecondDisplayWithDualShow->secondDisplayId:" + displayId);

break;

}

}

if(secondDisplayContent == null){

return;

}

if(!okToDisplay()){

return;

}

SurfaceControl.openTransaction();

WindowState win = null;

try{

WindowList secondDisplayAddList = new WindowList();

WindowList defaultDisplayAddList = new WindowList();

WindowList secondDisplayWindows = secondDisplayContent.getWindowList();

WindowList defaultWindows = defaultContent.getWindowList();

if(mTempWindowList != null && mTempWindowList.size() > 0)

defaultWindows.addAll(mTempWindowList);

mTempWindowList.clear();

for(int i= defaultWindows.size()-1;i>=0;i--){

win = defaultWindows.get(i);

if(win == null){

continue;

}

if (win.mAppToken == null){

continue;

}

if(win.mAppToken.mTask == null){

continue;

}

int windowTaskId = win.mAppToken.mTask.mTaskId;

if(windowTaskId == currentFocusedTaskId){

defaultWindows.remove(win);

win.mDisplayContent = secondDisplayContent;

if(win.mWinAnimator != null){

int layerStack = secondDisplayContent.getDisplay().getLayerStack();

if(win.mWinAnimator.mSurfaceControl!= null){

win.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);

}

}

secondDisplayAddList.add(0,win);

}

}

for(int i= secondDisplayWindows.size()-1;i>=0;i--){

win = secondDisplayWindows.get(i);

if(win == null){

continue;

}

if (win.mAppToken == null){

continue;

}

if(win.mAppToken.mTask == null){

continue;

}

int windowTaskId = win.mAppToken.mTask.mTaskId;

if(windowTaskId == secondDisplayTaskId){

secondDisplayWindows.remove(win);

win.mDisplayContent = defaultContent;

if(win.mWinAnimator != null){

int layerStack = defaultContent.getDisplay().getLayerStack();

if(win.mWinAnimator.mSurfaceControl!= null){

win.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);

}

}

defaultDisplayAddList.add(0,win);

}

}

//secondDisplayWindows.clear();

secondDisplayWindows.addAll(0,secondDisplayAddList);

//defaultWindows.clear();

defaultWindows.addAll(0, defaultDisplayAddList);

for (int i = 0; i < displayCount; i++) {

final DisplayContent content = mDisplayContents.valueAt(i);

assignLayersLocked(content.getWindowList());

content.layoutNeeded = true;

}

//Log.i("DualScreen", "WindowManagerService->moveWindowToSecondDisplayWithDualShow->allTaskIds:" + allTaskIds);

ArrayList allStacks = getAllStacks();

Log.i("DualScreen", "WindowManagerService->moveWindowToSecondDisplayWithDualShow->allStacks:" + allStacks);

mSecondDisplayTaskId = currentFocusedTaskId;

Log.i("DualScreen", "WindowManagerService->moveWindowToSecondDisplayWithDualShow->curMoveTaskId:" + curMoveTaskId);

misMovingToSecond = true;

Settings.System.putInt(mContext.getContentResolver(), Settings.DUAL_SCREEN_ICON_USED, 1);

switchFocusWindow(curMoveTaskId);

updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false);

mAppTransition.setReady();

performLayoutAndPlaceSurfacesLocked();

}finally{

SurfaceControl.closeTransaction();

}

//shouldAppMoveBack(-1);

}

Binder.restoreCallingIdentity(origId);

}

4.副屏页面如何全屏显示?修改PhoneWindowManager.java下layoutWindowLw方法添加代码如下:

pf.top = df.top = of.top = cf.top = vf.top = 0;

pf.right = df.right = of.right = cf.right = vf.right = width;

pf.bottom = df.bottom = of.bottom = cf.bottom = vf.bottom = height;

---------------------

作者:默默等待__007

来源:CSDN

原文:https://blog.csdn.net/u011365633/article/details/55001840

版权声明:本文为博主原创文章,转载请附上博文链接!

java 双屏显示_Android双屏异显的实现相关推荐

  1. 计算机无法设置双屏显示,电脑双屏显示怎么设置?

    不少用户在使用电脑的时候,会加一个显示器并设置双屏显示,方便直接在电脑上的操作.尤其是使用小屏幕的笔记本时,加一个大屏显示屏来配合能让效率提高不少.那么要怎么设置才能让电脑双屏显示呢?下面就让我们一起 ...

  2. android翻盖手机双屏显示,使用双屏翻盖手机是一种怎样的体验?

    原标题:使用双屏翻盖手机是一种怎样的体验? 使用双屏翻盖手机是一种怎样的体验?心系天下W系列手机是中国电信在国内首推的高端机型,从W699臻金.W799臻品.W899臻尊.W999臻观到心系天下W20 ...

  3. java如何控制分屏显示出来的_Android Presentation双屏异显,副屏的操作

    最近有一个双屏显示的需求,当时一脸蒙逼完全不知如何着手,不负众望找到解决办法,在Android4.2版本以后提供了Presentation类,可以轻松实现在两块屏幕上同时显示不同的内容.做一下笔记. ...

  4. RK3188 Android5.1 双屏异显副屏显示异常

    平台 RK3188 + Android 5.1 + 双屏异显补丁 概述 首先,要支持双屏异显,需先打上对应补丁. 在实现了双屏异显功能后,问题并非必现,需要在特定情况下,比如本文中的问题: 安装多几个 ...

  5. 安卓系统双屏异显_Android 双屏异显实现的三种方式

    在各种产品脑洞大开的时代,需求也是日益新异,笔者最近开发了一套双屏异显app.现在做一些总结 1.双屏异显第一种实现方式(官方提供的Presentation) Android 提供了一个叫 Prese ...

  6. 全志A40i工业核心板,100%国产4核ARM Cortex-A7,支持“双屏异显”【显示接口能力,工业HMI首选方案】

    1 多核国产工业平台,支持国产ARM处理器发展 创龙科技SOM-TLA40i是一款基于全志科技A40i处理器设计的4核ARM Cortex-A7国产工业核心板,每核主频高达1.2GHz. 图 1 SO ...

  7. 全志H8/a83t专业安卓KTV主板,支持双屏异显,接口丰富,支持vga、hdmi、cvbs显示

    这个KTV安卓方案,早在去年就已经完成了.一直和客户在配合一些细节,主板很早就成熟. 支持接口: 1路hdmi.1路cvbs.1路vga 2路rs232串口.一路line in.一路line out. ...

  8. Android-Presentation双屏异显-一看就懂篇

    绪论 随着用户的需求增多,特别是对于一些Android平板电脑以及其他的一些Android智能设备可能有多个屏幕,用户不仅想要在主屏幕上显示内容,同样在第二屏幕上也要显示想要的内容,这样可以达到更好的 ...

  9. Android双屏异显的实现

    概述 Android实现双屏异显的实现方式有2种. 方式一:在Android4.2及以上平台上,按照标准Android SDK提供的API,使用Presentation类,将一个APP的相关内容显示到 ...

最新文章

  1. Android之NDK开发的简单实例
  2. POJ1324贪吃蛇(状态压缩广搜)
  3. 【实验】 策略路由配置案例
  4. windowsphone开发_十大混生开发框架
  5. android java 调用js_android WebApp 集成方式怎么使用java调用js
  6. php的 datetime,PHP DateTime-修改参考
  7. oracle时间戳效率问题,时间戳问题 - Oracle开发 - ITPUB论坛-中国专业的IT技术社区...
  8. Kotlin — 使用IDEA运行第一个Kotlin程序,打印“Hello World”!
  9. mysql自定义函数索引_MySQL自定义函数、视图、索引
  10. Jenkins问题:SVN插件未更新到最新代码
  11. 2021-2027全球及中国LXP平台行业研究及十四五规划分析报告
  12. suse 12 sp5安装bug
  13. python图像配准的原理_SIFT图像匹配及其python实现
  14. ORA-20011 问题处理
  15. 数据结构教程 李春葆主编 (第5版)绪论笔记
  16. 卡内基梅隆大学计算机专业类别,卡内基梅隆大学计算机专业优势介绍
  17. 数据可视化之基础图表
  18. Linux修改系统时间、时区
  19. Java中表头的边框置为实线_table表格设置边框线为单实线
  20. 27-爬取华尔街见闻网中行情的数据【股票数据的一种】

热门文章

  1. 【DOM】初识DOM
  2. Centos设置自带中文输入法
  3. GO语言学习资源整理
  4. 大数据ssm项目案例总结
  5. 特斯拉的巫术(5)——“彩蛋”和未来
  6. 名悦集团分享汽车保养小知识,汽车异味轻松去除有妙招
  7. 个人永久性免费-Excel催化剂功能第91波-地图数据挖宝之行政区域信息实时下载(含经纬度)...
  8. scanline_p8
  9. 常用流媒体协议(HLS/HTTP/RTP组播/RTSP)提取流的方法
  10. 冰箱智能感应开灯,飞睿科技雷达传感器应用,雷达感应技术发展