Android Presentation实现双屏异显

一、概述

现在越来越多的Android设备有多个屏幕,双屏异显应用场景最多的应该就是类似于收银平台那种设备,在主屏上店员能够对点商品进行选择录入,副屏则是展示给我们的账单详情,但是它只通过了一个软件系统就实现了双屏异显这个功能,而Presentation正是这其中的关键。

二、Presentation分析

1.简述:首先从它的继承关系上来看Presentation是继承自Dialog的,就是说它其实就是一种特殊的Dialog用于在第二个屏幕上显示内容的,它在创建时会和它的目标展示屏幕相关联,包括它的context和一些配置参数等。

2.Context:然而这里提到的context和它的容器所处的context会有不同,它会用自身的context去加载presentation的布局和相关资源以此来确保在目标屏幕上能够展示正确的大小和获取合适的屏幕密度。

3.自动移除:虽说presentation和它相关联的Activity的context不同,但是他们也不是完全分离的关系,当和presentation相关联的屏幕被移除后,presentation也会自动的被移除,所以当Activity处于pause和resume的状态时Presentation也需要特别注意当前显示的内容的状态。

4.屏幕选择:因为有时候我们的Android设备有多个屏幕,所以选择合适的屏幕去展示就显得非常重要了,所以在我们显示Presentation的时候需要去让我们的系统去选择合适的屏幕来进行展示,以下是两种方式去选择一个合适的屏幕。

这是我们选择展示presentation最简单的一种方式,media router是一种系统层级的服务,它能够追踪到系统当中所有可用的音频和视屏route,当有路径被选中或取消选中,还有当适合用presentation进行显示的时候的route改变的时候它会发送一个通知,然后应用本身会监控这个通知自动的去选择presentation的展示或者隐藏,这里的推荐使用的presentation display其实只是media router推荐的,如果我们的应用需要在第二个屏幕上进行显示就使用,如果不用的话就用本地来展示内容。

  • 利用media router去选择presentation的显示屏幕
  • 利用display manager去选择persentation的显示屏幕

DisplayManager能够监控到我们系统当中的所有连接上的显示设备,然而不是所有的设备都适用于作为副屏来进行内容展示的,比如当一个Activity想显示一个presentation在主屏幕上,其实效果就会相当于在主Activity当中显示了一个特殊的Dialog,所以当我们选择这种方式去选用Presentation去显示的时候就必须给它绑定一个可用的display。

三、源码分析

首先来看它的构造函数

public Presentation(Context outerContext, Display display, int theme) {
 super(createPresentationContext(outerContext, display, theme), theme, false);

 mDisplay = display;
 mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE);

 final Window w = getWindow();
 final WindowManager.LayoutParams attr = w.getAttributes();
 attr.token = mToken;
 w.setAttributes(attr);
 w.setGravity(Gravity.FILL);
 w.setType(TYPE_PRESENTATION);
 setCanceledOnTouchOutside(false);
 }

在它的形参中第一个Context参数非常重要,这是应用正在展示presentation的一个context,它是Presentation自己创建的它自己的一个context,基于这个context才能正确的在它所关联的屏幕上展示合适的信息。然后代码里面设置了这个window的相关属性。

接着我们看看它自身的Context的创建

private static Context createPresentationContext(
 Context outerContext, Display display, int theme) {
 //首先判断传入的context和display是否为空,为空则抛出异常
 if (outerContext == null) {
 throw new IllegalArgumentException("outerContext must not be null");
 }
 if (display == null) {
 throw new IllegalArgumentException("display must not be null");
 }

 Context displayContext = outerContext.createDisplayContext(display);

 //这里是对它的主题的判断,为0即为默认主题
 if (theme == 0) {
 TypedValue outValue = new TypedValue();
 displayContext.getTheme().resolveAttribute(
  com.android.internal.R.attr.presentationTheme, outValue, true);
 theme = outValue.resourceId;
 }

 // Derive the display's window manager from the outer window manager.
 // We do this because the outer window manager have some extra information
 // such as the parent window, which is important if the presentation uses
 // an application window type.
 final WindowManagerImpl outerWindowManager =
 (WindowManagerImpl)outerContext.getSystemService(WINDOW_SERVICE);
 final WindowManagerImpl displayWindowManager =
 outerWindowManager.createPresentationWindowManager(displayContext);

 //因为ContextThemeWrapper的父类是我们的Context
 //所以这里最终返回的就是Presentation给我们创建好的Context
 return new ContextThemeWrapper(displayContext, theme) {

 //在这个方法中又返回的是Object对象
 @Override
 public Object getSystemService(String name) {
 if (WINDOW_SERVICE.equals(name)) {
  return displayWindowManager;
  //如果和这个传入的name相同的话返回的就是上面windowManager创建出来的WindowManager的一个具体实现
 }
 //否则就返回的是Context这个抽象类中的一种服务类型
 return super.getSystemService(name);
 }
 };
 }

接着我们继续看一下Presentation对屏幕增加、移除和改变的监听

private final DisplayListener mDisplayListener = new DisplayListener() {
 @Override
 public void onDisplayAdded(int displayId) {
 }

 @Override
 public void onDisplayRemoved(int displayId) {
 if (displayId == mDisplay.getDisplayId()) {
 handleDisplayRemoved();
 }
 }

 @Override
 public void onDisplayChanged(int displayId) {
 if (displayId == mDisplay.getDisplayId()) {
 handleDisplayChanged();
 }
 }
 };

这里我们看到它对add并没有进行处理,所以我们进一步去看一下onDisplayRemoved中的关键handlerDisplayRemoved和onDisplayChanged中的核心handlerDisplayChanged的实现

handlerDisplayChanged:

private void handleDisplayChanged() {
 onDisplayChanged();

 // We currently do not support configuration changes for presentations
 // (although we could add that feature with a bit more work).
 // If the display metrics have changed in any way then the current configuration
 // is invalid and the application must recreate the presentation to get
 // a new context.
 if (!isConfigurationStillValid()) {
 Log.i(TAG, "Presentation is being dismissed because the "
  + "display metrics have changed since it was created.");
 cancel();
 }
 }

在这个方法中,我们遗憾的发现Google程序员并没有对当前屏幕配置发生改变后做特殊的处理,所以当我们的屏幕尺寸等信息改变时,我们的presentation必须重新Create去重新获取context,再重新进行显示。

@Override
 protected void onStart() {
 super.onStart();
 mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);

 // Since we were not watching for display changes until just now, there is a
 // chance that the display metrics have changed. If so, we will need to
 // dismiss the presentation immediately. This case is expected
 // to be rare but surprising, so we'll write a log message about it.
 if (!isConfigurationStillValid()) {
 Log.i(TAG, "Presentation is being dismissed because the "
  + "display metrics have changed since it was created.");
 mHandler.sendEmptyMessage(MSG_CANCEL);
 }
 }

同时在onStart中我们也能发现,因为它暂时还没有对display change进行监听,而这里又是有可能会改变的,所以在这种情况下它是打印了一个log去通知一下。

handlerDisplayRemoved这个方法的话是系统自动去发送一个消息,然后调用后把presentation自动取消掉。

四、总结

在基本分析了Presentation之后,主要要注意一下它的Context以及和Activity之间绑定的关系,其实从简单来看,它就是一个Dialog,不过是可以显示在多个屏幕上。当然上述分析深度尚浅,更深入的理解和一些问题要在后续工作中多使用再继续观察。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android从网络中获得一张图片并显示在屏幕上的实例详解

    Android从网络中获得一张图片并显示在屏幕上的实例详解 看下实现效果图: 1:androidmanifest.xml的内容 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.capinftotech.image" an

  • Android使用百度地图出现闪退及定位时显示蓝屏问题的解决方法

    使用百度地图出现闪退 一般情况下出现闪退是在AndroidManifest.xml文件中未在application标签中配置 <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="D9Lh8MrrLMUuXdWMU8tRLtDsta6PoaYN" /> 但是,有些同学会发现,所有配置都是按照官网或者教程上的步骤来配置依旧会出现闪退问题.此时,不要盲目直接去网上搜索使用百度地图出

  • android开发教程之textview内容超出屏幕宽度显示省略号

    实现如下: 复制代码 代码如下: <TextView android:layout_width="fill_parent"                    android:layout_height="wrap_content"                   android:id="@+id/hello"                    android:ellipsize="end"          

  • android 中去掉窗口全屏显示的简单方法

    复制代码 代码如下: //去掉窗口        requestWindowFeature(Window.FEATURE_NO_TITLE);(一定要放在setContentView(R.layout.main)的前面)        //全屏显示        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

  • Android下Activity全屏显示实现方法

    本文较为详细的讲述了Android下Activity全屏显示实现方法.分享给大家供大家参考.具体方法如下: 方法一: 使用xml的方法,在该项目的AndroidManifest.xml文件中,在需要全屏的Activity元素中添加属性: 复制代码 代码如下: android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 这样就可以实现这个Activity的全屏显示,如果只是不要标题栏,即需要保留系统自带的任务栏的话,则使用: 复制

  • 分享Android平板电脑上开发应用程序不能全屏显示的问题解决

    本来LCD应该是800*600的,但总是得到600*600的结果.经过好几天的努力,才解决: 复制代码 代码如下: <http://schemas.android.com/apk/res/android>"      package="myb.x2.app2"      android:versionCode="1"      android:versionName="1.0"> <android:screenO

  • Android实现固定屏幕显示的方法

    本文实例讲述了Android实现固定屏幕显示的方法.分享给大家供大家参考.具体如下: 在Android开发中我们会碰到开发屏幕扭转的情况,如何固定住屏幕ScreenOrientation 呢? 在学习jetboy代码时,发现屏幕被旋转了,代查代码没有找到相关设置,在manifest.xml中找到了相关的代码: 找到这名代码: 复制代码 代码如下: android:screenOrientation="portrait" portrait表示横向,landscape表示纵向 如果要使Ac

  • Android编程之界面实现全屏显示的方法(2种方法)

    本文实例讲述了Android编程之界面实现全屏显示的方法.分享给大家供大家参考,具体如下: 在开发android的应用当中,我们会遇到将一些界面设置为全屏显示的格式,有两种实现的方法.其一是在Java代码中实现,其二是在配置文件中实现. 1. 在Java代码中设置 super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); //无title getWindow().setFlags(Wind

  • Android判断NavigationBar是否显示的方法(获取屏幕真实的高度)

    有些时候,我们需要知道当前手机上是否显示了NavigationBar,也就是屏幕底部的虚拟按键. 比如截屏的时候,要获取屏幕的高度,必须包括NavigationBar的高度. 试过网上的多种方法,但是对那种可以通过手势来显示/隐藏的NavigationBar没办法,最后终于找到了一个好办法,看代码: public boolean isNavigationBarShow(){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_M

  • Android Presentation实现双屏异显

    一.概述 现在越来越多的Android设备有多个屏幕,双屏异显应用场景最多的应该就是类似于收银平台那种设备,在主屏上店员能够对点商品进行选择录入,副屏则是展示给我们的账单详情,但是它只通过了一个软件系统就实现了双屏异显这个功能,而Presentation正是这其中的关键. 二.Presentation分析 1.简述:首先从它的继承关系上来看Presentation是继承自Dialog的,就是说它其实就是一种特殊的Dialog用于在第二个屏幕上显示内容的,它在创建时会和它的目标展示屏幕相关联,包括

  • Android如何实现设备的异显功能详解

    目录 前言 一.什么是异显 二.实现步骤 2.1权限 2.2定义分屏的界面 2.3操作分屏界面 总结 前言 大家都知道无线投屏或者有线投屏的功能,但应该很少有人知道安卓中的异显功能? 这篇文章是为了让大家对异显有初步的认识,以及怎么实现简单的异显. 一.什么是异显 无线投屏或者有线投屏的时候,安卓设备的画面会原封不动的投影在显示器上,这就是投屏. 而异显,则是安卓设备和显示器的画面分开显示,比如安卓设备上在聊天,显示器上还可以在播放电影,是不是和多窗口的感觉有点像. 当然,安卓设备需要支持VGA

  • Kotlin-Android之Activity使用详解

    目录 Activity中Toast的使用 Activity中不使用findViewById()获取控件ID Activity中使用菜单Menu Activity中intent的使用 intent显式 intent隐式 intent数据的传递 传递数据 返回数据 扩展 参考 Activity中Toast的使用 Toast.makeText(this,"ADD",Toast.LENGTH_SHORT).show() // Toast.makeText(Activity,提醒字符,lengt

  • Android开发之完成登陆界面的数据保存回显操作实例

    本文实例讲述了Android开发之完成登陆界面的数据保存回显操作.分享给大家供大家参考,具体如下: LoginActivity.java: package com.example.login; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.text.TextUtils; import android.view.Menu; import android.view

  • Android显式启动与隐式启动Activity的区别介绍

    前段时间立志坚持写博客,但是发现自己的积累的确不多,于是假期泡了泡图书馆,读了一些很有价值的文章.收获颇多,今天的文章分享为主,共同学习. 为什么要写显式启动与隐式启动Activity.这源于自己的一次面试,被Baidu工程师问道,但是后来觉得自己回答的不好,废话少说,进入正题. 如题,Android的Acitivity启动大致有两种方式:显式启动与隐式启动.下面分别介绍: A:显式启动 对于初学者来说,这个最常见,下面用代码来解释什么是显式启动. 复制代码 代码如下: Intent inten

  • 如何在Android中实现渐显按钮的左右滑动效果

    先看下运行效果:    程序结构: MainActivity文件中代码: 复制代码 代码如下: package com.android.buttonpageflipper;import android.app.Activity;import android.graphics.PixelFormat;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.Gra

  • Android手机卫士之获取联系人信息显示与回显

    前面的文章已经实现相关的布局,本文接着进行相关的功能实现 读取系统联系人 当点击"选择联系人"按钮后,弹出联系人列表,读取系统联系人分如下几个步骤: 系统联系人提供了一个内容提供者,通过内容解析器,匹配Url地址 1.内容解析器 2.Url地址,查看系统联系人数据库,内容提供者源码 先看api文档的清单文件,后看java类(联系人数据库有多张表) contents://com.android.contacts/表名 3.系统联系人数据库中核心表的表结构 raw_contacts 联系人

  • Android数据加密之异或加密算法的实现方法

    这几天被公司临时拉到去做Android IM即时通信协议实现,大致看了下他们定的协议,由于之前没有参与,据说因服务器性能限制,只达成非明文传递,具体原因我不太清楚,不过这里用的加密方式是采用异或加密.这种加密方式在之前做Android加密记事本的时候采用过这种加密方式.今天已经把客户端心跳维持.数据包解析对接完了,总结一下这种加密方式. 什么是异或加密? 异或运算中,如果某个字符(或数值)x 与 一个数值m 进行异或运算得到y,则再用y 与 m 进行异或运算就可以还原为 x ,因此应用这个原理可

  • 解析Android数据加密之异或加密算法

    前言: 这几天被公司临时拉到去做Android IM即时通信协议实现,大致看了下他们定的协议,由于之前没有参与,据说因服务器性能限制,只达成非明文传递,具体原因我不太清楚,不过这里用的加密方式是采用异或加密.这种加密方式在之前做Android加密记事本的时候采用过这种加密方式.今天已经把客户端心跳维持.数据包解析对接完了,总结一下这种加密方式. 其他几种加密方式: Android数据加密之Rsa加密 Android数据加密之Aes加密 Android数据加密之Des加密 Android数据加密之

  • Android实现类似execel的表格 能回显并能修改表格内容的方法

    如下所示: 自定义实现一个水平滚动控件HorizontalScrollView package com.example.view; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.HorizontalScrollView; /** * 自定义实现一个水平滚动控件HorizontalScrollView * @autho

随机推荐