android 多屏幕显示activity,副屏,无线投屏

Posted 王二の黄金时代

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android 多屏幕显示activity,副屏,无线投屏相关的知识,希望对你有一定的参考价值。

目录

1. 首先,需要一个副屏

1. 1 可以通过代码的形式自己创建VirtualDispaly ,创建副屏。

1.2 或者,在手机的开发者模式中直接开启模拟副屏,也是可以的。

2.0 怎么利用这个副屏幕?

2.1  用作 presentation 演示ppt:

2.2 克隆主屏幕的内容,就是主屏幕显示什么,副屏显示同样的内容,镜像模式。

2.3  将一个activity 从第二个屏幕上启动,作为一个独立的屏幕


首先说明一下这个多屏幕的概念,这里不是指分屏显示。
分屏显示:是 一个屏幕分出多个窗口,分别显示不同app.
多屏支持:是一个设备有多个屏幕,怎么让不同的屏幕显示不同的app,或者是一个app同时用两个屏幕来显示不同的页面内容。

多屏幕显示,现在的车机都逐渐趋向于多个屏幕,一个android系统多个屏幕也越来越普遍,就算是手机,也出现比如多屏协作的场景。我猜它的原理也是在手机端创建虚拟无线屏,然后将app的activity单独在无线屏中启动。
 

本篇在手机上,验证将app的activity启动到另一个屏幕上。

1. 首先,需要一个副屏

1. 1 可以通过代码的形式自己创建VirtualDispaly ,创建副屏。


1.2 或者,在手机的开发者模式中直接开启模拟副屏,也是可以的


 将会在屏幕上看到一个叠加的小窗口,就是虚拟的第二个屏幕。


2.0 怎么利用这个副屏幕?

2.1  用作 presentation 演示ppt:

          presentation 顾名思义就是用来做演示的,一个窗口,好比windows  打开ppt的时候接上投影仪或者第二个屏幕,就可以开启演示模式,只是将ppt的内容输出到第二个屏幕,而电脑自己的控制桌面都是在自己的屏幕上。 关于怎么使用者presentation,不赘述。

2.2 克隆主屏幕的内容,就是主屏幕显示什么,副屏显示同样的内容,镜像模式。

       开发者模式中创建的虚拟副屏默认就是这种模式,createVirtualDispaly的时候可以指定flag. 

2.3  将一个activity 从第二个屏幕上启动,作为一个独立的屏幕

          需要用startActivity()方法,这个Activity将只会在一个屏幕上显示

  •  给activity的启动选项里面,加上要启动的设备ID。
  •  Intent中添加上Intent.FLAG_ACTIVITY_NEW_TASK

 代码如下:

// 多次创建副屏 则副屏的id都是增加的,所以不一定是1,这里还是获取一下
                    int SecondeDid = 0;
                    DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
                    for (Display display : displayManager.getDisplays()) 
                        Log.d(TAG, "dispaly: " + display.getName() + ", id " + display.getDisplayId() + " :" + display.toString());
                        if (display.getDisplayId() != 0) 
                            SecondeDid = display.getDisplayId();
                        
                    

// 先检查一下是不是支持在第二屏上显示activity这个特性,
// 在ActivityOptions.java setLaunchDisplayId 上面有相关的说明
                    PackageManager packageManager = getPackageManager();
                    boolean ret = packageManager.hasSystemFeature(PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
                    Log.d(TAG, "onCreate: have " + PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS + "   " + ret);

// 要加上Intent.FLAG_ACTIVITY_NEW_TASK 
                    ActivityOptions options = ActivityOptions.makeBasic();
                    options.setLaunchDisplayId(SecondeDid);
                    Intent intent = new Intent(StartActivity.this, CameraServerActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent, options.toBundle());

如下,将一个只是预览摄像头的 activity给显示在了虚拟副屏上。

 

2.3 方式,如果把用户的输入信息都加入进来,结合上无线投屏就是 多屏协作了,在电脑端独立使用手机的应用。

rk3288 android7副屏旋转显示异常与满屏修改

rk3288 android7副屏旋转显示异常与满屏修改

主屏使用的是HDMI,副屏使用的lvds
主屏是HMDI转lvds 由于转接模块不支持1280x800 所以设置了hdmi输入源为1280x720 为了保证主屏正常显示 修改了framebuffer为1280x800
就是由于修改了framebuffer导致副屏显示旋转异常,一定不要设置persist.sys.framebuffer.main这个参数

persist.sys.framebuffer.main=1280x800

查找rk资料了解到,双屏同显时,副屏显示是在主屏显示的基础上进行的缩放,双屏异显时,副屏显示是按照副屏实际物理分辨率重新进行了UI绘制
下面的patch能解决副屏旋转后显示异常及同显时不满屏的问题
修改patch如下

---
 device/rockchip/rk3288/system.prop                 | 13 ++++++-----
 .../server/display/LocalDisplayAdapter.java        | 20 ++++++++++++++++-
 .../com/android/server/display/LogicalDisplay.java | 26 +++++++++++++++++++++-
 .../services/surfaceflinger/DisplayDevice.cpp      |  3 ++-
 4 files changed, 53 insertions(+), 9 deletions(-)

diff --git a/device/rockchip/rk3288/system.prop b/device/rockchip/rk3288/system.prop
index 358f0fd..f34c991 100755
--- a/device/rockchip/rk3288/system.prop
+++ b/device/rockchip/rk3288/system.prop
@@ -48,9 +48,10 @@ ro.rk.displayd.enable=false

 sys.hwc.device.primary=HDMI-A
 sys.hwc.device.extend=LVDS
-persist.sys.framebuffer.main=1280x800
-persist.sys.resolution.main=1920x1080
-persist.sys.resolution.aux=480x1280
-ro.same.orientation=false
-#ro.orientation.einit=0
-ro.rotation.external=false
+#persist.sys.framebuffer.main=1280x800
+#persist.sys.resolution.main=1280x720
+#persist.sys.resolution.aux=480x1280
+#ro.same.orientation=false
+#ro.rotation.external=false
+ro.orientation.einit=270
+persist.sys.rotation.efull=true
diff --git a/frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 68be9ce..be69c7e 100755
--- a/frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -422,8 +422,26 @@ final class LocalDisplayAdapter extends DisplayAdapter {

                     // For demonstration purposes, allow rotation of the external display.
                     // In the future we might allow the user to configure this directly.
-                    if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+                    /*if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
                         mInfo.rotation = Surface.ROTATION_270;
+                    }*/
+                    String rotation = SystemProperties.get("ro.orientation.einit","0");
+                    switch(Integer.valueOf(rotation)) {
+						case 0:
+							mInfo.rotation = Surface.ROTATION_0;
+							break;
+						case 90:
+							mInfo.rotation = Surface.ROTATION_90;
+							break;
+						case 180:
+							mInfo.rotation = Surface.ROTATION_180;
+							break;
+						case 270:
+							mInfo.rotation = Surface.ROTATION_270;
+							break;
+						default:
+							mInfo.rotation = Surface.ROTATION_0;
+							break;
                     }

                     // For demonstration purposes, allow rotation of the external display
diff --git a/frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java b/frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
index 287a25a..acc4c9f 100755
--- a/frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -26,7 +26,7 @@ import java.util.Arrays;
 import java.util.List;

 import libcore.util.Objects;
-
+import android.os.SystemProperties;

@@ -137,6 +137,22 @@ final class LogicalDisplay {
                 mInfo.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
                 mInfo.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
             }
+            if(mDisplayId!=Display.DEFAULT_DISPLAY){
+                 String rotation = SystemProperties.get("ro.orientation.einit","0");
+                 int rot = Integer.valueOf(rotation)/90;
+                if(rot%2!=0) {
+                    mInfo.appWidth = mPrimaryDisplayDeviceInfo.height;
+                    mInfo.appHeight = mPrimaryDisplayDeviceInfo.width;
+                    mInfo.logicalWidth = mPrimaryDisplayDeviceInfo.height;
+                    mInfo.logicalHeight=mPrimaryDisplayDeviceInfo.width;
+                }else{
+                    mInfo.appWidth = mPrimaryDisplayDeviceInfo.width;
+                    mInfo.appHeight = mPrimaryDisplayDeviceInfo.height;
+                    mInfo.logicalWidth = mPrimaryDisplayDeviceInfo.width;
+                    mInfo.logicalHeight=mPrimaryDisplayDeviceInfo.height;
+                }
+            }
+
         }
         return mInfo;
     }
@@ -349,6 +365,14 @@ final class LogicalDisplay {
         mTempDisplayRect.right += mDisplayOffsetX;
         mTempDisplayRect.top += mDisplayOffsetY;
         mTempDisplayRect.bottom += mDisplayOffsetY;
+        if(SystemProperties.getBoolean("persist.sys.rotation.efull", false)) {
+		    if(device.getDisplayDeviceInfoLocked().type!=Display.TYPE_BUILT_IN){
+		         mTempDisplayRect.left=0;
+		         mTempDisplayRect.right=physWidth;
+		         mTempDisplayRect.top=0;
+		         mTempDisplayRect.bottom=physHeight;
+		    }
+        }
         device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
     }

diff --git a/frameworks/native/services/surfaceflinger/DisplayDevice.cpp b/frameworks/native/services/surfaceflinger/DisplayDevice.cpp
index 0c63381..68f93ce 100755
--- a/frameworks/native/services/surfaceflinger/DisplayDevice.cpp
+++ b/frameworks/native/services/surfaceflinger/DisplayDevice.cpp
@@ -538,6 +538,7 @@ void DisplayDevice::setProjection(int orientation,
 #endif

 #if !RK_VR & RK_HW_ROTATION
+#if 0
     bool isHdmiScreen = mType == DisplayDevice::DISPLAY_EXTERNAL;
     if (isHdmiScreen) {
         int eInitOrientation = 0;
@@ -599,7 +600,7 @@ void DisplayDevice::setProjection(int orientation,
         }
         ALOGV("update frame [%d,%d]",frame.getWidth(),frame.getHeight());
     }
-
+#endif
     if (mType == DisplayDevice::DISPLAY_PRIMARY) {
         mClientOrientation = orientation;
         orientation = (mHardwareOrientation + orientation) % 4;
--
2.7.4

参考资料

https://blog.csdn.net/MrDongShiYi/article/details/96477121/

https://blog.csdn.net/kris_fei/article/details/86598923

以上是关于android 多屏幕显示activity,副屏,无线投屏的主要内容,如果未能解决你的问题,请参考以下文章

理想副屏怎么划到主屏

双屏显示时如何设定主副屏

rk3288 android7副屏旋转显示异常与满屏修改

rk3288 android7副屏旋转显示异常与满屏修改

rk3288 android7副屏旋转显示异常与满屏修改

win7在扩展屏/副屏显示任务栏