PS:在总结这部分内容之前,首先提醒自己的是,developer.android.com官网还是很重要的,官网上能第一时间看到Android系统新的特性,保持对官网的敏感不让自己的知识体系落伍。
Android 6.0 - API 23:
https://developer.android.com/about/versions/marshmallow/android-6.0-changes
主要特性:Runtime Permissions
Android 7.0 - API 24:
https://developer.android.com/about/versions/nougat/android-7.0-changes
主要特性:FileProvider
Android 8.0 - API 26:
https://developer.android.com/about/versions/oreo/android-8.0-changes
主要特性:后台服务Service、隐式广播BroadcastReceiver、通知栏Notification、快捷方式Shortcut、Alert Window、自适应启动图标Adaptive icons
首先是为什么要升级?主要原因是Android官网上Google Play的要求。
https://developer.android.com/distribute/best-practices/develop/target-sdk
本人经历的是项目由target sdk 23升级到target sdk 26。
涉及到修改的点是:
FileProvider
https://developer.android.com/reference/android/support/v4/content/FileProvider
FileProvider是ContentProvider的子类,通过content://替换file:///实现不同应用间文件的安全共享。
首先是为啥content://访问比file:///更安全?
content:// 通过Intent.setFlags()方式可以实现临时访问权限。权限持续时间是启动的Activity或Service运行期间。只有启动Intent的app才具备访问权限。
file:/// 只能修改文件系统权限实现访问权限,具备访问权限后所有app都能访问,取消权限需要修改文件系统权限。
基本修改思路:
查找涉及到跨应用文件访问的代码。全局搜索同时包含Uri.fromFile(uri)和new Intent(action)的代码片段,再分析对应的是不是跨文件访问,然后做出修改。
// 拍照、图片或视频文件选择、文件安装
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), mimeType);
// 分享
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setData(Uri.fromFile(file));
修改方式:
添加flags:intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION)
同时Uri.fromFile(file) -> FileProvider.getUriForFile()
后台服务Service
限制:当应用位于后台时,不能启动或使用后台服务。
修改原因:出于性能考虑,因为后台运行Service会占用资源。
满足以下任意条件即前台应用:
包含可见Activity,无论start或pause状态都可以。
包含前台服务。
和另外一个前台应用建立连接,绑定到该前台应用的Service或使用ContentProvider等。
当应用位于前台时,可以创建前台和后台服务;当应用进入后台时,有几分钟的窗口时间允许创建和使用后台服务,窗口时间结束后系统会停止后台服务。
另外就是前台服务的启动方式也发生了变化。
修改方式:
对于后台服务:
// 原来启动方式是startService时,使用JobScheduler
Service -> JobService,IntentService -> JobIntentService
// 原来启动方式是bindService时,不需要做修改
// PendingIntent.getService()实现上也是startService()
PendingIntent.getService() -> PendingIntent.getBroadcast()
对于前台服务:
调用startForegroundService(xxx)启动,同时在Service的onCreate()调用startForeground(),这个时间限制是5秒,否则会出现ANR。
隐式广播BroadcastReceiver
不能在AndroidManifest文件里注册隐式广播。
但是有一些例外。https://developer.android.com/guide/components/broadcast-exceptions
隐式广播:一般指不只是针对特定APP的系统级广播。
修改原因:主要出于性能考虑,BroadcastReceiver在收到广播时会消耗资源。对于AndroidManifest静态注册的广播,BroadcastReceiver的生命周期和Application一样;而registerReceiver()动态注册的广播,生命周期是unregisterReceiver()之前,可以自由控制。
有些情况可以用JobService代替广播,如网络监听时。
通知栏Notification
https://developer.android.com/guide/topics/ui/notifiers/notifications
主要变化是:增加了NotificationChannel的概念。将Notification按照NotificationChannel进行分类,实现对某一类通知栏的单独控制。一个APP可以创建多个NotificationChannel
快捷方式Shortcut
使用ShortcutManager创建快捷方式
悬浮窗Alert Window
如果要在App或系统窗口之上显示Window,显示需要设置window type的属性为TYPE_APPLICATION_OVERLAY
,当然还是位于状态栏和输入法的下层。
自适应启动图标Adaptive icons
https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive
可以做到在不同类型的设备上,显示不同形状的图标。区分前景foreground和背景background两部分。
网上随便一搜也能搜到很多资料。https://www.jianshu.com/p/d9f5b0801c6b