カスタムUnity Androidプラグインで非静的メソッドを呼び出す


8

私は自分のAndroid用Androidプラグインを構築する方法を理解しようとしています。

Javaクラス(AndroidStudioで作成されたクラス)で静的メソッドを呼び出すことはできましたが、非静的メソッドを呼び出すことはできません。

私はそれらのリンクをチェックします:

しかし、どれも機能しません。

Unityのボタンから次のように呼び出しを取得しようとしています:

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

Androidでの私の活動は次のようになります。

public class MainActivity extends UnityPlayerActivity {
    private static final String TAG = "LibraryTest";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "Created!");
    }

    public void SayHi()
    {
        Log.d(TAG, "HI_");
    }
}

私のADBは次のメッセージをスローしています: ここに画像の説明を入力してください

UnityPlayerではなく、次のように呼び出してみました。

AndroidJavaClass pluginClass = new AndroidJavaClass("com.example.eric.librarytest.MainActivity");

編集: これは私のAndroidManifest.xmlです

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.eric.librarytest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="24"
        android:targetSdkVersion="28" />

    <application android:label="@string/app_name" >
        <activity
            android:name="com.example.eric.librarytest.MainActivity"
            android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

しかし、非静的メソッドでも機能せず、静的メソッドでのみ機能しますpluginClass.CallStatic("")

編集2:

  • Taras LeskivはUnityPlayer.GetをUnityPlayer.GetStaticに変更することを提案していますが、次のエラーが発生します:

    エラー:java.lang.NoSuchMethodError:クラスLjava.lang.Objectにname = 'SayHi' signature = '()V'の非静的メソッドはありません。

  • Proguardはアクティブではありません。

AndroidManifest.xmlを追加できますか?内部にMainActivityがありますか?
JeanLuc

@JeanLucが投稿に追加されました。そうです。ご覧のとおり、内部にあります:(
Lotan

実際にあなたの活動は戻ってきましたか?もしそうなら、Unityはそのタイプを知らないかもしれず、それをだと思っていActivityます。だから、どういうわけかそれをキャストする必要があります。
tynn

@tynnはJean Bouvattierの回答でしたが、このキャストを達成する方法は説明されていません。
Lotan

回答:


1

あなたがこれをしているとき:

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.Get<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

currentActivityフィールドが静的であるため機能しません。次のようにしてください。

AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
currentActivity.Call("SayHi");

UnityPlayer.GetStaticパーツに注目してください

ここに私のプラグインの1つからの他の便利なスニペットがあります:

    static AndroidJavaObject _activity;

    public static AndroidJavaObject Activity
    {
        get
        {
            if (_activity == null)
            {
                var unityPlayer = new AndroidJavaClass(C.ComUnity3DPlayerUnityPlayer);
                _activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
            }
            return _activity;
        }
    }

次に、次のエラーが表示されます。:(
ロタン

さて、それが次のエラーです。ビルド時にJavaコードを難読化する可能性があるため、proguadが有効になっているかどうかも確認してください
Taras Leskiv

いいえ、proguardが無効になっているので、proguardディレクトリがないため、他に何ができますか?
ロタン

また、リリースの代わりにapp-debug.aarを使用して、Proguardによって縮小が行われないようにしています。
ロタン

0

多分それはJavaの継承に関係しているかもしれません:あなたのcurrentActivity AndroidJavaObjectはクラスですcom.unity3d.player.UnityPlayer が、このクラスにはSayHiメソッドがありませんMainActivity、メソッドを呼び出す前にオブジェクトをキャストする必要があります。


しかしMainActivityはAndroidJavaClassでもあります。どうすればよいでしょうか。例を投稿できますか?
ロタン

私はもっと今、あなたを助けることはできませんが、このリンクは、おそらくあなたを助ける:devua.co/2016/07/30/...
ジャンBouvattier

リンクを試しましたが機能しません。キャストで問題が発生しているのではないですか?oO
ロタン

0

私のコードは正しかった、問題はプロジェクト構造でした。

私のプロジェクトは次のようなものでした:

Assets
├── Plugins
   ├── classes.jar

そして次のようになります:

Assets
├── Plugins
   ├── Android
      ├── classes.jar

(私にとってはそうではありませんが)目立たなかったため、エラーが発生し、署名を見つけられなかったメッセージがスパム送信されたため、ソフトウェアはこれらのクラスを読み取ることができませんでした。


-1

必要なのは、アクティビティクラスで独自の静的コンテキストを宣言することだけです。

public class MainActivity extends UnityPlayerActivity {
    private static final String TAG = "LibraryTest";
    public static Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        Log.d(TAG, "Created!");
    }

    public void SayHi()
    {
        Log.d(TAG, "HI_");
    }
}

そして、次のようにC#から非静的メソッドを呼び出すだけです。

public static void AndroidCallFunction()
{
    using (AndroidJavaClass javaClass = new AndroidJavaClass("com.example.eric.librarytest.MainActivity"))
    {
        using (AndroidJavaObject activity = javaClass.GetStatic<AndroidJavaObject>("mContext"))
        {
            activity.Call("SayHi");
        }
    }
}

ありませんNO Javaコードから直接メソッドを呼び出すための他の方法が。AndroidJavaProxyコマンドとBroadcastコマンドを使用して、アクティビティをまったく行わずに独自のメッセージングシステムを実装できますが、これは別の問題です。


このアプローチ(静的コンテキストフィールド)により、メモリリークが発生します。
0xBFE1A8

はい、しかし、静的フィールドが多すぎる場合、これはajoがどのように機能するか理解できないためです
ニコライゴンザ

静的参照はオプションではありません。最初に、これらのアクティビティのいくつがスタックに含まれるかわかりません。あなたが本当にそれをする必要がある場合は、自分で後片付けをしてくださいonDestroy
tynn

Unityプレーヤーを実装するアクティビティは1つだけです。別のこと(サービス、別のアクティビティなど)の場合は、常にブロードキャストを使用できます。これは非常にシンプルでクラシックなソリューションです
Nikolay Gonza

@NikolayGonzaの返信が遅くなって申し訳ありませんが、あなたのコードでは、アクティビティはNull :(
Lotan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.