【Unity3D】Unity interacts with Android

1 Introduction

        This article mainly introduces the process of Unity packaging and releasing Android apk, implementing Unity to call Java code based on AndroidJavaObject (or AndroidJavaClass), and implementing Java to call Unity code based on UnityPlayer. For the official introduction, see →Android< /span>.

        The code to obtain the platform in Unity project C# is as follows, and the UnityEngine namespace needs to be introduced.

RuntimePlatform platform = Application.platform; 

        ​​​​RuntimePlatform is an enumeration type, and the main platforms are as follows.

public enum RuntimePlatform {
    OSXEditor = 0, // editor on macOS.
    OSXPlayer = 1, // player on macOS.
    WindowsPlayer = 2, // player on Windows.  
    OSXWebPlayer = 3, // web player on macOS.
    ...
    WindowsWebPlayer = 5, // web player on Windows.
    WindowsEditor = 7, // editor on Windows.
    IPhonePlayer = 8, // player on the iPhone.
    Android = 11, // player on Android.
    ...
    WebGLPlayer = 17, // player on WebGL
    ...
    LinuxPlayer = 13, // player on Linux.
    LinuxEditor = 16, // editor on Linux.
    ...
}

2 Unity release apk

2.1 Install Android Build Support

        Open the Add Module window in Unity Hub and do the following.

        ​​​Select Android Build Support to install, as follows (the author has already installed it here).​ 

         ​ ​ ​Create a Unity project, click [File→Build Settings→Android→Switch Platform] in order, and configure it as follows.

        ​​​​ Click [Edit→Preferences→External Tools] to open the JDK, SDK, NDK, and Gradle configuration pages, and check the default configuration, as follows.

        The Gradle versions downloaded by default for different versions of Unity Editor are as follows. For the official introduction, see →Gradle for Android.

        Users can also select the installed JDK, SDK, NDK, and Gradle paths, as follows.

        The author’s specific environment configuration is as follows:

Unity Editor: 2021.3.11f1c2
JDK: 1.8.0_391
SDK Platforms: 29
SDK Build-Tools: 30.0.3
SDK Command-line Tools: 11.0
SDK Platform-Tools: 34.0.5
NDK: 21.3.6528147
Gradle: 6.1.1
Gradle Plugin: 4.0.1

2.2 Configuration key

        Click [Edit→Project Settings→Player→Keystore Manager] in sequence (you can also enter from [File→Build Settings→Player Settings→Keystore Manager]), the operation is as follows.

        After opening Keystore Manager, click [Create New→Anywhere] and select a directory to save the keystore file. I saved it in [Keystore/user.keystore] under the project directory.

        Next set the password and alias, other options are not required.

        After Add Key, a pop-up window will pop up asking “Whether to use the created keystore as the keystore for the project”, click yes to confirm.

         After setting the key, return to the Project Settings page, as shown below.

        When creating a key, you can also create it through the following command.

keytool -genkey -keyalg RSA -alias key_name -keystore keystore_name -validity day_time
keytool -genkey -keyalg RSA -alias first -keystore user -validity 36500

2.3 Packaging apk

        Click [File→Build Settings→Player Settings] in order to configure the company name, project name, version number and other information, as follows.

        Configure the package name, minimum API version of Android SDK, target API version and other information in Other Settings, as follows.​ 

        Close Player Settings, click Build at the bottom of the Build Settings page to build the apk.​ 

2.4 Case

        Create a new Unity project and modify the screen size of the Game page as follows.

        The page is built as follows.

        ​ ​ ​ Add a script to the Button button, as follows.

        Test.cs

using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour {
    private Button button;

    private void Start() {
        button = GetComponent<Button>();
        button.onClick.AddListener(OnClick);
    }

    private void OnClick() {
        Debug.Log("Test-OnClick");
    }
}

        After compiling the apk, open the command line window and enter the following command to install the apk on the phone.

adb instll -r -t -d Test.apk

        After running the apk, run the following command in the command line window to view the log.

adb logcat | findstr "Test-OnClick"

         ​ ​ ​Click the Button button to print the log as follows.

3 Unity adjusts Android logic

3.1 Deploy Android code in Unity project

        1) Copy the Java source code to the Unity project

        You can copy the Java code in the Android project to the Assets subdirectory in the Unity project, as follows. Then you can access the Java code through AndroidJavaClass or AndroidJavaObject.

        2) Package Jar into Unity project

        You can package the Android project as Jar, then copy the Jar to the Assets subdirectory of the Unity project, and then access the Java code through AndroidJavaClass or AndroidJavaObject.

        Modify the build.gradle file of Module in the Android project, as follows, mainly change the id from 'com.android.application' to 'com.android.library', and delete the android { } module defaultConfig, buildTypes, compileOptions and other sub-modules.

        build.gradle

apply plugin: 'com.android.library'

android {
    compileSdkVersion 29
    buildToolsVersion '30.0.3'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'com.google.android.material:material:1.8.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

        After modifying the build.gradle file, you need to click Sync Now in the upper right corner to synchronize, and then follow the following steps to compile the project.

        After compilation, the packaged classes.jar is generated in the [build\intermediates\aar_main_jar\debug] directory of the Module.

        Preview classes.jar file as follows.

3.2 AndroidJavaObject 和 AndroidJavaClass

        AndroidJavaObject and AndroidJavaClass are two classes provided by Unity for calling Java code. AndroidJavaClass inherits AndroidJavaObject. They only have a little difference in their construction methods and no other differences. Therefore, this section only introduces AndroidJavaObject.

        1) Set and Get properties

        JavaTest.java

package com.zhyan8.test;

public class JavaTest {
    public static int intVal = 0;
    private String strVal = "abc";
}

        ​ ​ ​ Note: AndroidJavaObject can also access the private properties of JavaTest.​ 

        UnityTest.cs

using UnityEngine;

public class UnityTest : MonoBehaviour {
    private void Start() {
        AndroidJavaObject javaObject = new AndroidJavaObject("com.zhyan8.test.JavaTest");
        // 静态属性Set/Get
        javaObject.SetStatic<int>("intVal", 123);
        int intVal = javaObject.GetStatic<int>("intVal");
        Debug.Log("UnityTest, intVal=" + intVal); // 打印: UnityTest, intVal=123
        // 非静态属性Set/Get
        javaObject.Set<string>("strVal", "xyz");
        string strVal = javaObject.Get<string>("strVal");
        Debug.Log("UnityTest, strVal=" + strVal); // 打印: UnityTest, strVal=xyz
    }
}

        2) Call method

        JavaTest.java

package com.zhyan8.test;

import android.util.Log;

public class JavaTest {
    public static void fun1() {
        Log.d("JavaTest", "fun1"); // 打印: JavaTest: fun1
    }

    private int fun2() {
        Log.d("JavaTest", "fun2"); // 打印: JavaTest: fun2
        return 123;
    }

    public String fun3(int value) {
        Log.d("JavaTest", "fun3, value=" + value); // 打印: JavaTest: fun3, value=235
        return "Call fun3";
    }

    public String fun4(String value1, int value2) {
        Log.d("JavaTest", "fun4, value1=" + value1 + ", value2=" + value2); // 打印: JavaTest: fun4, value1=abc, value2=123
        return value1 + value2;
    }
}

        Note: For the Private method of Javatest, AndroidjavaObject can also be accessed.​  

        UnityTest.cs

using UnityEngine;

public class UnityTest : MonoBehaviour {
    private void Start() {
        AndroidJavaObject javaObject = new AndroidJavaObject("com.zhyan8.test.JavaTest");
        // 静态方法
        javaObject.CallStatic("fun1");
        // 非静态无参方法
        int val2 = javaObject.Call<int>("fun2");
        Debug.Log("UnityTest, val2=" + val2); // 打印: UnityTest, val2=123
        // 非静单参方法
        string val3 = javaObject.Call<string>("fun3", 235);
        Debug.Log("UnityTest, val3=" + val3); // 打印: UnityTest, val3=Call fun3
        // 非静双参方法
        string val4 = javaObject.Call<string>("fun4", "abc", 123);
        Debug.Log("UnityTest, val4=" + val4); // 打印: UnityTest, val4=abc123
    }
}

        After running the program, the print log is as follows.

3.3 Unity calls Android Toast

        UnityTest.cs

using UnityEngine;
using UnityEngine.UI;

public class UnityTest : MonoBehaviour {
    private void Start() {
        GetComponent<Button>().onClick.AddListener(() => {
            Toast("Clicked", 1);
        });
    }

    // 调用Android的代码: Toast.makeText(context, msg, durationFlag).show();
    private void Toast(string msg, int durationFlag) { // durationFlag: Toast.LENGTH_SHORT=0, Toast.LENGTH_LONG=1
        AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
        AndroidJavaClass unityPlayerClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject currentActivity = unityPlayerClass.GetStatic<AndroidJavaObject>("currentActivity");
        AndroidJavaObject toast = toastClass.CallStatic<AndroidJavaObject>("makeText", currentActivity, msg, durationFlag);
        toast.Call("show");
    }
}

        UnityPlayer is a Java class provided by the Unity engine, located in [Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes\classes.jar] in the Unity Editor directory.

        The operation effect is as follows.

4 Android adjusts the logic of Unity

4.1 Unity is packaged as an Android project

        After checking Export Project on the Build Settings page, click the Export button, as shown below.

        After the build is successful, the Unity project will be packaged into an Android project. We can use Android Studio to open the generated Android project, as follows.

        Among them, UnityPlayerActivity is the started Main Activity, and unity-classes.jar is the Jar package in Unity Editor. For the location, see [Unity Hub\Unity\Editor\2021.3.11f1c2\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\ Classes\classes.jar], our commonly used UnityPlayer class is in this Jar file.

        If the user wants to package the Android project into the Unity project, but the Android project needs to reference the Unity interface, the user can copy the classes.jar in the Unity Editor to the Android project, as follows.

        Right-click classes.jar and select Add As Library in the pop-up menu.

4.2 UnityPlayer

        UnityPlayer inherits FrameLayout and is mainly used to call Unity code from Java. Its main properties and methods are as follows.

// 在UnityPlayer的构造方法中初始化, currentActivity = this.mActivity
public static Activity currentActivity = null;

// java调用Unity中的方法, gameObject: 游戏对象名, method: 游戏对象上挂载脚本中的方法名, params: 方法参数
public static void UnitySendMessage(String gameObject, String method, String params)

        UnitySendMessage to call the private method can be called.

4.3 Case

        UseUnity.cs

using UnityEngine;

public class UseUnity : MonoBehaviour {

    private void Start() {
        AndroidJavaObject javaObject = new AndroidJavaObject("com.zhyan8.test.JavaTest");
        javaObject.Call("start");
    }

    public void Fun1() {
        Debug.Log("UseUnity-Fun1"); // 打印: UseUnity-Fun1
    }

    private void Fun2(string value) {
        Debug.Log("UseUnity-Fun2, value=" + value); // 打印: UseUnity-Fun2, value=xyz
    }
}

        ​​​​Description: The UseUnity script component is hung on the TestObj object.

        JavaTest.java

package com.zhyan8.test;

import android.util.Log;

import com.unity3d.player.UnityPlayer;

public class JavaTest {

    public void start() {
        fun1();
        fun2();
    }

    private void fun1() {
        Log.d("JavaTest", "fun1"); // 打印: JavaTest: fun1
        UnityPlayer.UnitySendMessage("TestObj", "Fun1", "");
    }

    private void fun2() {
        Log.d("JavaTest", "fun2"); // 打印: JavaTest: fun2
        UnityPlayer.UnitySendMessage("TestObj", "Fun2", "xyz");
    }
}

        The print log is as follows:

Guess you like

Origin blog.csdn.net/m0_37602827/article/details/133936278