0%

Presentation实现双屏异显


由于公司的项目需求,需要在一台搭载Android系统的显示设备的两块屏幕上显示不同的内容,该设备拥有一块主屏和一块辅屏,这里就需要使用双屏异显的技术,以前没有接触过这一块的知识,经过一段时间的熟悉后顺利实现双屏异显,其实Android实现双屏异显并不难而且Google提供了现成的API,用Presentation这个类去实现,只不过没接触过的时候觉得挺高大上的,在此做一个简单的记录。


Presentation是一个特殊的dialog,可以在辅屏上显示与主屏不一样的内容,设置里面也可以把“模拟第二屏”的功能打开,运行的时候会在左上角显示一个小窗口来显示第二屏的显示内容,Presentation在创建的时候需要和Display对象相关联,关联之前需要先获取显示设备,DisplayManager或MediaRouter都可以来获取显示设备。下面用最简单的两个例子来介绍,在主屏和辅屏上都显示一个不同内容的TextView文本。

设置权限

1
2
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW" />

DisplayManager实现

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyPresentation extends Presentation {

public MyPresentation(Context outerContext, Display display) {
super(outerContext,display);

}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_screen);

}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MainActivity extends AppCompatActivity {

private MyPresentation myPresentation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

DisplayManager manager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = manager.getDisplays();
if (presentationDisplays.length > 1) {
// displays[0] 主屏 displays[1] 辅屏
myPresentation = new MyPresentation(this,displays[1]);
myPresentation.getWindow().setType(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
myPresentation.show();
}
}

@Override
public void onBackPressed() {
onDestroy();
//完全退出应用,取消双屏异显
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
System.exit(0);
}

这里的activity_main和second_screen就是一个xml布局,放了一个不同内容的TextView文本,代码就不贴了,可以看到DisplayManager的getDisplays方法可以返回一个可显示的Display数组,也就是当前可以连接的屏幕列表,第一个元素是主屏的Display对象,第二个元素是辅屏的Display对象,然后把辅屏的Display对象传入到Presentation的构造函数中绑定,设置窗口类型就可以展示了。

MediaRouter实现

这里就只贴辅屏的Display对象获取并传入到Presentation的构造函数中绑定的代码,因为其余部分都是一样的。

1
2
3
4
5
6
7
8
9
10
11
MediaRouter mediaRouter = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
MediaRouter.RouteInfo route = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
if(route != null) {
Display display = route.getPresentationDisplay();
if (display != null) {
myPresentation = new MyPresentation(this, display);
myPresentation.getWindow().setType(
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
myPresentation.show();
}
}

MediaRouter与DisplayManager不同的是MediaRouter会直接绑定周围最合适的设备。总的来说,这两个API实现的思路大致相同,都是要自定义Presentation,获取到一个辅屏的Display对象传入到Presentation的构造函数中进行绑定,Presentation初始化完成后设置窗口类型然后展示。