今年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 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,现在很多功能已经可以通过浮窗接口实现。画中画对于做视频应用或者有视频支持功能的应用非常有帮助。
此外,给程序员朋友们几个小贴士
通知栏一直是 Android 引以为豪的方面。相对于 iOS 的通知栏来说, Android 的通知栏具有几乎完爆的功能:自定义控件,自定义 Action,可以定义下来拓展的控件……除了快速回复。
在这之前,先上一段 Android N 新版本的通知栏和快速设置栏,至于为什么放视频,嗯。。。因为我觉得很好看:
如今,这一点已经被 Google 迎头赶上,并且体验绝不亚于 iOS,甚至好很多。
当然,如果一次来了多条消息并且都不是一个会话中,快速回复也是毫无压力:
这个新特性简而言之就是满足了快速回复的一切需求,也许从此再也不用担心沉浸式阅读时需要跳出回复消息这种伤害体验的情况。
当然了,除了快速回复,还有根据应用归档通知,这无疑是一个大杀器:
同时,这里需要同时提醒 PM 和开发同学的是:如果真的需要在通知上设置自定义控件,请调用 DecoratedCustomViewStyle()。它会让你的自定义控件在通知栏显得更加和谐。Sample:
Notification noti = new Notification.Builder()
.setSmallIcon(R.drawable.ic_stat_player)
.setLargeIcon(albumArtBitmap))
.setCustomContentView(contentView);
.setStyle(new Notification.DecoratedCustomViewStyle())
.build();
说到这个话题,真的很想用标准朋友圈标题:《Android Developer 一定不会告诉你的事!怒转!》,嗯,希望朋友圈的产品经理和运营们不要打我。
几乎所有人刷了 Android N 之后最大的感触只有三个:1. 这特么和 Android 6.0 有毛区别!2. 通知栏好看了 3. 通知栏拉到一半就会有快捷通知,真是懒人福利。
嗯。。好吧。。。
99%的人不会发现的秘密:Android N 中允许第三方应用程序向快速设置栏添加自己的快速部件。这个可比传统 Widget 方便快捷得多。当然,这个入口千万不要做特别重的操作。同时,区别于 iOS 的通知栏部件,你的入口将和 WiFi 开启、GPS 设置等系统设置同等级。当然,这一切的一切前提是用户将你的 QuickSetting 部件拖拽到了快捷入口的位置。我写了一个小 Sample:
虽然接口还没有出现在 Android Developer,但是已经有离线文档可以下载(http://developer.android.com/preview/setup-sdk.html#docs-dl ),里边就有 Tile API。
好吧。。。其实我写了一个小 Sample,(https://github.com/yexuan910812/android_n_tile )
你咋不上天呢!
总之,我已经看到 PM 们扬起的嘴角,并且计划着如何强奸这个快速设置栏(幸好有需要用户拖拽设置这一条)。不过还是希望各位维护这个生态啊亲们!
好了,到这里为止,对于一部分 PM 来说,这个文章就结束了,可以去准备需求文档了(去吧,皮卡丘)!
当然,我们非常欢迎热爱探索的PM们继续与我们愉♂快♂讨♂论♂程序员的世界。
在这个章节,我不会具体去讲刚刚提到的那些 feature 该怎么实现,几乎所有的 feature(除了我已经提供的快速设置 API 之外)都有相应的 Sample(http://developer.android.com/preview/samples.html )。
Doze 模式是 Android M 中推出的一个省电模式,当手机灭屏一段时间之后(一般而言是十几甚至几十分钟),设备会进入 Doze 模式。在 Doze 模式中,系统会通过减少应用 CPU 调用以及禁止掉网络连接,达到省电的目的。与此类似还有一种机制叫 App Standby,顾名思义只要你的应用在一段时间内没有操作并且不在前台,比如主动弹一个 Notification 之类就会把你暂时冻结掉,Standby 嘛,一边玩去。嗯。。。好像哪里不太对。
『这不是逼着应用疯狂弹通知么!』
所以,Android N中,Doze模式变得更加强大且不容易被突破了。只要手机灭屏一小段时间,并且当前不在充电状态,就会进入 Doze 模式。在Doze 模式下,你的应用就几乎可以肯定拿不到 WakeLock,甚至于普通的 AlarmManager 也已经无法使用。
『可是我的应用是一个闹钟应用/有定时提醒功能,怎么办!』
这种情况倒也好办,要么就是让用户将自己的的应用加入白名单,要么就主动申请权限:
An app holding the REQUEST_IGNORE_ BATTERY_OPTIMIZATIONS permission can trigger a system dialog to let the user add the app to the whitelist directly, without going to settings. The app fires a ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS Intent to trigger the dialog.
当然,对于大部分应用来说,影响最大的就是网络方面。应用灭屏了就不能联网,IM应用们该怎么办!
对此,Google 给了两个解决办法:
PowerManager.isIgnoringBatteryOptimizations(java.lang.String)
接口查询到自己是不是在白名单内,如果不在,则通过ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
这个动作引导用户进入系统设置添加自己为白名单。
对了,顺便安利一个开源的分析工具:耗电记录。这个也是 Google 官方的耗电分析工具,可以方便得查看系统内耗电占用,甚至某个应用的某个组件耗电。像这样:
一目了然。
这个并不是说 Android 机器人变瘦了,实际上,它还是那个胖胖的样子:
额。。。天天吃苹果当然会胖。。。
言归正传,实际上,自 Android L 开始,Google 就在强力推荐应用使用 JobScheduler 代替其他方式来进行后台服务,甚至在2014年的 Google I/O 大会上将这个新接口放在了大会上演示,这是其他接口都不曾有的待遇。当时我甚至还在朋友圈声称这个将会是以后实现后台服务的唯一方式。
可是现实重重得打了我的脸,这个接口的使用率并不理想。终于,在Android N上,Google重提了这个接口,并进行了大规模的强化。今后,如果有需要后台处理的数据、或者特定情况的后台处理。举个例子,如果你需要在用户充电并且不在数据网络的时候处理一些逻辑,你就可以这样:
public static final int MY_BACKGROUND_JOB = 0;
...
public static void scheduleJob(Context context) {
JobScheduler js =
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(
MY_BACKGROUND_JOB,
new ComponentName(context, MyJobService.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresCharging(true)
.build();
js.schedule(job);
}
『何必这样,我写一个BroadcastReceiver监听CONNECTIVITY_ACTION然后处理不就行了,naive!』
科科。
为了防止这个没有节操的事情发生,Google 在 Android N中拿掉了这三个广播:
这也是我非常佩服 Google 的一个点,敢于做减法。当然,留下的坑就多了,比如 CONNECTIVITY_ ACTION,很多应用(包括微信)都会监听。今后需要使用 JobScheduler 实现相同的逻辑了。JobScheduler 有非常多的好处,他会根据用户当前设备的情况,比如当前 RAM、电量、模式、是否应用在前台等等,决定是否执行该逻辑。你也不希望自己的程序变成用户手机变卡的罪魁祸首,从而让用户怒删,对吧?
当然了,不允许监听 CONNECTIVITY_ ACTION 针对的是静态注册的 BroadcastReceiver,如果是动态注册的 BroadcastReceiver 则并不会受到影响。
早在前年开始研究 Annotation 的时候,就在感慨为什么 Android 一直不支持 Java 8,即使现在 Java 9 都快出了。终于的终于,Android从N 版本开始支持 Java 8的编译,前提是要在 Gradle 文件中显式声明使用 Jack 编译器。
这个 Jack 是什么鬼呢?简单来说,传统的编译工具链是将 java 代码通过 javac 编译成.class 文件,再通过 dx 编译成 .dex。也就是酱紫的:
javac (.java --> .class) --> dx (.class --> .dex)
而 Jack 则是一条龙服务,中间不需要经过其他工具或者命令,一条命令就可以将.java 文件编译成.jack 从而编程.dex:
Jack (.java --> .jack --> .dex)
使用 jack 非常简单,gradle 配置即可
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
不过,Android N 版本的 Java 8特性并没有支持全,不过主流的 feature 已经支持,包括:
但是现在还没有支持一个很重要的特性:Stream。但是现在还在 Preview 阶段,比如刚刚的第四条 Method Reference 就是 Preview2 支持的,可以期待下 release 中是否会支持(最新消息:已经支持 java.util.stream 接口,棒棒的!)。
此外还需要注意两点:
这一点 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 时代那个臃肿的、落后的以及。。额,难看的形象。就像这样:
这是2011年左右,毕竟是5年前,那时 iPhone 上的应用也并不好看,不过还是比 Android 要强很多。但是现在 Android 应用已经长这样了(系统自带应用):
个人认为比 Apple 的设计。。。(为了防止引战)至少并不差吧。
其实,这里说了这么多,精通读心术的我也能想到大家心中的疑问:碎片化如此的 Android 市场,我们就算是适配了 N 的特性,大家也没有这么快用上,还是歇着吧。嗯,关于碎片化,首先,Android 目前版本分布是酱紫的(来自 Google 官方,链接 http://developer.android.com/about/dashboards/index.html)
也就是说,至少截止到今天,接近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 上的应用,低质量的应用实现已经威胁到了我们自身。不仅仅是要依靠产品经理,作为程序员,我们也要学会自救。
感谢!
本文系腾讯Bugly独家内容,转载请在文章开头显眼处注明作者和出处“腾讯Bugly(http://bugly.qq.com)”