Presentation双屏异显,主屏后台运行副屏保持显示
在Android4.2版本以后,Google也是提供了Presentation类,可以实现在两块屏幕上同时显示不同的内容。
创建Presentation
Presentation是一种特殊的对话框,属于Dialog的子类,创建方式如下:
public class MyPresentation extends Presentation {
/**
* 重写构造函数
*
* @param outerContext 上下文必须为Activity,否则会报错
* @param display 副屏的Display
*/
public MyPresentation(Context outerContext, Display display) {
super(outerContext, display);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xxx);
}
}
在创建Presentation时若使用默认的Dialog类型,则只能使用activity类的context,不可以使用getApplicationContext()作为创建时的context,否则会报如下错误:
11-11 09:23:39.837 E/AndroidRuntime(17598): FATAL EXCEPTION: main
11-11 09:23:39.837 E/AndroidRuntime(17598): Process: com.will.Screen, PID: 17598
11-11 09:23:39.837 E/AndroidRuntime(17598): android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.view.ViewRootImpl.setView(ViewRootImpl.java:683)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:380)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.app.Dialog.show(Dialog.java:322)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.app.Presentation.show(Presentation.java:237)
11-11 09:23:39.837 E/AndroidRuntime(17598): at com.will.Screen.MainActivity$1.onClick(MainActivity.java:48)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.view.View.performClick(View.java:5647)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.view.View$PerformClick.run(View.java:22443)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.os.Handler.handleCallback(Handler.java:751)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.os.Handler.dispatchMessage(Handler.java:95)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.os.Looper.loop(Looper.java:154)
11-11 09:23:39.837 E/AndroidRuntime(17598): at android.app.ActivityThread.main(ActivityThread.java:6119)
11-11 09:23:39.837 E/AndroidRuntime(17598): at java.lang.reflect.Method.invoke(Native Method)
11-11 09:23:39.837 E/AndroidRuntime(17598): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
11-11 09:23:39.837 E/AndroidRuntime(17598): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
而使用activity类的context时,当程序转到后台运行时,副屏会退出MyPresentation设定的界面显示,变为和主屏同步。要副屏在程序转到后台时能够表示显示,则context必须设置为application,此时的dialog类型需要设置为全局dialog。
选择Display
在presentation创建时,需要指定其显示的具体设备。获取系统Display的方式共有两种。
1、通过MediaRouter获取display
MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
MediaRouter.ROUTE_TYPE_LIVE_VIDEO);
Display presentationDisplay = route != null ? route.getPresentationDisplay() : null;
// Dismiss the current presentation if the display has changed.
if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
mPresentation.dismiss();
mPresentation = null;
}
// Show a new presentation if needed.
if (mPresentation == null && presentationDisplay != null) {
mPresentation = new MyPresentation(context, presentationDisplay);
try {
mPresentation.show();
} catch (WindowManager.InvalidDisplayException ex) {
mPresentation = null;
}
}
2、通过DisplayManager获取display
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] presentationDisplays = displayManager.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
if (presentationDisplays.length > 0) {
Display display = presentationDisplays[0];
if (mPresentation != null && mPresentation.getDisplay() != display) {
mPresentation.dismiss();
mPresentation = null;
}
if (mPresentation == null) {
mPresentation = new MyPresentation(context, display);
try {
mPresentation.show();
} catch (WindowManager.InvalidDisplayException e) {
mPresentation = null;
}
}
}
activity后台运行副屏保持显示
创建普通的Presentation时,传入的必须是Activity的上下文,副屏会随创建它的Activity显示或隐藏。要实现activity后台运行时副屏能够保持显示,则需要Presentation拥有系统弹窗权限,此时传入Presentation的上下文可以是Application或Service。
实现方式如下:
- 添加权限
AndroidManifest.xml中声明系统弹窗权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- 设置系统弹窗
给创建的presentation设置权限
mPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
其他
- Presentation实际上是一个Dialog,所以里面无法弹出Dialog、PopupWindow等依赖于Activity的小窗口,同样也无法使用Fragment。