Multi-Window技术预研

让我告诉你Multi-Window是什么鬼

在Android N以前,Android是无法像IOS或者传统PC那样舒畅地同时运行多个App的,谷歌曾经在 Android M预览版中提供分屏多任务的功能,但是在正式版中被砍掉了。不过很多厂商在自己的定制ROM中添加了这一功能,如三星、LG在Android 4 的年代就有了这些功能。一些视频应用也支持小窗口播放视频,这主要是利用WindowManager来添加悬浮界面,此外还有一些开源的解决方案,但是也只是在特定的系统版本和高性能的机器上才能支持。但是Android N之后,Google放大招了,Android用户也开始体验一下,同时做多件事情的功能了。在Google3月份放出的Android N预览版中,我们惊喜的发现Android N增加了对同时在一个屏幕上展示多个App的支持。用户可以将屏幕切分成多块,同时进行不同的操作。在不久的将来,我们在日常的手持设备上也可以和PC一样一边看视频,一边接收邮件。在多屏模式下,多个App可以分享同一个屏幕,用户可以随意的拖动切分线,使一个App的显示区域变大而使另外一个App的显示区域变小。多屏模式下,即使用户现在正在操作App A,系统也允许App B继续展示他的内容。

Android N支持以下几种模式的多屏模式:

1.Side-By-Side模式:两个 App 瓜分一个屏幕(可以左右并排,也可以上下并排)

2.One-above-the-other模式:一个 App 浮动在另一个 App 之上

3.Picture-in-picture模式:主要应用在Android TV上,用户在浏览其他 App 的时候,视频可以浮动在屏幕上。

用户有以下两种方法进入多屏模式:

1.点击Menu键进入任务视图,长按App的标题栏,拖动App到屏幕高亮的位置。然后在任务视图中选择另一个App,单击它使得这个App也进入分屏模式。

2.用户长按Menu键,当前App将进入多屏模式,然后打开任务视图让用户选择另外的App一起分享屏幕。

功能的视频演示:1.http://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid=404127595&idx=1&sn=9090ac8078f4a80421a88e2c6106829f&scene=23&srcid=0418uD1q88kCdIcNyWHYZJXh#rd

2.http://www.iplaysoft.com/android-n.html

Multi-Window下Activty的生命周期

Google并没有改变Multi-Window模式下的Activity的生命周期。在Multi-Window模式下,只有用户最近一个操作的Activity是Actived状态的(该Activity被称为topmost),其他可见的Activity都是Paused状态。当用户再次操作这些Paused状态的Activity的时候,这些Activity的状态将onResume变成Actived,而其他Activity将变成Paused状态。但一个与以前不同的地方在于,系统会给予更高的权限和优先级给这些可见而非Active状态的Activity(相比于非Active又不可见的Activity)。

Activity的生命周期

Demo1

首先我写了一个视频播放器Demo重温一下在Android N以前,Activity的生命周期是怎么样的。我在Activity里用MediaPlayer播放一段视频,在Android 4.4的机器上当Activity进入Stop状态的时候,视频就被强制停止播放并且MediaPlayer被回调onCompletion方法,代表视频播放被系统强制终结了。

首先起一个半透明的AnotherActivity去遮挡MainActivity,MainActivity会回调onPause,但是视频不会停止播放。

然后起一个不透明的AnotherActivity去覆盖MainActivity,MainActivity会回调onPause和onStop,然后回调Mediaplayer的onCompletion,然后结束视频播放。

从上面的一个试验当中可以看出,在Android N以前应用onPause进入Paused状态之后,应用并非真正的停止。但是这时候由于MainActivity已经被遮挡,所以我们应该在onPause中停止视频播放,并记录下播放进度,在用户回到播放器的时候seekTo调整播放进度重新播放视频。

Demo2

这里我尝试在Android N上进入Multi-Window模式,去看看Android N上系统是如何给予非Active状态下的Activity更高的权限。

上图中我打开了两个App,上面的是一个Gmail App,下面这个是一个Demo App。现在这两个App都是进入了分屏模式。我点击了Gmail,浏览了一封邮件,那么此时Gmail就被系统视为Actived状态,而下面的Demo App虽然对用户可见,但是它仍然是处于Paused状态的。接着我点击了系统的Back按钮返回,响应的是上面的Gmail。然后我又点击了下面的Demo App,这时它从Paused状态onResume变成了Actived状态。而上面的Gmail进入了 Paused状态。

注意,这两个App对于用户都是始终可见的,当它们处于Paused状态时,也将比那些后台的处于不可见的App得到更高系统优先级。这个优先级怎么体现呢?两个App进入分屏模式后,一定有一个处于Paused/Actived状态,假如我一直按Back返回,当这个Actived状态App的Task返回栈已经为空时,那么系统将把另外一个可见的App恢复为全屏模式。

对比Demo1,在Android N的分屏模式中,一个App可以在对用户可见的状态下进入Paused状态,所以你的App在处理业务时,应该知道自己什么时候应该真正的暂停。例如一个视频播放器,如果是进入了Andorid N的分屏模式,就不应该在onPaused()回调中暂停视频播放,而应该在onStop()回调中才暂停视频,然后在onStart回调中恢复视频播放。但是如果你的应用是运行在Android N以前,onPause代表Activity被部分遮挡,这是就应该在onPause中暂停视频播放,并在onResume中恢复播放。

你的App如何使用Multi-Window

如果你适配到了Android N,即build.gradle是这样的(截取自官方Demo):

此外,Andorid N提供了少量新的用于定制是否完全支持Multi-Window的 XML 属性。

android:resizeableActivity=["true" | "false"]

在AndroidManifest.xml的<activity> 或者 <Application>下加入以上属性。如果是true,表示这个activity可以自由随意的操作在多屏模式下。如果是false表示不支持多屏模式,这种情况下用户如果尝试去多屏模式,则会全屏显示。在android n下默认为true。特别注意的一点是:一个根Activity的设置属性将会被应用到所有在这个Task栈中的Activity(一个任务栈的根Activity一般是这个任务栈栈底的Activity,即该任务栈第一个启动的Activity)。即当根Activity的android:resizeableActivity属性为true,则在这个Task栈中的所有其他Activity都将是支持多屏模式的。

android:supportsPictureInPicture=["true" | "false"]

在manifest的<activity> 下加入以下属性,支持画中画(特殊的多屏模式)。如果resizeableActivity为false,这个属性被忽略。

<activity android:name=".MyActivity">
     <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minimalSize="450dp" />
  </activity>

在android中,一个activity的布局可以设置以下属性:在Android N中,我们可以向manifest文件中添加layout节点,并设置一些新增加的属性,通过这些属性来设置分屏模式的一些行为,如最小尺寸等。

如果你的应用支持Android N的话,你可以在manifest 中加入以下属性控制你的App的尺寸和布局。如果你的App的SDK版本低于Android N并且没有限定multi-orientation,当用户使用多屏模式的时候,系统将强制去拉伸你的App,不需要额外的配置字段。系统会弹出一个dialog警告用户,此App并不期望你在多屏模式下操作他。当你的应用是 fixed-orientation的时候,在多屏模式下,则系统不会自动拉伸而是直接全屏显示。

Multi-Window提供的API

Google仅仅为Multi-Window添加少量的 API,这些新的API可以让Activity接收到 Mutil-Window 状态改变的通知,以及判断是否处于 Mutil-Window 模式。

Activity.inMultiWindow()

查看一个Activity是否运行在Multi-Window模式。

Activity.inPictureInPicture()

查看一个Activity是否运行在PictureInPicture模式。(PictureInPicture画中画是一种特殊的多窗口模式,若inPictureInPicture()返回true,则inMultiWindow()也将返回true)

Activity.onMultiWindowChanged(boolean inMultiWindow)

当一个Activity进入或者退出多窗口模式的时候,系统将会回调onMultiWindowChanged()方法。参数inMultiWindow为true表示进入多窗口模式,为false表示退出多窗口模式。

Activity.onPictureInPictureChanged(boolean inPictureInPicture)

当一个Activity进入或者退出PictureInPicture模式的时候,系统将会回调onPictureInPictureChanged()方法。参数inPictureInPicture为true表示进入PictureInPicture模式,为false表示退出PictureInPicture模式。

Activity.enterPictureInPicture()

调用此方法可以使一个Activity进入画中画模式,如果Activity不支持画中画模式则无效果。

在Fragment也有对应的方法,比如说Fragment.inMultiWindow()。

使用Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT可以启动一个activity使其与当前Activity一起运行在多屏模式下。注意:这里只是尝试,但这不一定是100%生效的,前一篇博客里也说过,假如新打开的Activity的android:resizeableActivity属性设置为false,就会禁止分屏浏览这个Activity。所以系统只是尝试去以分屏模式打开一个新的Activity,如果条件不满足,将不会生效!

当满足下面的条件,系统会让这两个Activity进入分屏模式:

当前Activity已经进入到分屏模式。

新打开的Activity支持分屏浏览(即android:resizeableActivity=true)。

如果你在一个任务堆栈中启动一个新的 Activity,这个 Activity 会替换屏幕上的当前 Activity ,并且会继承所有它的多窗口属性,如果要启动一个显示在多窗口中的 Activity 需要启动一个新的任务,新任务才能是新窗口。(intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_Task);)

如何支持拖拽数据传送

Android N基于Multi-Window提供了一个强大的功能,在多屏模式下允许在两个Activity之间进行数据拖拽传输(在此之前,用户只能在一个 Activity 内部拖放数据),Android N Preview SDK中,View已经增加支持Activity之间拖动的API。

android.view.DropPermissions

接收方App所得到的权限列表,这个对象负责授权给App接收一个数据。

View.startDragAndDrop()

startDrag的替代方法。启用跨 Activity 拖放。

需要传递View.DRAG_FLAG_GLOBAL来实现跨Activity拖拽。如果需要将URI权限传递给接收方Activity,还可以根据需要设置View.DRAG_FLAG_GLOBAL_URI_READ或者View.DRAG_FLAG_GLOBAL_URI_WRITE。

View.cancelDragAndDrop()

取消当前进行中的拖拽,只可以被拖拽的发起方调用。

View.updateDragShadow()

可以给当前进行的拖拽设置阴影,由拖拽的发起方调用。

Activity.requestDropPermissions()

请求推送权限。传递URI权限时,需要调用这个方法。传递的内容存储在DragEvent中的ClipData里。返回值为前面的android.view.DropPermissions。

Demo3

Demo3实现了在分屏模式下,把一个Activity中ImageView中保存的内容到另外一个Activity中进行显示。实际应用中,可以还可以传递图片的url或者Bitmap对象。

上图是一个最基本的例子,实现了把MainActivity中的图片保存的内容,拖拽到SecondActivity中。实现步骤如下:

在MainActivity中,发起拖拽。

在SecondActivity中,接收这个拖拽的结果,在ACTION_DROP事件中,把结果显示出来。

这里实现的关键在新增加的startDragAndDrop方法,看下官方的API文档:清楚地提到了,发出的DragEvent能够被所有可见的View对象接收到,所以在分屏模式下,SecondActivity可以监听View的onDrag事件,于是我们监听它!

接着,我们看下DragEvent.ACTION_DROP事件发生的条件:当被拖拽的View的阴影进入到接收方View的坐标区域,如果此时用户松手,那么接收方View就可以接收到这个Drop事件。一目了然,我们通过拖拽ImageView到图上的灰色区域,松手,便可以触发DragEvent.ACTION_DROP,把数据传到SecondActivity中了。

面对更复杂的一些情况,需要调用requestDropPermissions。

带来的问题

1.应用如要支持多窗口,也有一些需要注意的地方,最主要的是分辨率的适配。在多窗口模式下,应用的显示比例不一定是手机屏幕的比例。这里可能会影响到一些代码,比如应用一启动就全局存储一下屏幕的宽高,在N下可能就有问题了,需要开发者做相应的修改。

2.在多屏模式以下特性无法使用:应用无法隐藏状态栏如果他不是全屏模式下。

3.系统忽略android:screenOrientation属性(无法根据屏幕方向来旋转App的界面)。

参考文章

1.http://blog.sina.com.cn/s/blog_63f5ae1a0100zajv.html

2.http://developer.android.com/intl/zh-cn/guide/topics/resources/runtime-changes.html

3.http://developer.android.com/intl/zh-cn/training/basics/activity-lifecycle/starting.html

4.http://unclechen.github.io/2016/03/12/Android-N-App%E5%88%86%E5%B1%8F%E6%A8%A1%E5%BC%8F%E5%AE%8C%E5%85%A8%E8%A7%A3%E6%9E%90-%E4%B8%8A%E7%AF%87/

5.http://unclechen.github.io/2016/03/12/Android-N-App%E5%88%86%E5%B1%8F%E6%A8%A1%E5%BC%8F%E5%AE%8C%E5%85%A8%E8%A7%A3%E6%9E%90-%E4%B8%8B%E7%AF%87/?utm_source=tuicool&utm_medium=referral

时间: 2024-10-06 03:30:18

Multi-Window技术预研的相关文章

iOS9 Https技术预研

一.服务器需要做的事情: 1.要注意 App Transport Security 要求 TLS 1.2, 2.而且它要求站点使用支持forward secrecy协议的密码. 3.证书也要求是符合ATS规格的,ATS只信任知名CA颁发的证书,小公司所使用的 self signed certificate,还是会被ATS拦截..因此慎重检查与你的应用交互的服务器是不是符合ATS的要求非常重要. 二.客户端可使用四种方案: 1.全部Https  2.俩者混合,个别不符合  3. 全部禁用Https

[转] 前后端分离开发模式的 mock 平台预研

引入 mock(模拟): 是在项目测试中,对项目外部或不容易获取的对象/接口,用一个虚拟的对象/接口来模拟,以便测试. 背景 前后端分离 前后端仅仅通过异步接口(AJAX/JSONP)来编程 前后端都各自有自己的开发流程,构建工具,测试集合 关注点分离,前后端变得相对独立并松耦合 开发流程 后台编写和维护接口文档,在 API 变化时更新接口文档 后台根据接口文档进行接口开发 前端根据接口文档进行开发 开发完成后联调和提交测试 面临问题 没有统一的文档编写规范,导致文档越来越乱,无法维护和阅读 开

Windows Server 2016技术预览

Windows Server 2016是微软将于2016年9月份发布的最新服务器操作系统.目前微软官方发布了许多Windows Server 2016新的功能和特性,下面我们来简单看下: 主要内容 预览版界面 系统需求及安装 服务器管理变化 新特性及变化 预览版界面 服务器界面,沉浸而不渲染 登录界面,色调变得活泼起来,用户图像由原先Windows2012的方块变成圆形 继续 进入系统,乍一看,以为是WIN10呢,注意右下角 如此做法,似乎在传递win10的最佳服务器系统就是他了 开始菜单,Al

微软发布Win10:技术预览版免费下载

微软今日如约放出了Windows 10技术预览版的下载,大家现在就可以免费下载Windows 10技术预览版ISO文件,安装并开启体验. Windows 10技术预览版首批提供了英语.简体中文.葡萄牙语,含32位.64位. Windows 10技术预览版简体中文版64位大小为3.96GB,32位大小为3.05GB. 产品密钥:NKJFK-GPHP7-G8C3J-P6JXR-HQRJR Windows 10技术预览版简体中文版官方下载: 64位:http://go.microsoft.com/fw

Windows 10 技术预览版抢先体验

Windows 10 是微软公司新一代操作系统,即传说中的Windows Threshold,NT内核为6.4.该系统于2014年9月30日(美国东部时间, 北京时间2014年10月1日)发布开技术预览版.北京时间10月2日凌晨开放下载技术预览版[1] .该操作系统可能会是微软的最后一款操作系统(即不再有大更新). Windows 10正式版将于2015年发布,将涵盖PC.平板电脑.手机.XBOX和服务器端,芯片类型将涵盖Intel.AMD和ARM[2] . 上面文字引述百度百科内容. ====

WINDOWS SERVER 2016 TP4(技术预览第四版)搭建MDT 2013 UPDATE 1成功

c=gengchenencheenWINDOWS SERVER 2016 TP4(技术预览第四版)搭建MDT 2013 UPDATE 1成功 WINDOWS SERVER 2016 TP4(技术预览第四版) MDT 2013 UPDATE 1

Nvidia NVENC 硬编码预研总结

本篇博客记录NVENC硬编码的预研过程 步骤如下: (1)环境搭建 (2)demo编译,测试,ARGB编码 (3)研究demo源码,阅读API文档 (4)封装so共享库,联调测试多路编码性能 (5)研究内存,显存拷贝方案,尝试解决CPU,GPU消耗过高等性能问题 1. 环境搭建 (1)编译环境,预研中这个环境不是我亲手搭建的,需要CUDAToolKit, NVENC SDK (2)运行环境,需要Nvidia独立显卡,另外还要注意NVENC SDK的版本对显卡驱动版本有要求,具体在SDK的文档中会

System Center 10 DPM技术预览版安装体验

前言 整体来说,System Center DPM技术预览版的安装过程和之前DPM 2012 R2的安装过程没有太大的区别,安装完成后的管理界面也没有太大的区别.相信等正式版推出之后,会有大量的新功能和新特性放出来,对新产品的支持会更好. 下载的安装包是exe格式的,需要先解压出来. 进入到解压后的文件夹,运行SCDPM的安装文件. 然后进入DPM的安装向导,选择install data protection manager. 同意许可协议. DPM会自动完成先决条件的准备组件安装. 进入安装的

iOS 技术预览

iOS 技术预览 1. 关于iOS相关技术 iOS是运行在iPad,iPhone,iPod设备上的操作系统.iOS Software Development Kit(SDK)包含开发.安装.运行.测试App需要的工具和接口.App开发使用Objective-C和Apple提供的框架.帮助文档 :Xcode>Help>Documentation and API Reference 2. iOS分层体系结构 层次: -------------------- |  Cocoa Touch | ---