やはりUNITYでAndroidプラグインを作るにはAndroidJavaClassが便利だ

More than 1 year has passed since last update.

UNITYでスマホ用アプリを開発していると
どうしても、ネイティブ機能を使う必要が出てきます
ので、その時の言語バインディングには色んな方法あるので
メモ的に

C言語でバインド

AndroidであればNDKで soファイルを作りそれをリンクします
C言語ぶぶんはそれだけで あれがあれなので今回はヘッダのみ

c言語
extern "C" {
  const char* cfunk (int n);
} 
c#
[DllImport ("PluginName")]
private static extern const char* cfunc (int n); 

DllImportします。
これは iOSとのリンクするときも同じです
JavaやC#は リバースエンジニアリングが容易なので
セキュリティー関連等は あえてC言語で書く人も多いと思いますし
速度を重視したり、大量のメモリを使う場合等
C++を使う場面も多いと思います
が、C++なので当然 基本データ型しか使えません
string も当然使えないので char* 等で渡しましょう

Javaでバインド(staticメソッド)

最も良く使われる方法
Java側のstaticなメソッドをコールする
(基本的にPluginは シングルトンで作る事が多い)

ネイティブ
package com.sample;
public class plugin{
  public static String func(int n){
    return( "Hello world!!" + Integer.toString(n) );
  }
}
UNITY
  AndroidJavaClass cls = new   AndroidJavaClass("com.sample.plugin"))
  string str = cls.CallStatic<string>("func",1);

ネイティブ側は説明不要。
UNITY側は、AndroidJavaClassに クラス名をフルネームで与え、classを取得
取得したclassのstaticメソッドを呼ぶのがCallStatic
ジェネリクスには 戻り値の型を指定し、第一引数は関数名。第二引数以降に引数を指定する

引数や戻り値に使えるのは、プリミティブ型とstring型で、それ以外は AndroidJavaObject型で受け取る

Javaでバインド(staticプロパティー)

プロパティーの場合も ほぼ同じ

ネイティブ
package com.sample;
public class plugin{
  public static String mStr = "aaaaa";
}
UNITY
  AndroidJavaClass cls = new AndroidJavaClass("com.sample.plugin"))
  string str = cls.GetStatic<string>("mStr");
  cls.SetStatic("Hello World");

GetStatic<> と、SetStatic でオケー

Javaでバインド(non staticメソッド)

non staticな場合は、インスタンス作成が必要なので AndroidJavaObjectを使う
(AndroidJavaClass はインスタンスを作らないのでStaticフィールドにアクセスする事しかできない)

ネイティブ
package com.sample;
public class plugin{
  String mStr;
  plugin(String str){
    mStr = str;
  }
  public String func(int n){
    return( mStr + Integer.toString(n) );
  }

}
UNITY
  AndroidJavaObject obj = new AndroidJavaObject("com.sample.plugin","Hello World!");
  string str = obj.Call<string>("func", 2);

AndroidJavaObjectで プラグインのclassのインスタンスを作成し、non staticメンバーを Call
もちろん、プロパティーには Get、Set 関数が容易されている
あまり UNITY側でプラグインクラスをインスタンス化する事はしないかもしれないが
例えば プラグインを Singletonで実装し、non staticメンバにアクセスする事は 時々やるかな。

UNITY
  AndroidJavaClass cls = new AndroidJavaClass("com.sample.plugin");
  AndroidJavaObject obj = cls.GetStatic<AndroidJavaObject>("getInstance");
  string str = obj.Call<string>("func", 2);

getInstance()で プラグインのインスタンスを取得し、AndroidJavaObject型で受け、non staticアクセスをしている

C#で完結させる

ちょっとした処理にわざわざJar作るのも面倒なので
可読性が失われない小さいプラグインは、直接書いてしまった方が楽

例えば、アプリケーションのBundleバージョンの取得

UNITY
public getVersionName()
{
  AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  AndroidJavaObject context = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity").Call<AndroidJavaObject>("getApplicationContext");
  AndroidJavaObject pManager = context.Call<AndroidJavaObject>("getPackageManager");
  AndroidJavaObject pInfo = pManager.Call<AndroidJavaObject>( "getPackageInfo", context.Call<string>("getPackageName"), pManager.GetStatic<int>("GET_ACTIVITIES") );

  string versionName = pInfo.Get<string>( "versionName" );
  return versionName;
}

Staticとnon static を分けて考えなければならないのが、少し面倒だけど
Javaとの連携は比較的簡単Death!!