【Bugly干货】关于 Android N 那些你不知道的事儿
今年3月,Google 破天荒提前半年发布了 Android N 开发者预览版。当然,作为一个不合格的谷粉并没有第一时间体验安装,因为至今仍然能够回忆起来去年今日此门中(雾)兴冲冲刷了 Android M Preview 的时候发现各种 Crash 就连微信也(不出所料得)中招时自己一脸懵逼的心情。当然,为自己的机智而庆幸并没有过多久,很快就有微信好友(当然也是纯纯的谷粉)反馈微信又双叒叕在 Android 新版本下 Crash了……好吧这次我们的时间很充裕,因为 5 个 preview 之后才会发布最终 release 版本。令人失望(咦)的是,我们的工程师在一天之内就修复了这个 bug 并且赶在当天 6.3.15 alpha 版本发布之前修复并合入主线,辜负了 Google 的一片苦心。
痛定思痛,当天我就拎起来麒麟臂,在 Chrome 的地址栏重重得敲入:http://developer.android.com/preview/overview.html ,并且听说Google 在北京举办了 Android 开发者大会的时候,屁颠屁颠得过去了。
假如我是产品经理
在这个『人人都是产品经理』的年代,作为程序员当然是敲得起代码,当得起经理(。。。)。如果我是产品经理,Android N 的更新无非是以下三个点:
-
默认多窗口支持
-
强化通知,里边有你最喜欢的直接回复
-
没了…当然不是:Android Developer 一笔带过的重磅 feature:允许第三方应用在快速设置中添加自己的服务
注意『默认』二字:这很重要,这很重要,这很重要。
![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230208472-2145637492.jpg)
Android M 里边,系统允许应用在启动某 Activity(对于 PM 来说可以不严谨得理解成界面)时带上特殊参数,该应用可以在最近任务窗口中和主应用分开显示,即 multi-tasking 支持。当然,并没有多少应用鸟这个 Android M 中为数不多的新特性之一,因为效果实在是不明显。也有一定的原因是在这个大部分产品经理不会关注 Android Developer 的年代,这个非默认的特性实在不会引起他们的注意。
在 Android N 中,竟然直接支持了 multi-window!虽然这个特性并不惊艳,在 iOS 和三星的机型中早已支持,甚至在 Android M 中,也可以预埋了这个特性,并可以通过某些特殊方法开启。然而,和 iOS 应用需要特殊声明才能支持多窗口的特性不同,Android N竟然默认支持了多窗口。这意味着任何一个应用,无论 target-api 是否是 Android N,都支持从最近任务中长按应用标题栏进入多窗口模式。这里是个 Demo。
默认支持也就意味着除非特殊声明,任何应用都支持前述视屏所示效果,也就是说如果应用不针对这种模式进行完美适配,或者说用了绝对布局的话,你的应用就会。。。。呵呵呵。
当然,这种老掉牙的特性是不会引起高冷的 PM 的注意的,只会扔给开发狗交给我们去适配。那好吧,来一个 one more thing 刺激一下你:
在 Android N 中,将支持分屏情况下 drag and drop,让这个4.0开始就支持 faeture 焕发了新生。这也就意味着你可以将一个应用内、甚至不同应用间的分屏情况将一个分屏幕控件拖拽到另外一个分屏幕。也许可以用来拖拽图片快速发图,或者。。随便你想干什么。
当然,从开发狗的角度来说,这里有一点安全隐患:如果通过拖拽将数据传递过来,你甚至不知道来源是什么。但是想想也是,毕竟用的和粘贴板一样的接口,还能指望什么呢?
另外,作为分屏的一种特殊形式,画中画(picture in picture)也得到了相应的支持。不过据 Google 的工程师说,画中画模式主推 Android TV 中应用(也许 Google 认为在手持设备上场景不足)。不过 whatever,现在很多功能已经可以通过浮窗接口实现。画中画对于做视频应用或者有视频支持功能的应用非常有帮助。
此外,给程序员朋友们几个小贴士
-
虽然分屏状态下两个应用都可见,但是对于非 Focus 状态的应用当前是处于 onStop 状态的,也就是说,并没有实际在运行中。原本 onStop 的时候应用应该是不可见,但是现在可见了。。。原本的一些恶心逻辑注意修改下。
-
虽然分屏状态下的应用不会 double 内存占用,但是内存占用肯定会比正常状态大,注意分屏模式下即时释放内存。
-
适配好你的程序,该加 scroll 的地方加 scroll。当然,如果原本的你的程序就已经针对多尺寸屏幕有了处理,就已经完美适配了这个模式
通知栏一直是 Android 引以为豪的方面。相对于 iOS 的通知栏来说, Android 的通知栏具有几乎完爆的功能:自定义控件,自定义 Action,可以定义下来拓展的控件……除了快速回复。
在这之前,先上一段 Android N 新版本的通知栏和快速设置栏,至于为什么放视频,嗯。。。因为我觉得很好看:点我看视频
如今,这一点已经被 Google 迎头赶上,并且体验绝不亚于 iOS,甚至好很多。
当然,如果一次来了多条消息并且都不是一个会话中,快速回复也是毫无压力:
这个新特性简而言之就是满足了快速回复的一切需求,也许从此再也不用担心沉浸式阅读时需要跳出回复消息这种伤害体验的情况。
当然了,除了快速回复,还有根据应用归档通知,这无疑是一个大杀器:
![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230239597-1902287167.jpg)
同时,这里需要同时提醒PM和开发同学的是:如果真的需要在通知上设置自定义控件,请调用DecoratedCustomViewStyle()。它会让你的自定义控件在通知栏显得更加和谐。Sample:
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
|
Notification noti = new Notification.Builder() .setSmallIcon(R.drawable.ic_stat_player) .setLargeIcon(albumArtBitmap)) .setCustomContentView(contentView); .setStyle( new Notification.DecoratedCustomViewStyle()) .build(); |
『何必这样,我写一个BroadcastReceiver监听CONNECTIVITY_ACTION然后处理不就行了,naive!』
科科。
为了防止这个没有节操的事情发生,Google 在 Android N中拿掉了这三个广播:
-
CONNECTIVITY_ACTION:网络变化
-
ACTION_NEW_PICTURE:添加新图片
-
ACTION_NEW_VIDEO:添加新视频
这也是我非常佩服 Google 的一个点,敢于做减法。当然,留下的坑就多了,比如 CONNECTIVITY_ ACTION,很多应用(包括微信)都会监听。今后需要使用 JobScheduler 实现相同的逻辑了。JobScheduler 有非常多的好处,他会根据用户当前设备的情况,比如当前 RAM、电量、模式、是否应用在前台等等,决定是否执行该逻辑。你也不希望自己的程序变成用户手机变卡的罪魁祸首,从而让用户怒删,对吧?
当然了,不允许监听 CONNECTIVITY_ ACTION 针对的是静态注册的 BroadcastReceiver,如果是动态注册的 BroadcastReceiver 则并不会受到影响。
Java 8支持
扯淡
早在前年开始研究 Annotation 的时候,就在感慨为什么 Android 一直不支持 Java 8,即使现在 Java 9 都快出了。终于的终于,Android从N 版本开始支持 Java 8的编译,前提是要在 Gradle 文件中显式声明使用 Jack 编译器。
这个 Jack 是什么鬼呢?简单来说,传统的编译工具链是将 java 代码通过 javac 编译成.class 文件,再通过 dx 编译成 .dex。也就是酱紫的:
[Java] 纯文本查看 复制代码
1
|
javac (.java --> . class ) --> dx (. class --> .dex) |
而 Jack 则是一条龙服务,中间不需要经过其他工具或者命令,一条命令就可以将.java 文件编译成.jack 从而编程.dex:
[Java] 纯文本查看 复制代码
1
|
ack (.java --> .jack --> .dex) |
使用 jack 非常简单,gradle 配置即可
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
|
android { ... defaultConfig { ... jackOptions { enabled true } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } |
不过,Android N 版本的 Java 8特性并没有支持全,不过主流的 feature 已经支持,包括:
-
定义接口默认实现方法
-
Lamda 表达式支持(喜欢语法糖的同学的福利)
-
Repeatable annotations。这个已经可以说的内容很多,改天有空给大家慢慢介绍。
-
Method Reference。这个实话实说我并不是太了解,也是语法糖一种。感兴趣的同学可以看看这个链接:https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html
此外还需要注意两点:
-
Lamda 表达式本质上回生成匿名类,在性能敏感的模块慎用
-
由于 Jack 编译器不会产生.class 中间文件,因此在.class 上做 trick 的一些库或者项目可能就会失效或者出问题。因此在使用之前,一定要好好测试。
-
Data Saver:乍看上去是一个数据存储的 API,感觉很兴奋,结果点开一看是流量节省。。。好吧,博大精深的英文。从 Android N 开始,系统层级支持用户针对每一个应用添加自己的流量控制限制。今后开发的时候需要先通过 ConnectivityManager.getRestrictBackgroundStatus() 接口获取本应用流量控制情况。
-
Key Attestation:对于绝大部分应用并不需要仔细研究的 feature,甚至可以当做不存在,但是对于我个人所做的生物认证项目来说,可谓是非常重要的 feature。
-
针对文件目录或类型申请权限:实话实说,这个也算是一个很重要的 feature。从 Android 6.0 开始,如果需要使用存储空间,包括读写,需要动态申请权限。然而对于大部分应用来说,都需要申请这个权限,而且一旦用户允许,应用就可以为所欲为。因此,Android N 中允许应用声明仅仅授权某个文件夹或者文件类型的存储。
这一点 Android Developer 没有讲,至少暂时没有讲
还记得之前我说的微信升级到 N 会 Crash 么?实际上就是这个原因。
自 Android N 开始,系统将禁止第三方应用 so 文件链接系统 lib 库,包括并不限于 libcrypto.so,libandroidruntime.so,libicu.so,libbinder.so。动态链接上述库轻则弹 Toast 提示,重则直接 crash。Android 此举原因大家可以讨论,但是事实已然如此,尽管对于大多数应用而言并无妨碍,但是对于类似微信这种在底层做了大量优化和调用的应用来说还是很伤脑筋的。至于解决方法。。。暂时只想到了改用静态链接,对于包的大小增加并不会太大。如果有更好的方法,欢迎大家讨论。
实话实说,这次 Android N 的更新对于我们程序员来说还是干货满满,满到我有些话想说。
前面说的都是 Android N,现在终于开始讲扯淡了。实际上,从 Android L 开始,Google 就已经开始反省自己过分开放的策略。原本后台任务满天飞的系统,现在渐渐地被控制得有序起来。比如 Android L 发布的 JobScheduler,Android M 发布的 Doze 模式和 APP Standby,Android N 的 Doze 加强以及瘦身计划,无一不是在限制系统的后台任务数量以及计算强度。亡羊补牢,不知是否为时未晚。
同时,关于设计方面,Material Design 推出已经接近两年,尽管有很多应用已经适配,但是包括微信、Facebook、Twitter 在内的很多主流应用仍然在坚持使用自己的设计语言。诚然,这里有可以理解的风格统一之考虑, MD 本身也有很多缺陷,但是我们很高兴能看到的是 MD 自身在不断的调整优化,越来越成为一个漂亮的并且优秀的设计,其层次感以及灵动性无处不撩拨着用户的神经。所以,是不是仍有很多人抱着 2.3 混乱局面或者 4.0 不那么优秀的 Android Design 来臆测 Android 的设计风格?也许用着 iOS 的诸位对于 Android 的印象依然是 2.x 时代那个臃肿的、落后的以及。。额,难看的形象。就像这样:
![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230312738-1555173501.jpg)
这是2011年左右,毕竟是5年前,那时 iPhone 上的应用也并不好看,不过还是比 Android 要强很多。但是现在 Android 应用已经长这样了(系统自带应用):![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230336457-2083408736.jpg)
![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230336457-2083408736.jpg)
个人认为比 Apple 的设计。。。(为了防止引战)至少并不差吧。
其实,这里说了这么多,精通读心术的我也能想到大家心中的疑问:碎片化如此的 Android 市场,我们就算是适配了 N 的特性,大家也没有这么快用上,还是歇着吧。嗯,关于碎片化,首先,Android 目前版本分布是酱紫的(来自 Google 官方,链接 http://developer.android.com/about/dashboards/index.html)![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230356472-1782748168.jpg)
![](https://images2015.cnblogs.com/blog/833142/201604/833142-20160430230356472-1782748168.jpg)
也就是说,至少截止到今天,接近40%的人的设备已经是 Android 5.0 以及以上,按照如今厂商发货的速度,目测一两个月内比例就会过半。平心而论,针对这半数用户,有几家应用做到了完美支持?无论是 UI 还是具体功能,大部分应用应该都是在4.x,甚至2.x版本的基础上填坑,fix 新版本上的 crash,有几家用到了新的特性,新的 feature 呢?而大家以为占主流的2.3系统,实际上已经不足3%,是不是仍然有很多应用的 target api 仍然是 4.x 以下?
而且 Google 现在很鸡贼啊(这一点谢老大提醒),一年发布一个大版本,前年5.0,去年6.0,今年 7.0,你说 Google 都到 7.0 了你还好意思连 5.0 都不上?这一点实际上对于解决碎片化是非常有帮助的。
面对占市场份额近 7 成的 Android 设备本身并不需要救助,一直都没有放弃发展,欣欣向荣。相反,需要救助的是我们在 Android 上的应用,低质量的应用实现已经威胁到了我们自身。不仅仅是要依靠产品经理,作为程序员,我们也要学会自救。
感谢!