Android导出Activity到AAR包供Unity使用

想在 Unity 中显示 Android 界面,但又不想导出 Unity 工程在 Android Studio 里编辑,于是探索将 Activity 导出到 AAR 包,用 Unity 编译打包的方法。
说明
本文介绍了通过 Unity Editor 打包含 Android Activity 在内的多 Activity 应用的方法,至于多 Activity 的使用因人而异,仅简单探讨,后续在其他文章详细讨论。
一般情况下,Unity 应用对其他 Activity 有两种用途:
- Activity 画面渲在一张纹理上,在 Unity 3D 场景内显示为一个片;
- 直接跳转 Activity,退出 Unity Activity。
前者够写好几篇文章的,而后者简单到根本不用写,因此本文不会探讨具体用法。
所以,让我们开始吧~
准备额外的 Activity
在 Android Studio 中创建一个 Module:
在 Module 中创建一个 Activity,按需拼好界面,写好 Activity 逻辑:
用于 Unity C# 层的拉起 Activity 方法
这里只提供拉起 Activity 的 Intent 构建方法。
public void unityCallStartActivity(){
Intent intent = new Intent(this.unityActivity, testActivity.class);
/*
在 VirtualDisplay 上展示
ActivityOptions activityOptions = ActivityOptions.makeBasic();
activityOptions.setLaunchDisplayId(this.targetVirtualDisplayId);
this.unityActivity.startActivity(intent, options.toBundle());
*/
this.unityActivity.startActivity(intent);
}
至于如何在 Unity 里调用上述 Java Android 方法,应该没人不会,略。
给 Activity 添加 Theme
上文创建的 Activity 没有默认 Theme,Unity 里拉起 Activity 时会报错。
我们需要在AndroidManifest.xml
里给 Activity 添加一个 Theme:
<activity
android:theme="@style/Theme.AppCompat.DayNight.NoActionBar"
android:name=".testActivity"
android:exported="false" />
本处仅为示例,具体 Theme 和需求有关:例如是不是需要 ActionBar 等。
导出 AAR 包
选中当前 Module,在 Android Studio 菜单栏选择Build/Make Module
:
稍等片刻,可以看到生成的 aar 包:
Unity 打包配置修改
Unity 本质也是 Gradle 打包,只不过把大部分可配置项都隐藏了。
Player Setting 中勾选如下两项:
Custom Launcher Gradle Template
Custom Gradle Properties Template
勾选后,Unity 将把默认的 Gradle 配置文件拷贝到Plugins/Android
中供你修改:
1. 开启 AndroidX 支持
在gradleTemplate.properties
中添加:
android.useAndroidX=true
android.enableJetifier=true
改完记得保存。
2. 添加 module 依赖
我们需要在launcherTemplate.gradle
中加入 Module 的依赖包。
上文打包的 AAR 的不包含 dependencies,有人认为这是坏事,会用各种 bypass 手段让 AAR 打入依赖的包,我不推荐这么做。模块不包含依赖包是好事:如果多个 AAR 都依赖同一个包,且各自都包含一份该依赖,打包会冲突的。
通常把 Module 文件夹中build.gradle
文件内dependencies
下的implementation
拷贝过来即可:
# 一个例子,不要直接拷贝本文
implementation 'androidx.appcompat:appcompat:xxx'
implementation 'com.google.android.material:material:xxx'
implementation 'androidx.constraintlayout:constraintlayout:xxx'
当然,这里有坑,后面疑难解答里会详细说。
3. 拷贝 AAR
将上文中生成的 AAR 文件放置在Plugins/Android
中。
打包
现在就可以去打包了(大概率打包会报错,见后文疑难解答)。
如果得法,你将通过 Unity Editor 附带的编译工具打出一个多 Activity 应用出来,比如我这个:
至于如何使用其他的 Activity,就看个人需求了,不过使用范围应该都在前文提到的“两种用法”范围内。
疑难解答
问题1:打包报错 uses-sdk:minSdkVersion xx cannot be smaller than version xx declared in library
我们的 Module 有MinSdkVersion
与TargetSdkVersion
设置,可以在module settings
中管理:
这个报错是因为 Unity 的Minimum API Level
低于 module 的MinSdkVersion
,此时有两种解决方法:
- 降低 module 的
MinSdkVersion
,重新出 aar 包; - 提高 Unity 的
Minimum API Level
。
问题2:打包报错 AAPT: error: resource android:attr/lStar not found.
这就是上文提到的坑点。
Android 这边对compileSdkVersion
与TargetVersion
是有区分的:
compileSdkVersion
是应用编译时需要的 SDK 版本;TargetVersion
是应用运行时的版本。
一个库如果即兼容低版本又适配高版本的新特性,则需要用高版本编译,原则上compileSdkVersion
>= TargetVersion
即可。
Unity 把Target API Level
作为打包的compileSdkVersion
,一般来说,这种做法是没问题的。
但是,当你的Target API Level
比 dependencies 的compileSdkVersion
低时,就出问题了。
以本问题为例,编译时的依赖顺序:
- 当 appcompat 版本较高时编译
- ↑ 编译依赖新版的 AndroidX 组件
- ↑ 编译依赖 android:attr/lStar,Android 12 才有
- ↑ 要求 compileSdkVersion ≥ 31
- ↑ 编译依赖 android:attr/lStar,Android 12 才有
- ↑ 编译依赖新版的 AndroidX 组件
对这个问题有两种解决方法(以及一种和本文无关的方法):
- 提高 Unity
Target API Level
到 API 31,同时保持minimum API Level
不变(兼容低版本设备); - 使用低版本的 dependencies 包。
- (非本文情况)导出工程,用 Android Studio 修改
compileSdkVersion
后打包。
如果不想修改Target API Level
到 Android 12,执意使用低版本的 dependencies,下面的版本是一个推荐值:
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
至于其他包的依赖关系,可以在 https://mvnrepository.com/ 里查看。