Не получается вызвать C# код из java

Программирование для iPhone & Android

Не получается вызвать C# код из java

Сообщение keydon24.kd 23 апр 2017, 01:40

Выручайте, который день мучаюсь и не получается вызвать C# код из java.
Не нашел годных плагинов для поддержки midi, приходится свой писать.
В API Android активно юзаются callback, да и midi-команды все же придется в C# передавать.

Нагуглил следующие варианты:
1)использовать unitysendmessage
Вроде юзаю, правильно, перерыл много инфы как с форумов и стаковерфлоу, так и официальной информации(а ее очень мало, вообще доки устаревшие и нет примеров java кода). Ориентировался на это видео
Скрытый текст:

у него вроде все работает.
Но раз у меня не работает видимо где-то косячу.
Java функции из C# нормально вызваются, а вот сообщения из java в C# насколько я понимаю не доходят.
Синтаксис:
Используется csharp
using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class PluginWrapper : MonoBehaviour {

    static AndroidJavaClass plugin;
    static Text textMesh;
    static AndroidJavaObject midiManager;
    static public GameObject gameobject;

    //public class DeviceCallback : AndroidJavaProxy
    //{
    //    public DeviceCallback() : base("android.media.midi.MidiManager.DeviceCallback") { }

    //    void onDeviceAdded(AndroidJavaObject info)
    //    {
    //        //do C#
    //        textMesh.text = textMesh.text + "Добавлено новое устройство" + '\n';
    //    }
    //}

    public void SendUnityMessage(string objectName, string methodName, string parameterText){
#if UNITY_ANDROID && !UNITY_EDITOR
        Debug.Log("SARA: call SendUnityMessage(" + "objectName: " + objectName + " methodName: " + methodName + " parameterText: " + parameterText+ ")");
        AndroidJavaClass ajc = new AndroidJavaClass("com.example.saraplugin");
        ajc.CallStatic("SendUnityMessage",     objectName,        methodName,        parameterText);
#elif UNITY_EDITOR
        //nothing
#endif                                                                                                      
    }

        // Use this for initialization
        void Start () {
        textMesh = GetComponent<Text>();
        //SendMessage("ApplyDamage", "MessageForUnity");

#if UNITY_ANDROID && !UNITY_EDITOR
        plugin = new AndroidJavaClass("com.example.saraplugin.PluginClass");

        //получаем контекст
        AndroidJavaClass unityplayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject context = unityplayer.GetStatic<AndroidJavaObject>("currentActivity");
        //textMesh.text = plugin.CallStatic<bool>("isMidiSupport", context).ToString();

        //получаем midiManager
        midiManager = plugin.CallStatic<AndroidJavaObject>("getMidiManager", context);
        //textMesh.text = midiManager.ToString();

        //midiManager.Call("registerDeviceCallback", new DeviceCallback());
        //GameObject testobj = this;
        Debug.Log("SARA: name" + this.name);

        Debug.Log("SARA: start calling sendunitymessage from java");

        SendUnityMessage(this.name, "ApplyDamage", "MessageForUnity");
#elif UNITY_EDITOR
        plugin = null;
        midiManager = null;
#endif
    }
       
        // Update is called once per frame
        void Update () {

#if UNITY_ANDROID && !UNITY_EDITOR
        //////получаем подключенные в настоящий момент устройства
        int numOfDevices = plugin.CallStatic<int>("getDevicesNumber", midiManager);
        AndroidJavaObject device = plugin.CallStatic<AndroidJavaObject>("getDevice", midiManager, 1);
        int firstDeviceID = device.Call<int>("getId");

        textMesh.text = "Количество устройств:" + numOfDevices + '\n'
                        + "Id первого устройства:" + firstDeviceID + '\n';

       // Debug.Log("SARA: UPDATE!!!!!!!!!");


#elif UNITY_EDITOR_WIN
        //nothing
        //example message sending
        GameObject go = GameObject.Find("PluginWrapper");
        gameObject.SendMessage("ApplyDamage", "teststr");
#endif
    }

    //for test delete this method in future
    public void ApplyDamage(string str)
    {
        Debug.Log("SARA: Unity sended message: " + str);
    }

}


Синтаксис:
Используется java
package com.example.saraplugin;

import android.content.Context;
import android.content.pm.PackageManager;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiManager;

import com.unity3d.player.UnityPlayer;

public class PluginClass {

//    public MidiManager m = null;
//    public Context context = null;


    //todo delete this method
    public static String GetTextFromPlugin(int number){
        return "Number iiiisss" + number;
    }

    public static void SendUnityMessage(String objectName, String methodName, String parameterText){
        com.unity3d.player.UnityPlayer.UnitySendMessage(       objectName,        methodName,        parameterText);
    }

    public static boolean isMidiSupport(Context context){
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
    }

    public static MidiManager getMidiManager(Context context){
        return (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
    }

    //// TODO: 05.04.2017 should see AndroidJNIHelper.ConvertFromJNIArray is working for not native objects
    public static int getDevicesNumber(MidiManager m){
        return m.getDevices().length;
    }

    public static MidiDeviceInfo getDevice(MidiManager m, int num){
//        UnityPlayer.UnitySendMessage ("PluginWrapper", "ApplyDamage", "Message to send teststr");
        return m.getDevices()[num];
    }

    //Регистрируем калбеки
    public static int registerDeviceCallback(MidiManager m){
//        MidiManager.DeviceCallback callback = new MidiManager.DeviceCallback() {
//            public void onDeviceAdded(MidiDeviceInfo info) {
//
//                UnityPlayer.UnitySendMessage ("Text", "ApplyDamage", "Message to send teststr");
                return 0;
//            }
//        };
//        m.registerDeviceCallback(callback);
    }

    //UnityPlayer.UnitySendMessage("GameObjectName1", "MethodName1", "Message to send")
//    public static MidiDeviceInfo[] getDevices(MidiManager m){
//        return m.getDevices().length;
//    }
//
//    public static MidiDeviceInfo[] getDevices(MidiManager m){
//        MidiDeviceInfo[] infos = m.getDevices();
//        return infos;
//    }
}


Вывод logcat, правильно я понимаю, что он не может найти объект TextBoard?
Синтаксис:
  1. 04-23 01:19:48.826 17283-17301/com.keydon.plugintest I/Unity: SARA: nameTextBoard 
  2. UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object) 
  3. UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) 
  4. UnityEngine.Logger:Log(LogType, Object) 
  5. UnityEngine.Debug:Log(Object) 
  6. PluginWrapper:Start() (at E:\Programs\Unity\Unity projects\plugintest\plugintest\Assets\PluginWrapper.cs:52) 
  7.  
  8. (Filename: E Line: 0) 
  9. 04-23 01:19:48.828 17283-17301/com.keydon.plugintest I/Unity: SARA: start calling sendunitymessage from java 
  10. UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object) 
  11. UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) 
  12. UnityEngine.Logger:Log(LogType, Object) 
  13. UnityEngine.Debug:Log(Object) 
  14. PluginWrapper:Start() (at E:\Programs\Unity\Unity projects\plugintest\plugintest\Assets\PluginWrapper.cs:54) 
  15.  
  16. (Filename: E Line: 0) 
  17. 04-23 01:19:48.833 17283-17301/com.keydon.plugintest I/Unity: SARA: call SendUnityMessage(objectName: TextBoard methodName: ApplyDamage parameterText: MessageForUnity) 
  18. UnityEngine.DebugLogHandler:Internal_Log(LogType, String, Object) 
  19. UnityEngine.DebugLogHandler:LogFormat(LogType, Object, String, Object[]) 
  20. UnityEngine.Logger:Log(LogType, Object) 
  21. UnityEngine.Debug:Log(Object) 
  22. PluginWrapper:SendUnityMessage(String, String, String) (at E:\Programs\Unity\Unity projects\plugintest\plugintest\Assets\PluginWrapper.cs:25) 
  23. PluginWrapper:Start() (at E:\Programs\Unity\Unity projects\plugintest\plugintest\Assets\PluginWrapper.cs:56) 
  24.  
  25. (Filename: E Line: 0) 
  26. 04-23 01:19:48.879 17283-17301/com.keydon.plugintest I/Unity: AndroidJavaException: java.lang.ClassNotFoundException: com.example.saraplugin 
  27. java.lang.ClassNotFoundException: com.example.saraplugin 
  28. at java.lang.Class.classForName(Native Method) 
  29. at java.lang.Class.forName(Class.java:324) 
  30. at java.lang.Class.forName(Class.java:285) 
  31. at com.unity3d.player.UnityPlayer.nativeRender(Native Method) 
  32. at com.unity3d.player.UnityPlayer.a(Unknown Source) 
  33. at com.unity3d.player.UnityPlayer$b$1.handleMessage(Unknown Source) 
  34. at android.os.Handler.dispatchMessage(Handler.java:98) 
  35. at android.os.Looper.loop(Looper.java:148) 
  36. at com.unity3d.player.UnityPlayer$b.run(Unknown Source) 
  37. Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.saraplugin" on path: DexPathList[[zip file "/data/app/com.keydon.plugintest-3/base.apk"],nativeLibraryDirectories=[/data/app/com.keydon.plugintest-3/lib/arm, /data/app/com.keydon.plugintest-3/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]] 
  38. at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) 
  39. at java.lang.C 


Директория Assets:
Синтаксис:
  1. Unity projects/plugintest/plugintest/Assets 
  2. $ ls -R 
  3. .: 
  4. Plugins/ plugintest.apk plugintest.unity PluginWrapper.cs 
  5. Plugins.meta plugintest.apk.meta plugintest.unity.meta PluginWrapper.cs.meta 
  6.  
  7. ./Plugins: 
  8. Android/ Android.meta 
  9.  
  10. ./Plugins/Android: 
  11. libs/ libs.meta 
  12.  
  13. ./Plugins/Android/libs: 
  14. AndroidManifest.xml AndroidManifest.xml.meta classes.jar classes.jar.meta 


Скрипт присоединен к TextBoard:
Скрытый текст:
Изображение

ЧЯДНТ? Из-за чего еще может не робить? Что еще можно проверить? В Unity стоит Player settings для android
Minium API Level: Android 5.1 Lollipop (API Level 22)
А библиотеку собираю
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.keydon.saraplugin"
minSdkVersion 23
targetSdkVersion 25
Вроде это не должно влиять?

2) использовать AndroidJavaProxy
Примеры которые нашел запутаны(искал чуть меньше), кроме того не уверен можно ли его использовать для переопределения методов java классов, а не интерфейсов.
Как я понимаю тут код только на C# стороне.
Тем не менее он не работал(закомментирован выше).

Могу выложить в гит, если так будет удобнее, правда не умею его готовить для unity, поэтому запихаю все.

В догонку пара мелких вопросов:
1)при указании ifdef платформы, VS 2012 перестает подсвечивать Android код, видимо считая, что раз я под виндой, то он мне и не нужен. Как исправить?
2)можно ли как-нибудь автоматически обновлять jar в юнити после сборки в android studio? Удалять из директории напрямую средствами ОС Unity не рекомендует, якобы связи теряются. Сейчас ручками удаляю через Unity. Или можно забить на связи(они там вообще есть для jar то? в скриптах то он не используется) и сделать символьную ссылку на jar? Как юнити вообще отнесется к тому, что добавленный когда-то файл будет со стороны изменяться?
Скрытый текст:
Изображение
keydon24.kd
UNец
 
Сообщения: 1
Зарегистрирован: 23 апр 2017, 00:29

Вернуться в iPhone & Android

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2