虚幻4中,android第三方类库的接入

虚幻4中安卓sdk的接入, 可以使用 APL (Android Programming Language) 进行第三方库的接入,首先创建一个NAME_APL.XML 文件,该文件包括了库文件的拷贝、权限的写入、activity java文件的修改和添加等一系列android打包和接口修改的内容。不再需要手动去修改代码或者Java层的文件和代码调用接口。

1.创建一个插件并在插件Source目录下创建一个NAME_APL.XML文件,在该插件模块Name.Build.cs文件中调用如下:

public class PluginModuleName : ModuleRules
{
  public PluginModuleNamePluginModuleName(TargetInfo Target)
  {
    // Additional Frameworks and Libraries for Android
    if (Target.Platform == UnrealTargetPlatform.Android)
    {
        PrivateDependencyModuleNames.AddRange(new string[] { "Launch" });
        string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, BuildConfiguration.RelativeEnginePath);
        AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(PluginPath, "NAME_APL.XML")));
    }
  }
}

2.项目中加载该模块

包含头文件目录, 把插件Type改成Runtime(这个貌似很关键,之前没注意)
PublicIncludePaths.AddRange(
       new string[] {
           "PluginModuleName/Public",
       }
    );

PrivateIncludePaths.AddRange(
        new string[] {
           "PluginModuleName/Private",
        }
    );
PublicDependencyModuleNames.AddRange(new string[] { "PluginModuleName" });
PrivateIncludePathModuleNames.AddRange(new string[] { "PluginModuleName" });

3.APL_AML中文件结构说明

(1). proguardAdditions,代码混淆
<proguardAdditions>
<insert>
  ########################################################################################## sdkname
  -dontwarn com.sdkname.**
  -keep class com.sdkname.** {*;}
</insert>
</proguardAdditions>
(2). prebuildCopies,目录文件拷贝
<prebuildCopies>
<copyDir src="$S(PluginDir)/../../Libs"
        dst="$S(BuildDir)" />
</prebuildCopies>
(3). gameActivityImportAdditions,引用插入
<gameActivityImportAdditions>
<insert>
  import com.sdkname.*;
  import com.sdkname.name.*;
</insert>
</gameActivityImportAdditions>
(4). gameActivityClassAdditions, 成员变量, 函数插入
<gameActivityClassAdditions>
  <insert>
  private AmazonIapManager AmazonManager;
  public void AndroidThunkJava_IapSetupServiceAmazon()
  {
    Log.debug("[JAVA] - AndroidThunkJava_IapSetupServiceAmazon");
    AmazonManager = new AmazonIapManager(this);
    final AmazonPurchasingListener amazonPurchasingListener = new AmazonPurchasingListener(AmazonManager);
    PurchasingService.registerListener(this.getApplicationContext(), amazonPurchasingListener);
    if( AmazonManager == null )
    {
        Log.debug("[JAVA] - Amazon Manager is invalid");
    }
  }
  </insert>
</gameActivityClassAdditions>
(5). gameActivity[funname]Additions, 在函数中出入内容
<gameActivityOnPauseAdditions>
  <insert>
    if(gvrLayout != null)
    {
      gvrLayout.onPause();
    }
  </insert>
</gameActivityOnPauseAdditions>
(6). resourceCopies, 文件拷贝,指定源和目标
<resourceCopies>
  <log text="Copying GoogleVR runtime files to staging" />
  <isArch arch="armeabi-v7a">
    <copyFile src="$S(EngineDir)/Source/ThirdParty/GoogleVR/lib/android_arm/libgvr.so"
          dst="$S(BuildDir)/libs/armeabi-v7a/libgvr.so" />
</resourceCopies>
(7).androidManifestUpdates修改AndroidManifest.xml文件
<androidManifestUpdates>
<!-- Add features -->
<addFeature android:name="android.hardware.sensor.accelerometer" android:required="true" />
<if condition="bSupportDaydream">
  <true>
    <addFeature android:name="android.hardware.vr.high_performance" android:required="true" />
  </true>
  <false>
    <addFeature android:name="android.hardware.vr.high_performance" android:required="false" />
  </false>
</if>

<!-- Add intents -->
<loopElements tag="activity">
  <setStringFromAttribute result="activityName" tag="$" name="android:name" />
  <setBoolIsEqual result="bGameActivity" arg1="$S(activityName)" arg2="com.epicgames.ue4.GameActivity" />
  <if condition="bGameActivity">
    <true>
      <!-- Check for existing intent filter -->
      <setBool result="bHasIntentFilter" value="false" />
      <loopElements tag="intent-filter">
        <setBool result="bHasIntentFilter" value="true" />
      </loopElements>

      <!-- If no intent filter found, add a new one -->
      <if condition="bHasIntentFilter">
        <false>
          <setElement result="newIntentFilter" value="intent-filter" />
          <addElement tag="$" name="newIntentFilter" />
        </false>
      </if>
    </true>
  </if>
</loopElements>
</androidManifestUpdates>
(7). soLoadLibrary, 在GameActivity.java中指定so库先于libUE4.so加载
<soLoadLibrary>
  <loadLibrary name="gvr" failmsg="GoogleVR library not loaded and required!" />
</soLoadLibrary>

4.虚幻4中jni的接口调用


if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
{
  // Populate some java types with the provided product information
  jobjectArray ProductIDArray = (jobjectArray)Env->NewObjectArray(ProductIds.Num(), FJavaWrapper::JavaStringClass, NULL);
  jbooleanArray ConsumeArray = (jbooleanArray)Env->NewBooleanArray(ProductIds.Num());

  jboolean* ConsumeArrayValues = Env->GetBooleanArrayElements(ConsumeArray, 0);
  for (uint32 Param = 0; Param < ProductIds.Num(); Param++)
  {
    jstring StringValue = Env->NewStringUTF(TCHAR_TO_UTF8(*ProductIds[Param]));
    Env->SetObjectArrayElement(ProductIDArray, Param, StringValue);
    Env->DeleteLocalRef(StringValue);

    ConsumeArrayValues[Param] = IsConsumableFlags[Param];
  }
  Env->ReleaseBooleanArrayElements(ConsumeArray, ConsumeArrayValues, 0);

  static jmethodID Method = FJavaWrapper::FindMethod(Env, FJavaWrapper::GameActivityClassID, "AndroidThunkJava_IapQueryInAppPurchasesAmazon", "([Ljava/lang/String;[Z)Z", false);
  FJavaWrapper::CallBooleanMethod(Env, FJavaWrapper::GameActivityThis, Method, ProductIDArray, ConsumeArray);

  // clean up references
  Env->DeleteLocalRef(ProductIDArray);
  Env->DeleteLocalRef(ConsumeArray);
}

5.虚幻4代码如果需要调用jni, 则必须包含模块 “Launch”

if (Target.Platform == UnrealTargetPlatform.Android)
{
    PrivateDependencyModuleNames.AddRange(new string[] { "Launch" });
}

暂时理解到虚幻4的sdk接入流程和内容基本如上。


猜你喜欢

转载自blog.csdn.net/or7rccl/article/details/72899036