介绍

很多 Android 手机有刘海屏,如果应用程序不对其进行支持,那么应用程序就不会在刘海区域显示,刘海区域会变成黑色的长条背景,极其难看。

国内的手机厂商在 Android 未正式支持刘海屏之前就自行修改 Android O 添加了刘海屏的支持,因此适配方案各个厂商都不相同。

而到了 Android P,Google 终于加入了对各种异形屏的支持,包括不限于刘海屏、挖孔屏、水滴屏等等各种异形屏。具体可以参考以下介绍:

环境

  • Unity 5.3.8f2
  • Android Studio 4.0
  • Android 11
  • Windows 7
  • macOS 10.14.6

问题

由于使用的 Unity 版本较旧,导致适配问题只能自行处理。Unity 2018.3 及以上版本可以勾选显示到安全区外选项。

另外想要尽可能适配国内厂商生产的 Android O 刘海屏,很多人不会升级手机出厂时的操作系统,因此希望尽可能兼容更多的玩家。

任务

Android 版本

  • Android P Google 官方支持刘海屏
  • Android O 各家厂商有自己的实现方案。

Unity 版本

  • Unity 2018.2 及以下版本需要自行适配
  • Unity 2018.3 及以上版本可以勾选显示到安全区外选项

游戏显示

  • 游戏需要自行决定是否将内容、UI 显示在刘海中

Android 处理

  • 判断是否是刘海屏
  • 设置是否在刘海屏上显示
  • 获取刘海区域的大小

最终决定只需要将游戏画面完全显示到刘海屏区域中即可。

适配方案

Android O 适配

因Google官方的适配方案到Android P才推出,因此在Android O设备上,各家厂商有自己的实现方案。 我这里主要适配了华为、小米、oppo,这三家都给了完整的解决方案。至于vivo,vivo给了判断是否刘海屏的API,但是没用设置刘海区域显示到API,因此无需适配。

Android P 及以上版本适配

Google 官方 Android 文档,中文编写,非机翻,质量非常高:

方案总结

针对刘海屏适配的问题,网上已经有了相当多的资料介绍,可以进一步阅读参考:

最初是想用设置属性的方法适配刘海屏,比较 Unity 2018.4.25 导出的支持与不支持刘海屏的工程,主要在 AndroidManifest.xmlcom.unity3d.player.UnityPlayerActivity 结点下多了

1
2
3
            <meta-data
                android:name="android.notch_support"
                android:value="true" />

application 结点下多了

1
2
3
        <meta-data
            android:name="notch.config"
            android:value="portrait|landscape" />

assets/bin/Data/boot.config 中有如下改动:androidRenderOutsideSafeArea=1

但是这种方法适配 Android O 意味着要参考国内厂商的文档手动适配一遍,工作量太大。

最后考虑使用网上现成的开源库,一是直接适配 Android O 与 P,二是经过许多人的验证质量会更高。

开源库

主要找到以下两个开源库:

  1. GitHub - smarxpan/NotchScreenTool: Android刘海屏、水滴屏等全面屏适配工具
  2. zhangzhun132/NotchTools: 💥💥Android刘海屏适配方案—NotchTools,适配国内四大厂商(华为、小米、oppo、vivo)刘海屏手机,根据自己业务需求,提供多种接入方式适配刘海屏。

比较两个项目,看起来第二个 Star 数量更多且最后提交时间更近一些,因此尝试使用第二个。

测试

首先要验证开源库是否可以正常工作,需要追求效率,因此尝试创建空白工程验证。

Unity 导出 Eclipse 工程

由于 macOS 10.14.6 不支持 Unity 5.3.8f2,需要先用 Windows 7 新建空白 Unity 工程导出 Eclipse 工程。

转换 Eclipse 工程为 Gradle 工程

导出的 Android 工程转换为 Gradle 工程

  • 使用 Unity 2018.4 导出的 build.gradle 文件
  • src 目录下的内容放到 src/main 目录下
  • src/main/com 放到 src/main/java 目录下
  • assets 移动到 src/main 目录下
  • res 移动到 src/main 目录下
  • libs/armabi-v7alibs/x86 移动到 src/main/jniLibs 目录下

使用 Eclipse 导出时会输出具体的目录对应关系,可以发现与上面总结的相同。其实不用 Eclipse 导出,手工按上述映射处理也是一样的效果。

0、Eclipse -> AndroidStudio
我们先来看看从Eclipse工程到AndroidStudio工程,在结构上有哪些变化,下图为AndroidStudio工程自动生成的导入摘要。

这篇文章使用的环境也是 Unity 5.3,其中在上面引用文字下方有一张截图显示了 Eclipse 工程导出为 Gradle 工程时的映射关系。

将工程打包到 Android 11 真机上,在这一步要保证工程可以正常编译运行。

集成 NotchTools

由于这是一个空工程,因此非常容易集成第三方库,将 NotchTools 源代码直接放在工程内,然后加入调用代码调试运行。运行后报错:

1
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.test.TestAndroidDisplayCutout/com.test.displaycutout.UnityPlayerActivity}: java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams

替换 RelativeLayoutFrameLayout,因此最终正确的调用代码如下:

1
2
3
4
5
6
7
8
9
NotchTools.getFullScreenTools().fullScreenUseStatus(this, new OnNotchCallBack() {
   @Override
   public void onNotchPropertyCallback(NotchProperty notchProperty) {
      int marginTop = notchProperty.getMarginTop();
      FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mUnityPlayer.getLayoutParams();
      layoutParams.topMargin += marginTop;
      mUnityPlayer.setLayoutParams(layoutParams);
   }
});

最终解决掉所有问题后,可以正确将游戏画面显示在刘海屏区域。

集成

编译 jar

使用 Android Studio 打开 NotchTools 工程,执行 Gradle | NotchTools | notchtools | Tasks | other | createFullJarRelease

在以下目录中找到生成的 jar 文件

notchtools/build/intermediates/intermediate-jars/release/full.jar

使用

将上一步生成的 jar 文件放到 Plugins/Android/libs 目录中,将调用适配的代码加入到 Activity 的 onCreate 方法中即可。

其他

targetSdkVersion 设为 24 可以修复 Android 11 运行游戏后提示是为旧版本 Android 打造提示框问题。