Call non-static methods on custom Unity Android Pl

2020-08-26 11:30发布

问题:

I'm trying to understand how to build my own Android plugins for Android.

I achieve to call static methods on my Java class (the one created on AndroidStudio), but I really CAN'T call non-static methods.

I check those links:

  • https://answers.unity.com/questions/884503/cant-call-non-static-method-in-androidjavaclass.html

  • http://leoncvlt.com/blog/a-primer-on-android-plugin-development-in-unity/

  • https://answers.unity.com/questions/1327186/how-to-get-intent-data-for-unity-to-use.html

  • how to call Non-static method from Unity Android Plugin?

But none works.

I'm trying to get the call from a button from Unity like:

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

And my activity on Android looks like:

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_");
    }
}

My ADB is throwing this message:

I've also tried calling instead of UnityPlayer call it like:

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

EDIT: This is my 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>

But doesn't work either for non-static methods, it works only for static methods if I do pluginClass.CallStatic(""), any idea?

EDIT 2:

  • Taras Leskiv suggest to change UnityPlayer.Get to UnityPlayer.GetStatic, but then i get the follow error:

    error: java.lang.NoSuchMethodError: no non-static method with name='SayHi' signature='()V' in class Ljava.lang.Object;

  • Proguard is not active.

回答1:

When you are doing this:

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

It doesn't work because the currentActivity field is static, what you should do is:

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

Notice the UnityPlayer.GetStatic part

Here is other convenience snippet from one of my plugins:

    static AndroidJavaObject _activity;

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


回答2:

Maybe it has to do with java inheritence : your currentActivity AndroidJavaObject is of class com.unity3d.player.UnityPlayer but this class does not have SayHi method, you should cast your object to MainActivity before calling your method.



回答3:

All you need to do is declare your own static context in activity class:

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_");
    }
}

And then just call any non-static method from C# like this:

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

There is NO other methods to call methods directly from java code. You can implement your own messaging system using AndroidJavaProxy and Broadcast commands without even activity at all, but it is another question.



回答4:

My code was correct, the problem was the Project structure.

My Project was like:

Assets
├── Plugins
│   ├── classes.jar

And should be like:

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

Was obvius (not for me) cause the error spam the message that could not find the signature, so the software can't read those classes.