Android 8.0的正式版,官方代号为Oreo。新系统在优化和新功能设计上下足了功夫。

以下是一些比较重要的特性。

1、画中画模式PiP

PIP 是一种多窗口显示模式,多用于视频播放,即你可以一边发微信一边看视频。最早用于 Android TV,从 Android 8.0 开始,API 开放给所有 Android 设备。

android 画中画自定义ui 安卓画中画功能_生命周期

Android 的画中画是基于整个 Activity 的,并不是单纯的一个 View,因此,这里就会设计到 Activity 的生命周期的问题,所以画中画也会和 Activity 的生命周期绑定在一起,形成画中画生命周期。画中画的生命周期和 Android 7.0 推出的分屏模式的生命周期是一样的,只有当前和用户交互的 Activity 是最上层的 Activity,其它的可见的 Activity 都是 paused 状态。所以在处理画中画或者分屏模式需要注意 Activity 的生命周期。

实现方法:

在项目的 manifest 中,给对应的 Activity 加上

android:supportsPictureInPicture=ture

调用接口

Activity.enterPictureInPictureMode(PictureInPictureParams args)

进入画中画模式。PictureInPictureParams 可以携带画中画的配置参数,如在屏幕中显示多大比例等,如果参数为空,系统将会使用默认配置参数。后续也可以通过接口

Activity.setPictureInPictureParams()

来改变窗口大小(比例)等。

2、自适应启动图标

Android 的屏幕适配一直以来都折磨着不少的开发者。为了帮助开发者更好的与设备 UI 集成,Android O 支持创建自适应图标,系统可以基于设备选择的蒙版将这些图标显示为不同形状。

自适应图标支持多种形状

通过定义两张图层(前景与背景)你可以制定你的桌面图标外观,你必须提供没有形状和阴影的 PNG 格式图象作为图层。

android 画中画自定义ui 安卓画中画功能_图层_02

自适应图标由两张图层和一个形状来定义

在以前的 Android 版本中,图标大小定义为 48 x 48 dp。现在你必须按照以下的规范定义你的图层大小:

  1. 两张图层大小都必须为 108 x 108 dp。
  2. 图层中心 72 x 72 dp 范围为可视范围。
  3. 系统会保留四周外的 36dp 范围用于生成有趣的视觉效果(如视差和跳动)。

创建你的自适应图标

首先你需要在 Application 标签中加入 Android:icon 属性,定义你的 icon 图标。其次如果你需要创建一个原型的 icon,你还需要加入 Android:roundIcon 属性。

android 画中画自定义ui 安卓画中画功能_Android O_03

接下来,你需要 res/mipmap-anydpi/ic_launcher.xml 文件中定义您的图层。在 选项中加入您的前景和背景图层。

android 画中画自定义ui 安卓画中画功能_图层_04

3、通知渠道(Channeld)

通知渠道是由应用自行定义的通知内容类别,借助渠道,开发者可以让用户对不同种类的通知进行精细控制,用户可以单独拦截或更改每个渠道的行为,而不是统一管理应用的所有通知。

适配8.0的第一步自然是把targeSdk升级到26,在8.0中所有通知的实现都需要提供通知渠道,否则,所有通知在8.0系统上面都不能正常显示;

创建自定义渠道

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// The id of the channel.
String id = "my_channel_01";
// The user-visible name of the channel.
CharSequence name = getString(R.string.channel_name);
// The user-visible description of the channel.
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(id, name, importance);
// Configure the notification channel.
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
mNotificationManager.createNotificationChannel(mChannel);

 获取渠道信息:设备用户可以在设备的设置里改变应用自定义的渠道,因此应用可以通过如下接口获取当前渠道的配置信息

NotificationManager.getNotificationChannel (String channelId)
List<NotificationChannel> channels = NotificationManager.getNotificationChannels ()
NotificationChannel.getSound()
NotificationChannel.getImportance()
NotificationChannel.getVibrationPattern()

 引导到渠道界面:有时需要调转到渠道界面,让用户修改渠道设置

Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
intent.putExtra(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
startActivity(intent);

4、安装未知应用的权限

android APP都会有打开APP时内部提醒更新的功能,在Android 8.0上可能会出现,下载了apk包,安装不了的情况。因为Android 8.0在对用户权限上控制得更严格了。Android 8.0去除“允许未知来源”选项,需手动确认。

解决方法:

在AndroidManifest.xml文件中声明:

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

安装时判断是否获得权限:

getPackageManager().canRequestPackageInstalls();

如果没有,就引导用户打开权限(可以弹个dialog)

Intent intent =new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

用户打开权限就可以升级APP了。

5、悬浮窗

悬浮窗要使用类型 TYPE_APPLICATION_OVERLAY,原来的类型TYPE_SYSTEM_ALERT从Android8.0开始被舍弃了。

WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams();
    // 设置为TYPE_SYSTEM_ALERT类型,才能悬浮在其它页面之上
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // 注意TYPE_SYSTEM_ALERT从Android8.0开始被舍弃了
        wmParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
    } else {
        // 从Android8.0开始悬浮窗要使用TYPE_APPLICATION_OVERLAY
        wmParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
    }

6、后台执行限制