Edited at

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

More than 5 years have 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!!