Android sdk工程搭建(aar)

Android sdk工程搭建(aar)

Unity 和 Android 交互流程

AndroidJavaClass:

  • public AndroidJavaClass(string className); // className:指定类名
  • java.lang.Class的通用实例的统一表示,是java里的类。

AndroidJavaObject:

  • 生成一个对象,通过对象去调用里面的方法和属性
// 加载 com.unity3d.player.UnityPlayer 类 
AndroidJavaClass ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
// 调用 com.unity3d.player.UnityPlayer 类中的 静态方法
ajc.CallStatic("Test");
ajc.CallStatic("Test","Hello"); // 带参数的静态方法
int sum = ajc.CallStatic<int>("Sum", 1, 2); // 带参数和返回值的静态方法

// 实例化 com.unity3d.player.UnityPlayer 对象
AndroidJavaObject ajo = new AndroidJavaObject("com.unity3d.player.UnityPlayer");
// 调用 com.unity3d.player.UnityPlayer 类中的 实例方法
ajo.Call("Test");
ajo.Call("Test","Hello");
int sum = ajo.Call<int>("Sum", 1, 2);

classes.jar

Unity发布AndroidAPK时,会使用AndroidSDK构建,发布出来的APK只包含一个Activity,俗称MainActivity。在发布过程中,Unity会引入内置的Jar库(classes.jar),里面包含了Unity需要的库类,关键类UnityPlayerActivity就是Android程序的主要入口类,也就是MainActivity

aar 和 jar的区别

  • jar:只包含了class文件与清单文件,不包含资源文件,如图片等所有res中的文件
  • aar:包含所有资源,class以及res资源文件。

AndroidManifest

Unity发布Android的APK时,如果在Plugins/Android目录下不存在AndroidManifest文件,会使用Unity默认的AndroidManifest文件。

默认的AndroidManifest文件目录:Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Apk

如果存在AndroidManifest文件,Unity会使用它代替默认的AndroidManifest文件,这个AndroidManifest文件必须带有活动以及标签

<meta-data android:name="unityplayer.UnityActivity" android:value="true"/>

发布APK的两种方式

  • Internal:不需要签名,仅需Android SDK支持,不能导出工程。
  • Gradle:需要签名,需要Android SDKGradle 支持,可以导出Android Studio工程,使用与需要与Android功能交互的项目。

Unity接入SDK两种方法

  • Unity在安卓平台选中Gradle打包出来,然后在Android Studio导入需要的SDK进行操作。
  • Unityclasses.jar包和需要的SDK导入Android Studio新建的Library中,然后导出jar或者aar放到Unity中调用。

具体操作流程

  • 创建一个Android Studio项目,视图切换到Project

  • 首先修改 app - build.gradle 文件。

  • 将第一行,application 改为 library,这样就可以发布aar

  • 删掉 applicationId 那一行

// apply plugin: 'com.android.application'
apply plugin: 'com.android.library'	// 不生成apk,生成aar包。

android {
    
    
    compileSdkVersion 28	// sdk版本
    buildToolsVersion "30.0.3"
    defaultConfig {
    
    
    	// applicationId "com.td.sdktest"  注释这一行
        minSdkVersion 15	// 最低sdk版本
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
    
    
        release {
    
    
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    
    
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation files('libs/classes.jar') //添加unity classes.jar 添加依赖自动生成
}
  • 点击工具栏 - Build - MakeProject 测试是否可以发布aar包。

  • 完成之后,可以看到在 app - build - outputs - aar 文件夹下已经生成app-debug.aar

  • 复制Unityclasses.jarAndroidStudio

    UnityAndroid没法直接通信,需要classes.jar搭桥牵线。classes.jarUnity提供。

    Unity 安装目录下的 classes.jar 复制到 Android 项目的 libs 文件夹下,右键点击Add As Library添加依赖。implementation files('libs/classes.jar')

    目录:Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes

  • 修改MainActivity.java以便unity调用

package com.example.unityaar;

import android.os.Bundle;
import android.widget.Toast;
import java.text.SimpleDateFormat;
// 复制过来的 unity_classes.jar
import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

// 修改类 继承 UnityPlayerActivity
public class MainActivity extends UnityPlayerActivity {
    
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        // setContentView(R.layout.activity_main)	// 注释掉,不需要界面
    }

    // 写交互函数

    // 供unity调用的普通函数,弹toast
    public void ShowAndroidToast(String str){
    
    
        Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
    }

    // unity调用的静态方法,然后再调用unity函数
    // UnityPlayer.UnitySendMessage(String,String,params)
    // 参数1:unity中一个GameObject名字。参数2:改GameObject脚本中的一个方法。参数3:改方法参数
    public static void GetSystemTime(){
    
    
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String timeStr = sDateFormat.format(new java.util.Date());
        UnityPlayer.UnitySendMessage("Canvas","GetDate", timeStr);
    }

    // 供unity调用的普通方法,带返回值
    public String GetDate(){
    
    
        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String timeStr = sDateFormat.format(new java.util.Date());
        return timeStr;
    }
}
  • 不需要Android界面,删除 app - src - main - res - layout 文件夹

  • 不需要Android界面,删除 app - src - main - res - values - styles.xml 文件

  • 修改AndroidManife文件

    • android:theme修改成安卓自带的主题@android:style/Theme.NoTitleBar
    • android:name="com.example.unityaar.MainActivity"
    • 再添加<meta-data android:name="unityplayer.UnityActivity" android:value="true"/>,否则发布的apk是无法运行的
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.unityaar">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@android:style/Theme.NoTitleBar">
            <activity android:name="com.example.unityaar.MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true"/>
        </application>
    
    </manifest>
    
  • Build - Make Project,生成新的aar

  • Android导出的aarAndroidManifest 复制到unity项目Plugins/Android目录下。

    • 删除aar压缩包lib文件下的unity_classes.jar,否则会有冲突,打包不成功
  • 编写Unity脚本,调用Android接口。

    using UnityEngine;
    using UnityEngine.UI;
    
    public class UnityAndroidAar : MonoBehaviour {
    
        public Text timeTxt;
        public InputField inputField;
        public Text timeBtnStr;
    
        private AndroidJavaClass javaClass;
        private AndroidJavaObject javaObject;
    
        private void Start()
        {
            // 获取 Unity 导出的 Activity 对象,固定写法,UnityPlayerActivity 里面对其进行了处理
            javaClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");     // Unity 要导出的 MainActivity 类
            javaObject = javaClass.GetStatic<AndroidJavaObject>("currentActivity"); // 获取 MainActivity 的实例对象
        }
    
        private void Update()
        {
            // 调用 Java 类中的普通方法
            javaObject.CallStatic("GetSystemTime");
        }
    
        // Android 调用 unity 方法
        public void GetDate(string timeStr) {
            timeTxt.text = timeStr;
        }
    
        public void OnClickGetTimeBtn() {
            // 调用 Java 类中的普通方法 ,带返回值
            timeBtnStr.text = javaObject.Call<string>("GetDate");
        }
    
        public void OnClickThostBtn() {
            // 调用 Java 类中的普通方法,带参数,不带返回值
            string inputValue = inputField.text;
            javaObject.Call("ShowAndroidToast",inputValue);
        }
    }
    
  • 打包发布APKunity切换到Android平台。Build 。安装APK,运行游戏检测。

遇到的坑:

  • 直接运行Unity,报错。

解决:需要运行在安卓真机设备上。如果需要调试:

#if UNITY_ANDROID && !UNITY_EDITOR
    // 报错的调用代码写这里
#endif
  • 打包报错:

解决:与unity中的classes.jar冲突,打开aar包,删除lib文件夹下的classe.jar文件,重新导入unity

  • 当导出apk时,可能遇到下面的问题:
    Unable to find unity activity in manifest. You need to make sure orientation attribute is set to fullSensor manually.
    需在AndroidManifest中, 主 Activity的之前增加一行:

    <meta-data android:name="unityplayer.UnityActivity" android:value="true" />

猜你喜欢

转载自blog.csdn.net/wang_lvril/article/details/126419881