UnityとAndroidネイティブ間の双方向通信実装ガイド(AARプラグイン連携編)

Android側プラグインの構成整備

Unityプロジェクトからネイティブ機能へアクセスするには、専用のライブラリモジュールを作成する必要があります。Android Studioにおいて既存のApplicationモジュールとは別にLibraryタイプModuleを追加し、パッケージネームスペースを区別しておきます。

引き続き、Unityランタイムから直接呼び出し可能なJavaクラスを定義します。ここではAndroid側のウィンドウコンテキスト取得とユーザー向けUIフィードバック表示を一元化するマネージャーを実装します。

package com.game.plugin.androidbridge;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;

public class AndroidBridgeManager {
    private static volatile Activity unityActivityRef;

    /**
     * Unityプロセスが保持するアクティビティ参照を取得
     */
    public Activity getUnityContext() {
        if (unityActivityRef == null) {
            try {
                Class targetClass = Class.forName("com.unity3d.player.UnityPlayer");
                java.lang.reflect.Field activityField = targetClass.getDeclaredField("currentActivity");
                unityActivityRef = (Activity) activityField.get(null);
            } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
                throw new IllegalStateException("Unity Contextの初期化に失敗しました", e);
            }
        }
        return unityActivityRef;
    }

    /**
     * メインスレッドへディスパッチしてトースト表示を実施
     * @param userMessage 表示対象の文字列
     * @return 実行ステータス
     */
    public boolean dispatchNativeAlert(String userMessage) {
        Activity ctx = getUnityContext();
        if (ctx != null && !ctx.isFinishing()) {
            postToMainThread(() -> 
                Toast.makeText(ctx, userMessage, Toast.LENGTH_SHORT).show()
            );
            // Android→Unityへデータを返す場合はこの位置に
            // UnityPlayer.UnitySendMessage("ManagerObject", "ReceiveCallback", userMessage);
            return true;
        }
        return false;
    }

    private void postToMainThread(Runnable runnable) {
        new Handler(Looper.getMainLooper()).post(runnable);
    }
}

AARアーカイブのビルドと設置

ソースコードの修正が完了したら、Gradleビルドツール経由でパッケージファイルを生成します。モジュール名の設定画面から「Make Library」を実行し、出力ディレクトリ(通常は build/outputs/aar)内に拡張子.aarのファイルが作成されることを確認します。生成されたバイナリは、Unityプロジェクトの Assets/Plugins/Android フォルダ配下に配置してください。配置後はUnityのエンジンが自動的にマニフェストのマージとJNIロードを行います。

C#ランタイムからの呼び出し処理

Unity環境では AndroidJavaObject クラスを用いてメモリ内ネイティブアドレスとやり取りします。UIアクションを起点としてプラグイン関数をトリガーするコントローラーの実装例を以下に示します。

using UnityEngine;
using UnityEngine.UI;

public class BridgeConnector : MonoBehaviour
{
    private const string NAMESPACE_PATH = "com.game.plugin.androidbridge";
    private const string BRIDGE_CLASS = "AndroidBridgeManager";
    
    private AndroidJavaObject nativeWrapper;

    private void Awake()
    {
        // ネイティブクラスのインスタンスをヒープ上に確保
        nativeWrapper = new AndroidJavaObject(NAMESPACE_PATH + "." + BRIDGE_CLASS);

        // 簡易的なUIフック(Scene上にButtonが存在することを想定)
        Button triggerBtn = FindObjectOfType<Button>();
        if (triggerBtn != null)
        {
            triggerBtn.onClick.AddListener(SendCommandToNative);
        }
    }

    private void SendCommandToNative()
    {
        Debug.Log("[CLR] ネイティブ層へコマンド送信開始");
        bool executionResult = nativeWrapper.Call<bool>("dispatchNativeAlert", "Androidレイヤーより応答中");

        if (executionResult)
        {
            Debug.Log("[CLR] ハンドシェイク完了");
        }
        else
        {
            Debug.LogWarning("[CLR] ネイティブ呼び出しが拒否されました");
        }
    }

    /// <summary>
    /// Java側から送信されたペイロードを受信する登録メソッド
    /// </summary>
    public void ReceiveNativePayload(string data)
    {
        Debug.LogFormat("[CLR] 着信データ解析: {0}", data);
    }
}

ターゲットデバイスでの検証手順

Unity Editorのプレイモードまたは実際のAndroid端末へのビルド展開を行い、実機上での動作を検証します。画面の操作イベント発生時に指定したメッセージがデバイスのオーバーレイ通知としてレンダリングされ、ConsoleビューにC#側のデバッグログが順次出力されれば、クロスプラットフォーム通信経路は正常確立されています。パーミッションの動的取得や非同期データのシリアライズを伴うケースでは、各OSのライフサイクル規約に合わせて拡張を行ってください。

タグ: Unity Android AAR JNI C#

5月17日 16:03 投稿