更新日期:2025年 12月 04日Unreal Engine(Android)接入文档
<h4>
<span style="font-size:14px;">1. 环境及工具配置</span>
</h4>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<span style="font-size:14px;">MasOS 15.7.1(arm64)</span><br />
<span style="font-size:14px;">UnrealEditor 5.5.4</span><br />
<span style="font-size:14px;">JetBrains Rider 2025.3</span><br />
<span style="font-size:14px;">Xcdeo 16.0</span><br />
<span style="font-size:14px;">JDK 17</span><br />
<span style="font-size:14px;">Visual Studio Code 1.106.1 (Universal)</span><br />
<span style="font-size:14px;">Android Studio Flamingo | 2022.2.1 Patch 2</span><br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">Gradle 及 Android SDK 均为Android Studio创建项目后的默认版本</span>
</p>
<p>
<span style="font-size:14px;color:#E53333;">建议:上述工具及环境配置或安装时一律使用其推荐的默认路径</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<br />
<h4>
<span style="font-size:14px;">2. 修改默认Application及SplashActivity</span>
</h4>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<span style="font-size:14px;">虚幻引擎UnrealEditor在生成Android项目时,会从引擎源代码项目内copy一份默认标准安卓项目源码(含默认Application GameActivity Mainfest build.gradle ..等),由于Unreal的UPL模式只能往Application和manifest内插入代码,而不能改变其继承关系,所以我们需要找到这份默认文件并替换部分内容</span><br />
<br />
<p>
<span style="font-size:14px;">方式1:</span>
</p>
<p>
<span style="font-size:14px;">找到当前UnrealEditor默认安装目录:</span>
</p>
<p>
<span style="font-size:14px;">/Users/Shared/Epic Games/UE_5.5/Engine/Build/Android/Java/src/com/epicgames/unreal</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<span style="font-size:14px;">方式2:</span><br />
<p>
<span style="font-size:14px;">使用Rider或者VScode 打开UnrealEditor对应的项目,选择文件系统展示项目目录层级:</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"><img src="https://staticsite.quickapi.net/data/newFiles/20251204/20251204164304NKTh934.png" alt="" /><br />
</span>
</p>
<br />
<span style="font-size:14px;">通过上述方式找到源码路径之后,先把本地原有的这2个文件复制一份保存到其余目录(防止以后非QuickSDK项目接入使用出错),然后从下面链接下载并替换进去:</span><br />
<p>
<span style="font-size:14px;">GameApplication.java.template:https://ai.feishu.cn/wiki/R3JGw0Ji9iosOlkcogncs4eenRh</span>
</p>
<p>
<span style="font-size:14px;">SplashActivity.java:https://ai.feishu.cn/wiki/HAdvwY2x9ipbyVkzmJ8cNaN4nRe</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<br />
<h4>
<span style="font-size:14px;">3. 创建Android插件并导入资源</span>
</h4>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"><img src="https://staticsite.quickapi.net/data/newFiles/20251204/202512041645589xxR799.png" alt="" /><br />
</span>
</p>
<br />
<span style="font-size:14px;color:#E53333;">插件创建完成后,在根目录下创建Android文件夹,并把QuickSDK JAVA对接资源内的jar(对应libs) 、so(对应jinLibs)、 res等资源放入其内</span><br />
<br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<h4>
<span style="font-size:14px;">4. 创建UPL文件</span>
</h4>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">下载QuickSDK_UPL.xml<u style="white-space:normal;font-size:14px;"><a href="https://ai.feishu.cn/wiki/ZAgvwXYUeim5n9kCEYjc9mkYnme" target="_blank"> </a></u>文件:https://ai.feishu.cn/wiki/ZAgvwXYUeim5n9kCEYjc9mkYnme</span>
</p>
<p>
<br />
</p>
<p>
<br />
</p>
<p>
<span style="font-size:14px;">4.1 注册插入gradle配置</span>
</p>
<p>
<br />
</p>
<pre class="brush:js;toolbar:false"> <gradleProperties>
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
}
</gradleProperties></pre>
<p>
<br />
</p>
<p>
<br />
</p>
<p>
<span style="font-size:14px;">4.2 注册插入SDK资源依赖</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<pre class="brush:js;toolbar:false"><resourceCopies>
<!-- 拷贝 JAR 文件 -->
<copyFile src="$S(PluginDir)/Android/libs/quicksdk274.jar"
dst="$S(BuildDir)/libs/quicksdk274.jar" />
<!-- 拷贝资源文件 -->
<copyDir src="$S(PluginDir)/Android/res"
dst="$S(BuildDir)/res" />
<copyDir src="$S(PluginDir)/Android/jniLibs/arm64-v8a"
dst="$S(BuildDir)/libs/arm64-v8a" />
<copyDir src="$S(PluginDir)/Android/jniLibs/armeabi-v7a"
dst="$S(BuildDir)/libs/armeabi-v7a" />
</resourceCopies></pre>
<br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">4.3 GameActivity Import</span>
</p>
<br />
<pre class="brush:js;toolbar:false"> <gameActivityImportAdditions>
<insert>
import com.quicksdk.BaseCallBack;
import com.quicksdk.Extend;
import com.quicksdk.FuncType;
import com.quicksdk.QuickSDK;
import com.quicksdk.Sdk;
import com.quicksdk.User;
import com.quicksdk.entity.GameRoleInfo;
import com.quicksdk.entity.OrderInfo;
import com.quicksdk.entity.UserInfo;
import com.quicksdk.notifier.ExitNotifier;
import com.quicksdk.notifier.InitNotifier;
import com.quicksdk.notifier.LoginNotifier;
import com.quicksdk.notifier.LogoutNotifier;
import com.quicksdk.notifier.PayNotifier;
import com.quicksdk.notifier.SwitchAccountNotifier;
import com.quicksdk.utility.AppConfig;
import org.json.JSONObject;
import android.util.Log;
</insert>
</gameActivityImportAdditions></pre>
<br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">4.4 插入sdk生命周期函数</span>
</p>
<br />
<pre class="brush:js;toolbar:false"> <gameActivityOnStartAdditions>
<insert>
// 在这里添加 onStart 方法的代码
com.quicksdk.Sdk.getInstance().onStart(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnStartAdditions>
<gameActivityOnStopAdditions>
<insert>
com.quicksdk.Sdk.getInstance().onStop(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnStopAdditions>
<gameActivityOnDestroyAdditions>
<insert>
com.quicksdk.Sdk.getInstance().onDestroy(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnDestroyAdditions>
<gameActivityOnRestartAdditions>
<insert>
com.quicksdk.Sdk.getInstance().onRestart(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnRestartAdditions>
<gameActivityOnResumeAdditions>
<insert>
com.quicksdk.Sdk.getInstance().onResume(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnResumeAdditions>
<gameActivityOnPauseAdditions>
<insert>
com.quicksdk.Sdk.getInstance().onPause(com.epicgames.unreal.GameActivity.this);
</insert>
</gameActivityOnPauseAdditions>
<gameActivityOnCreateAdditions>
<insert>
// 在这里添加 onCreate 方法的代码
com.quicksdk.Sdk.getInstance().onCreate(com.epicgames.unreal.GameActivity.this);
initNotifier();
</insert>
</gameActivityOnCreateAdditions>
<gameActivityOnNewIntentAdditions>
<insert>
// 在这里添加 onCreate 方法的代码
com.quicksdk.Sdk.getInstance().onNewIntent(newIntent);
</insert>
</gameActivityOnNewIntentAdditions>
<gameActivityOnActivityResultAdditions>
<insert>
// 在这里添加 onCreate 方法的代码 com.quicksdk.Sdk.getInstance().onActivityResult(com.epicgames.unreal.GameActivity.this, requestCode, resultCode, data);
</insert>
</gameActivityOnActivityResultAdditions></pre>
<br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">4.5 插入SDK(<span style="white-space:normal;font-size:14px;">必接接口</span>)</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;color:#E53333;">SDK必接接口包含初始化 登陆 支付 注销 角色投递 退出 等接口 以及注册对应的回调</span>
</p>
<p>
<span style="font-size:14px;">详细接口及回调逻辑 参照<a href="https://www.quicksdk.com/doc-13.html" target="_blank">QuickSDK JAVA 对接文档</a>,这里不过多赘述</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"> </span>
</p>
<pre class="brush:js;toolbar:false"><gameActivityClassAdditions>
<insert>
/**
* 暂定处理各种回调 JAVA==>C++
* @param msg json 类型 String
*/
public native void onMessageToUnreal( String msg);
/**
* 隐私协议窗口
*/
public void showPrivace(){
com.epicgames.unreal.GameActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Sdk.getInstance().showPrivace( com.epicgames.unreal.GameActivity.this, new BaseCallBack() {
@Override
public void onSuccess(Object... objects) {
try{
JSONObject data=new JSONObject();
data.put("event","privaceAgree");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util. Log.e("quicksdk","showPrivace ex: "+e.toString());
}
}
@Override
public void onFailed(Object... objects) {
try{
JSONObject data=new JSONObject();
data.put("event","privaceDisagree");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util. Log.e("quicksdk","showPrivace dis ex: "+e.toString());
}
}
});
}
});
}
/**
* 初始化
*/
public void init() {
com.epicgames.unreal.GameActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Sdk.getInstance().init(com.epicgames.unreal.GameActivity.this,"88049844578484520615487574815873","82414864");
}
});
}
/**
* 登录
*/
public void login() {
com.epicgames.unreal.GameActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
User.getInstance().login(com.epicgames.unreal.GameActivity.this);
}
});
}
/**
* 注销
*/
public void logout() {
com.epicgames.unreal.GameActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
User.getInstance().logout(com.epicgames.unreal.GameActivity.this);
}
});
}
/**
* 退出
*/
public void exit() {
com.epicgames.unreal.GameActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if (QuickSDK.getInstance().isShowExitDialog()) {
// 游戏不能调用自身的退出对话框
Sdk.getInstance().exit(com.epicgames.unreal.GameActivity.this);
} else {
// 游戏调用自身的退出对话框,点击确定后,调用sdk的exit
Sdk.getInstance().exit(com.epicgames.unreal.GameActivity.this);
}
}
});
}
public void initNotifier() {
try{
QuickSDK.getInstance()
// 1.设置横竖屏,游戏横屏为true,游戏竖屏为false
.setIsLandScape(true)
// 3.设置初始化通知
.setInitNotifier(new InitNotifier() {
@Override
public void onSuccess() {
try{
JSONObject data=new JSONObject();
data.put("event","initSuccessed");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util. Log.e("quicksdk","init notifier ex: "+e.toString());
}
}
@Override
public void onFailed(String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","initFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util. Log.e("quicksdk","init notifier ex: "+e.toString());
}
}
})
// 4.设置登录通知
.setLoginNotifier(new LoginNotifier() {
@Override
public void onSuccess(UserInfo userInfo) {
try{
JSONObject data=new JSONObject();
data.put("event","loginSuccessed");
JSONObject extraData=new JSONObject();
extraData.put("uid",userInfo.getUID());
extraData.put("username",userInfo.getUserName());
extraData.put("token", userInfo.getToken());
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","login notifier ex: "+e.toString());
}
}
@Override
public void onCancel() {
try{
JSONObject data=new JSONObject();
data.put("event","loginCancel");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","login notifier ex: "+e.toString());
}
}
@Override
public void onFailed(final String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","loginFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","login notifier ex: "+e.toString());
}
}
})
// 5.设置注销通知
.setLogoutNotifier(new LogoutNotifier() {
@Override
public void onSuccess() {
try{
JSONObject data=new JSONObject();
data.put("event","logoutSuccessed");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","logout notifier ex: "+e.toString());
}
}
@Override
public void onFailed(String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","logoutFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","logout notifier ex: "+e.toString());
}
}
})
// 6.设置支付通知
.setPayNotifier(new PayNotifier() {
@Override
public void onSuccess(String sdkOrderID, String cpOrderID, String extrasParams) {
try{
JSONObject data=new JSONObject();
data.put("event","paySuccessed");
JSONObject extraData=new JSONObject();
extraData.put("sdkOrderId",sdkOrderID);
extraData.put("cpOrderId",cpOrderID);
extraData.put("extraParams",extrasParams);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","pay notifier ex: "+e.toString());
}
}
@Override
public void onCancel(String cpOrderID) {
try{
JSONObject data=new JSONObject();
data.put("event","payCancel");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","pay notifier ex: "+e.toString());
}
}
@Override
public void onFailed(String cpOrderID, String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","payFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","pay notifier ex: "+e.toString());
}
}
})
// 7.设置退出通知
.setExitNotifier(new ExitNotifier() {
@Override
public void onSuccess() {
finish();
System.exit(0);
}
@Override
public void onFailed(String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","exitFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","exit notifier ex: "+e.toString());
}
}
});
QuickSDK.getInstance().setSwitchAccountNotifier(new SwitchAccountNotifier() {
@Override
public void onSuccess(UserInfo userInfo) {
try{
JSONObject data=new JSONObject();
data.put("event","switchAccountSuccessed");
JSONObject extraData=new JSONObject();
extraData.put("uid",userInfo.getUID());
extraData.put("username",userInfo.getUserName());
extraData.put("token", userInfo.getToken());
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","switch notifier ex: "+e.toString());
}
}
@Override
public void onFailed(String message, String trace) {
try{
JSONObject data=new JSONObject();
data.put("event","switchAccountFailed");
JSONObject extraData=new JSONObject();
extraData.put("id",trace);
extraData.put("msg",message);
data.put("result",extraData);
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","switch notifier ex: "+e.toString());
}
}
@Override
public void onCancel() {
try{
JSONObject data=new JSONObject();
data.put("event","switchAccountCancel");
data.put("result","");
onMessageToUnreal(data.toString());
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","switch notifier ex: "+e.toString());
}
}
});
}catch (Exception e){
e.printStackTrace();
android.util.Log.e("quicksdk","initNotifier ex: "+e.toString());
}
}
</insert>
</gameActivityClassAdditions></pre>
<br />
<p>
<br />
</p>
<span style="font-size:14px;color:#E53333;">所有供Unreal C++调用的方法都必须封装在GameActivity内,如果有安卓基础可以将GameActivity.java.templete copy 进AndroidStudio 项目 然后对接QuickSDK接口,修改完成之后替换进引擎默认路径下</span><br />
<br />
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<h4>
<span style="font-size:14px;">5. 插件项目配置</span>
</h4>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;">在插件目录/XXXX.Build.cs 文件内插入</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"> </span>
</p>
<pre class="brush:js;toolbar:false">//判断平台为Android
if (Target.Platform == UnrealTargetPlatform.Android)
{
//Android/Java c++封装库
PublicDependencyModuleNames.Add("Launch");
PublicDependencyModuleNames.Add("ApplicationCore");
//配置依赖之前创建的UPL文件
AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(ModuleDirectory, "QuickSDK_UPL.xml"));
}
</pre>
<br />
<p>
<br />
</p>
<p>
<span style="font-size:14px;">在公共依赖中添加unreal官方Json库</span>
</p>
<p>
<span style="font-size:14px;"><br />
</span>
</p>
<p>
<span style="font-size:14px;"> </span>
</p>
<pre class="brush:js;toolbar:false">PublicDependencyModuleNames.AddRange(
new string[]
{
"Core","Json","JsonUtilities"
// ... add other public dependencies that you statically link with here ...
}
);</pre>
<br />
<p>
<br />
</p>
<p>
<span style="font-size:14px;">在主项目目录/XXXX.Build.cs 文件内插入对插件的依赖配置</span>
</p>
<br />
<pre class="brush:js;toolbar:false">PrivateDependencyModuleNames.AddRange(new string[] { "QuickSDK_Android"});
</pre>
<br />
<br />
<br />
<span style="font-size:14px;"></span>