某学姐

Android Female Developer, Technology Fan, Reader.

Android学习笔记——target sdk 26升级实践

2018-09-02 | Comments

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

本文原文发自 某学姐, 转载请保留出处, 谢谢.

Comments