Unity Android插件开发

背景
在Unity中开发Android插件可以让你利用Android平台的特定功能和API,从而扩展Unity应用的功能。以下是开发Unity Android插件的详细步骤,包括创建Android库、与Unity集成、调用Java方法、处理回调等。

1. 设置开发环境

首先,你需要安装以下工具:

  • Unity
  • Android Studio
  • JDK(Java Development Kit)
  • Android SDK
2. 创建Android库项目

在Android Studio中创建一个新的Android库项目:

  1. 打开Android Studio,选择 “Start a new Android Studio project”。
  2. 选择 “Phone and Tablet” 选项,然后选择 “Add No Activity”。
  3. 在 “Configure your project” 窗口中,选择 “Library” 作为项目类型,并填写项目名称和包名。
  4. 点击 “Finish” 创建项目。
  5. 在android工程下的libs文件里添加unity的jar包

Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Release\Classes里面找到对应需要的class.jar

3. 编写Java代码

在Android库项目中编写你需要的Java代码。例如,创建一个简单的类来展示Toast消息:

package com.example.myplugin;

import android.content.Context;
import android.widget.Toast;

public class MyPlugin {
    public static void showToast(Context context, String message) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    }
}
4. 配置build.gradle

确保你的build.gradle文件配置正确,以生成AAR文件。以下是一个示例配置:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 30
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:28.0.0'
}
5. 生成AAR文件

在Android Studio中,点击 “Build” 菜单,然后选择 “Make Project”。这将生成一个AAR文件,通常位于 app/build/outputs/aar/ 目录下。

6. 将AAR文件导入Unity
  1. 打开你的Unity项目。
  2. 创建一个名为 Plugins 的文件夹(如果还没有)。
  3. 在 Plugins 文件夹中创建一个名为 Android 的子文件夹。
  4. 将生成的AAR文件复制到 Plugins/Android 文件夹中。
7. 创建C#脚本与Java交互

在Unity中创建一个C#脚本,用于调用Java方法。以下是一个示例脚本:

using UnityEngine;

public class MyPluginWrapper : MonoBehaviour
{
    private static AndroidJavaObject _pluginInstance;

    void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            using (var pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin"))
            {
                _pluginInstance = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            }
        }
    }

    public static void ShowToast(string message)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            _pluginInstance.Call("showToast", message);
        }
    }
}
8. 调用Java方法

在Unity脚本中调用Java方法。例如,在一个按钮点击事件中调用 ShowToast 方法:

using UnityEngine;
using UnityEngine.UI;

public class Example : MonoBehaviour
{
    public Button showToastButton;

    void Start()
    {
        showToastButton.onClick.AddListener(OnShowToastButtonClicked);
    }

    void OnShowToastButtonClicked()
    {
        MyPluginWrapper.ShowToast("Hello from Unity!");
    }
}
9. 处理回调

如果需要从Java代码中回调Unity,可以使用Unity的 UnityPlayer.UnitySendMessage 方法。以下是一个示例:

Java代码
package com.example.myplugin;

import android.content.Context;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;

public class MyPlugin {
    public static void showToast(Context context, String message) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        UnityPlayer.UnitySendMessage("GameObjectName", "OnToastShown", "Toast shown: " + message);
    }
}
Unity C#代码
using UnityEngine;

public class MyPluginWrapper : MonoBehaviour
{
    private static AndroidJavaObject _pluginInstance;

    void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            using (var pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin"))
            {
                _pluginInstance = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            }
        }
    }

    public static void ShowToast(string message)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            _pluginInstance.Call("showToast", message);
        }
    }

    // 回调方法
    public void OnToastShown(string message)
    {
        Debug.Log("Received message from Android: " + message);
    }
}

在Java代码中,我们使用 UnityPlayer.UnitySendMessage 方法将消息发送回Unity。UnitySendMessage 方法的参数包括:

  • Unity中的GameObject名称
  • Unity中的方法名称
  • 传递的消息

在Unity中,我们需要确保 OnToastShown 方法所在的GameObject名称与Java代码中的名称匹配。

10. 调试和测试
  1. 在Unity中测试插件

    • 确保你的Android设备已连接并启用了开发者模式。
    • 在Unity中,构建并运行你的项目到Android设备上。
    • 触发调用Java方法的事件(例如,点击按钮),并观察日志输出。
  2. 查看日志

    • 使用 adb logcat 命令查看Android设备的日志输出,确保Java方法被正确调用,并且回调方法在Unity中被正确处理。
11. 处理复杂数据类型

如果需要在Unity和Java之间传递复杂数据类型,可以使用JSON或其他序列化方法。例如,传递一个包含多个字段的对象:

Java代码
package com.example.myplugin;

import android.content.Context;
import android.widget.Toast;
import com.unity3d.player.UnityPlayer;
import org.json.JSONObject;

public class MyPlugin {
    public static void showToast(Context context, String message) {
        Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
        try {
            JSONObject json = new JSONObject();
            json.put("message", message);
            json.put("timestamp", System.currentTimeMillis());
            UnityPlayer.UnitySendMessage("GameObjectName", "OnToastShown", json.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Unity C#代码

     (备注:也可以AndroidJavaClass androidClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

m_androidObj = androidClass.GetStatic<AndroidJavaObject>("currentActivity");

using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;

public class MyPluginWrapper : MonoBehaviour
{
    private static AndroidJavaObject _pluginInstance;

    void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            using (var pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin"))
            {
                _pluginInstance = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            }
        }
    }

    public static void ShowToast(string message)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            _pluginInstance.Call("showToast", message);
        }
    }

    // 回调方法
    public void OnToastShown(string json)
    {
        var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
        Debug.Log("Received message from Android: " + data["message"]);
        Debug.Log("Timestamp: " + data["timestamp"]);
    }
}
12. 发布和维护
  1. 文档:为你的插件编写详细的文档,包括如何集成、使用示例和API参考。
  2. 版本控制:使用版本控制系统(如Git)来管理你的插件代码。
  3. 发布:将你的插件发布到Unity Asset Store或其他平台,方便其他开发者使用。
  4. 维护:定期更新和维护你的插件,修复bug并添加新功能。

通过以上步骤,你可以成功地在Unity中开发和集成Android插件,从而利用Android平台的特定功能和API,扩展你的Unity应用的功能。

classes.jar文件

在Unity项目中集成Android插件时,classes.jar 文件通常包含你在Android Studio中编写的Java代码的编译结果。为了让Unity能够正确识别和使用这个classes.jar文件,你需要将它放在特定的目录中。

将 classes.jar 文件放到 Unity 项目中
  1. 创建 Plugins/Android 目录

    • 在你的Unity项目的 Assets 目录下,创建一个名为 Plugins 的文件夹(如果还没有)。
    • 在 Plugins 文件夹中,创建一个名为 Android 的子文件夹。
  2. 复制 classes.jar 文件

    • 将 classes.jar 文件复制到 Assets/Plugins/Android 目录中。
示例目录结构
YourUnityProject/
├── Assets/
│   ├── Plugins/
│   │   ├── Android/
│   │   │   ├── classes.jar
│   │   │   ├── your-other-plugin-files.aar
│   │   │   └── AndroidManifest.xml (if needed)
│   ├── Scripts/
│   │   ├── MyPluginWrapper.cs
│   └── ...
├── ProjectSettings/
└── ...
配置 AndroidManifest.xml(如果需要)

有时,你的插件可能需要在 AndroidManifest.xml 中声明特定的权限或组件。在这种情况下,你需要在 Assets/Plugins/Android 目录中创建或修改 AndroidManifest.xml 文件。

示例 AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myplugin">

    <application>
        <!-- 声明你的插件需要的权限或组件 -->
        <activity android:name="com.example.myplugin.MyActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <!-- 声明你的插件需要的权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>
在Unity中调用Java代码

确保你已经在Unity中编写了相应的C#脚本来调用Java代码。以下是一个示例脚本:

using UnityEngine;

public class MyPluginWrapper : MonoBehaviour
{
    private static AndroidJavaObject _pluginInstance;

    void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            using (var pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin"))
            {
                _pluginInstance = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            }
        }
    }

    public static void ShowToast(string message)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            _pluginInstance.Call("showToast", message);
        }
    }
}

通过将 classes.jar 文件放置在 Assets/Plugins/Android 目录中,并确保正确配置 AndroidManifest.xml 和相应的C#脚本,你可以成功地在Unity项目中集成和使用Android插件。

修改build.gradle

在Android Studio中创建Android库项目并生成AAR文件时,build.gradle 文件的配置非常重要。以下是一个详细的示例,展示了如何配置 build.gradle 文件,以确保生成的AAR文件可以正确集成到Unity项目中。

示例 build.gradle 文件
apply plugin: 'com.android.library'

android {
    compileSdkVersion 30

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        // 如果需要使用NDK,可以在这里配置
        // ndk {
        //     abiFilters "armeabi-v7a", "x86"
        // }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    // 配置输出AAR文件的路径
    libraryVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "${project.name}-${variant.name}.aar"
        }
    }
}

dependencies {
    // 添加你需要的依赖库
    implementation 'com.android.support:appcompat-v7:28.0.0'
    // implementation 'com.google.android.gms:play-services-ads:19.7.0'
}
生成AAR文件
  1. 在Android Studio中构建项目
    • 打开Android Studio,确保你已经打开了你的Android库项目。
    • 点击 “Build” 菜单,然后选择 “Make Project” 或 “Build > Build Bundle(s) / APK(s) > Build APK(s)”。
    • 这将生成一个AAR文件,通常位于 app/build/outputs/aar/ 目录下。
将AAR文件导入Unity
  1. 创建 Plugins/Android 目录

    • 在你的Unity项目的 Assets 目录下,创建一个名为 Plugins 的文件夹(如果还没有)。
    • 在 Plugins 文件夹中,创建一个名为 Android 的子文件夹。
  2. 复制 AAR 文件

    • 将生成的AAR文件复制到 Assets/Plugins/Android 目录中。
示例目录结构
YourUnityProject/
├── Assets/
│   ├── Plugins/
│   │   ├── Android/
│   │   │   ├── your-plugin-release.aar
│   │   │   └── AndroidManifest.xml (if needed)
│   ├── Scripts/
│   │   ├── MyPluginWrapper.cs
│   └── ...
├── ProjectSettings/
└── ...
在Unity中调用Java代码

确保你已经在Unity中编写了相应的C#脚本来调用Java代码。以下是一个示例脚本:

using UnityEngine;

public class MyPluginWrapper : MonoBehaviour
{
    private static AndroidJavaObject _pluginInstance;

    void Start()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            using (var pluginClass = new AndroidJavaClass("com.example.myplugin.MyPlugin"))
            {
                _pluginInstance = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            }
        }
    }

    public static void ShowToast(string message)
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            _pluginInstance.Call("showToast", message);
        }
    }
}
最后unity打包的时候要选择这一项调试和测试

  1. 在Unity中测试插件

    • 确保你的Android设备已连接并启用了开发者模式。
    • 在Unity中,构建并运行你的项目到Android设备上。
    • 触发调用Java方法的事件(例如,点击按钮),并观察日志输出。
  2. 查看日志

    • 使用 adb logcat 命令查看Android设备的日志输出,确保Java方法被正确调用,并且回调方法在Unity中被正确处理。

通过正确配置 build.gradle 文件,生成AAR文件,并将其导入Unity项目中,你可以成功地在Unity项目中集成和使用Android插件。