AndroidStudio3.4+Unity2018.3,導出JAR包給UNITY使用


環境 Android studio 3.4 + unity2018.3

1,android studio 新建空工程,一切默認,完成。
這個空工程只是個殼,它的所有參數都沒什么用,它存在的意義是為了后面能創建 module。
因為JAVA不像C++,可以直接創建類庫。
2,新建模塊
file->new module->android library
application name 和 module name 都不重要,沒有實際用處(這里取名mylibrary),重要的是包名: package name。
這里取名為 com.x.y
包名用到哪些地方?
(1,AndroidManifest.xml里的 package
(2,每個java文件的開始處,形如 package com.x.y,表示此java文件被放入了工程的com/x/y目錄下
(3,unity 的build Settings里的 package name

這三處必須使用同一個包名,如果不一致則啟動時閃退。如果想修改包名,就要修改這三處就行了。

3,在mylibrary模塊下的src/java/com.x.y/添加java文件,隨便取名,就叫MainActivity吧
修改其源碼如下:

 

package com.x.y;

import android.content.Intent;
import com.unity3d.player.UnityPlayerActivity;
import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends UnityPlayerActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        activity = this;
    }

    //public  static  MainActivity activity;
    public static MainActivity activity;
    public int Calc(int x, int y){
        return  x + y;
    }

    public static float Calcf(float x, float y){
        return  x + y;
    }

    public void restartApplication() {
        new Thread(){
            public void run(){
                Intent launch=getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
                launch.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(launch);
                android.os.Process.killProcess(android.os.Process.myPid());
            }
        }.start();

        finish();
    }
}

 

這個類的目的:
(1,測試普通成員函數和靜態函數的調用
(2,測試重啟功能

4,修改mylibary模塊的AndroidManifest.xml,這一步放在最后也行,此文件是拿給UNITY用的,內容如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.x.y">

<application android:allowBackup="true" android:label="@string/app_name">
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
  <action android:name="android.intent.action.MAIN"/>
  <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>

 

注意一定要有下面兩行
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
學過安卓開發的都知道這是標記此活動是主活動,沒有主活動的應用是不會被運行的。
默認情況下UNITY會創建自己AndroidManifest.xml,一旦我們在Assets/Plugins/Android/下放置了我們自定的AndroidManifest.xml,
UNITY就以我們的配置為主,並將buildsettings里的相關配置合並進來,如安裝位置,持久化路徑等。
因此,如果我們生成了自己的AndroidManifest.xml,卻又不配置為主活動,安裝后桌面沒有圖標,因為它不是一個可執行程序

5,修改mylibrary模塊的 build.gradle(注意不是修改工程的),為編譯做准備,在末尾添加:

task exportJar(type: Copy) {
//必須先刪除舊的包,否則新包不會生成,這個目錄對應mylibrary/build/libs/AndroidUtils.jar
delete 'build/libs/AndroidUtils.jar'

//生成的目錄在這里
from('build/intermediates/packaged-classes/release/')

//生成build/libs目錄,並將build/intermediates/packaged-classes/release/下的classes.jar復制到此目錄
into('build/libs/')

//指定我們只在build/intermediates/packaged-classes/release/下尋找classes.jar(放入到build/libs/目錄
include('classes.jar')

//重命名下,起個個性的名字,不要與別人混淆
rename('classes.jar', 'AndroidUtils.jar')
}

//這里會觸發真正對mylibaray的編譯
exportJar.dependsOn(build)

 

然后點擊工具欄上的 run anything: ,或雙擊ctrl,在彈出的輸入窗口中輸入 gradlew exprotJar,回車,等待編譯完成。
如果沒問題,會提示 BUILD SUCCESSFUL
如果出了錯,仔細看前面的輸出LOG。

這里的注意點:
(1,from('build/intermediates/packaged-classes/release/') 這里的路徑在不同版本的 Android Studio中不同。
在低版本的AS中路徑為 build/intermediates/bundles/release
如果編譯中報錯 exportJar: NO-SOURCE,就說明是此路徑錯誤了,這時就去磁盤上的build/intermediates/目錄搜索classes.jar文件,
找到它的路徑,寫入到from里就對了。

6,生成完成后,得到我們的AndroidUtils.jar包,新建UNITY工程,package name取名:com.x.y

在Assets下新建如下目錄 Plugins/Android,然后將AndroidManifest.xml放入到此目錄下,然后在創建 Plugins/Android/libs目錄,
將AndroidUtils.jar放入此目錄。
注意這里的目錄結構要求:AndroidManifest.xml必須與libs同目錄,AndroidUtils.jar必須在libs目錄中,名字不能錯。
但libs和XML不一定直接在Android下,可以是多層目錄下,如:Android/abc/libs也可以

7,添加腳本,隨便掛在什么上,如相機上,測試代碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class calljava : MonoBehaviour
{
    AndroidJavaObject jo;
    Text info;

    void Start()
    {
        //方式一,使用基類,這種比較通用
        var jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        info = GameObject.Find("TextInfo").GetComponent<Text>();
        info.text += "start \n";

        //方式二,使用具體類,不通用,當類名改了就要改這里的字符串
        //var jc = new AndroidJavaClass("com.example.mylibraryx.MainActivity");
        //jo = jc.GetStatic<AndroidJavaObject>("activity");

        info.text += "get java object " + (jo == null ? "null\n" : "ok\n");

        //var btn = GetComponent<Button>();
        //btn.onClick.AddListener(() =>
        //{
            if (jo != null)
            {
                //注意1,參數類型必須傳對,否則運行到這里就出錯了
                var ret = jo.Call<int>("Calc", 10, 20);
                info.text += "call ret : " + ret + " \n";

                //調用靜態函數
                var retf = jo.CallStatic<float>("Calcf", (float)10.2, (float)20.2);
                info.text += "call retf : " + retf + " \n";


                //注意2,由於Calcf是個靜態函數,非靜態調用會造成參數錯位,結果為retfx = 10.2
                var retfx = jo.Call<float>("Calcf", (float)10.2, (float)20.2);
                info.text += "call retfx : " + retfx + " \n";

            }

        //});
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

8,打包APK,到安卓上運行。在UNITY上運行會出錯,提示jo為空.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM