今天晚上,闲来无事,不想敲代码,于是乎来了解一下Android 5.0的新特性,似乎5.0都出来很久了,惭愧惭愧…
转载请注明出处:http://blog.youkuaiyun.com/qinjunni2014/article/details/44342725
文章内容大部分翻译自安卓官方文档,我们主要从技术从面上来看看5.0的系统对于开发者来说带来了那些变化:
1. Android运行时(ART)
在5.0中引入了ART代替了传统的Dalvik虚拟机作为默认的运行平台,ART的主要特性有:
1.1 Ahead-of-time 编译
在app安装的时候,ART会使用dex2oat工具将dex文件转化为可执行文件。而在传统的Dalvik虚拟机中,app是以dex文件形式存在,每次在执行app的时候,都会做一次编译,这样程序的执行效率就会下降。而使用ART,app安装的时候会进行一次预编译。ART的缺点在于兼容性问题,Google已经列出了常见的兼容性issues.
1.2 改善GC效率
垃圾回收GC会影响app的性能,ART会从一下几个方面来改善GC的效率
GC暂停次数减为一次
老的Dalvik在回收内存时会暂停两次,第一次Dalvik暂停所有的线程来分析堆的使用情况,第二个阶段Dalvik暂停所有线程来清理堆,这回导致应用在性能上得卡顿。ART在改进后只暂停一次
改善GC的及时性
GC的内存回收更加及时,使得GC_FOR_ALLOC会很少出现
1.3 改善调试环境
支持采样分析
以往的开发者,能通过traceview来做实时分析,但是TraceView在Dalvik上的结果会受到这种per-method-call调用的影响,而且使用这种工具会影响app的性能。在ART中,traceview不会有这些限制,它能给出在不影响app运行的情况下给出更准确的试图
支持很多新的调试特色
比如:
- 看出哪个当前栈中持有什么锁,然后跳到占有锁的那个线程
- 查询对于给定类有多少alive的实例,并且可以产看这些实例以及导致这些实例仍然活着的引用
- 对于某个instance过滤特定的event(比如断点)
- 支持查看函数退出时的返回值
- 支持field断点,让程序在一个特定的field被访问或修改时挂起
对于异常能给出更详细的细节和crash报告
比如对于NullPointerException,能给出更详细的关于的信息,对于该null指针,程序试图做什么。
大多数安卓程序可以在ART下直接运行而不会有任何问题,但是有一些能在Dalvik上work的技术在ART上却不一定管用。尤其需要注意的是:
- 你的应用使用了JNI来运行c/c++代码
- 你使用了某些开发工具来生成非标准的代码,比如混淆工具
- 你使用了一些与GC不兼容的技术
2. Notification消息
2.1 Material 设计风格
为了适应新的Material设计风格,新的Notification 样式使用深色字体,浅色背景,如果你的风格看起来不对,作如下修复:
- 调用setColor 设置一个accent color 作为icon的背景色
- 移除包含颜色的资源文件,notification中的icon包括action icon与主通知icon 都只包含alpha通道,颜色信息会被忽略
扩展样式:
2.2 声音和振动
如果你当前正在使用Ringtong,MediaPlayer 或者Vibrator来为你的app产生音效和振动效果,请移除这些代码,使用Notification.Builder中的函数来添加音效和振动,以便系统能以正确地优先级模式产生音效。
setVibrate(long[] pattern)指定了消息产生时振动的频率
setSound (Uri sound, AudioAttributes audioAttributes)
这个函数以及AudioAttributes这个类,都是在API level21中新加入的,指定了Sound的属性,
AudioAttribute主要指定了sound的用途,Content-type以及callback的标志,具体用法请见官方reference
2.3锁屏界面可见性
在5.0上,notification默认都可以在锁屏界面上显示,为了防止用户的隐私被暴露,用户可以通过setPublicVersion自定义
2.4 媒体播放
如果你想通过Notification来获取media的播放状态或者控制,你可以通过Notification.MediaStyle来实现,替代以前的RemoteView,无论通过哪种方式来实现,你都应该将notification的可见性设为VISIBILITY_PUBLIC,以便在锁屏界面上能够获取控制。而从5.0开始,系统不再开始在锁屏界面上显示RemoteControlClient(PS:貌似这个控件在国内这种生态环境下极为窘迫,因为锁屏界面通常都被定制了)。
2.5 Heads-up Notification
5.0开始,当手机屏幕是活动状态时,notification可以一个小的浮动窗口呈现在用户面前,用户可以在不用离开当前应用的状态下点击动作按钮或者dismiss 消息。
触发heads-up notification常见场景为:
- 用户当前activity处于全屏状态(应用使用fullScreenIntent)
- notification设置了很高的优先级而且使用了响铃或振动
PendingIntent pi = PendingIntent.getActivity(this, 101, new Intent(this, IntentActivity.class),0);
Notification.Builder builder = new Notification.Builder(this)
.setContentTitle("hello")
.setContentText("hello junli, Good morning")
.setSmallIcon(R.drawable.ic_launcher)
.setColor(getResources().getColor(android.R.color.holo_blue_light))
.setFullScreenIntent(pi,true);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(101, builder.build());
3. 媒体控制与RemoteControlClient
就像在notification中讲到的一样,你可以在锁屏界面上呈现出媒体控制界面,通过MediaSession,能达到这一目的。5.0中为notification引入了MediaStyle这一设置, 可以将你通过Notification.Builder.addAction()添加的动作按钮,紧凑的呈现出来。
通过设置setSession可以配置notification控制指定的MediaSession。通过.setVisibility(Notification.VISIBILITY_PUBLIC)以使其出现在锁屏界面上。我们先来看看这一功能如何实现:
MediaSession session = new MediaSession(this, "hello");
Notification noti = new Notification.Builder(this)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Track title")
.setContentText("Artist - Album")
.addAction(R.drawable.ic_prev, "Previous", pi) // #0
.addAction(R.drawable.ic_pause, "Pause", pi) // #1
.addAction(R.drawable.ic_next, "Next", pi) // #2
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.angle))
.setStyle(new Notification.MediaStyle()
.setMediaSession(session.getSessionToken())
.setShowActionsInCompactView(0, 1, 2))
.build();
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(101, noti);
看锁屏效果,
其实纵观国内这一市场,大部分音乐播放器都是实现了自己的锁屏界面,这样不仅能使音乐控制界面更加丰富,比如可以看到歌词,添加收藏等,还可以避免其他自定义rom厂商,使用自己的锁屏实现而是使个功能不兼容。
4. getRecentTasks废弃
以往的app可以通过ActivityManager.getRecentTasks(),获得用户最近启动的任务,但是从5.0开始,为了保护用户隐私,这一功能被废弃了。为了向后兼容,这一函数仍然返回少量信息,比如app内的任务,或者一些不敏感的task比如home,但是如果仅仅只是为了获取这些信息,你可以通过调用getAppTasks来达到。
5. 64位的支持
5.0中引入了对64位的支持,64位在完全支持32位的同时,增大了地址空间,改善了性能。还能增强openSSL密码的效率。另外,5.0版本还引入了对native媒体ndk api的支持包括对native openGL ES的支持。为了使用5.0中的64位支持,开发者可以下载NDK revesion 10c来提供支持。
6. 绑定到Service
5.0中如今bind到service需要一个显式的intent,如果传递了隐式的intent,将会抛出异常。为了app的安全起见,在开启或者绑定到service时,需要指派显式的intent,而且不需要为service设置intent-filter