Chame métodos não estáticos em plugins personalizados do Unity Android

8

Estou tentando entender como criar meus próprios plug-ins para Android.

Consigo chamar métodos estáticos na minha classe Java (a criada no AndroidStudio), mas realmente NÃO POSSO chamar métodos não estáticos.

Verifico esses links:

Mas nenhum funciona.

Estou tentando receber a chamada de um botão do Unity, como:

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

E minha atividade no Android se parece com:

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

Meu ADB está lançando esta mensagem: insira a descrição da imagem aqui

Também tentei ligar em vez do UnityPlayer, assim:

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

EDIT: Este é o meu 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>

Mas também não funciona para métodos não estáticos, funciona apenas para métodos estáticos, se faço pluginClass.CallStatic(""), alguma ideia?

EDIT 2:

  • Taras Leskiv sugere alterar o UnityPlayer.Get para UnityPlayer.GetStatic, mas então recebo o seguinte erro:

    erro: java.lang.NoSuchMethodError: nenhum método não estático com nome = 'SayHi' signature = '() V' na classe Ljava.lang.Object;

  • O programa não está ativo.
Lotan
fonte
Você pode adicionar seu AndroidManifest.xml? Você tem a MainActivity dentro?
JeanLuc 24/02
@JeanLuc adicionado ao post, e sim, ele está dentro, como você pode ver :(
Lotan
É realmente sua atividade retornada? Nesse caso, o Unity pode não conhecer esse tipo e acha que é um Activity. Então, você pode precisar lançá-lo de alguma forma.
tynn 3/03
@tynn essa foi a resposta de Jean Bouvattier, mas não explica como alcançar esse elenco.
Lotan

Respostas:

1

Quando você está fazendo isso:

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

Não funciona porque o currentActivitycampo é estático, o que você deve fazer é:

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

Observe a parte UnityPlayer.GetStatic

Aqui está outro trecho de conveniência de um dos meus 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;
        }
    }
Taras Leskiv
fonte
Em seguida, recebo o seguinte erro: java.lang.NoSuchMethodError: nenhum método não estático com nome = 'SayHi' signature = '() V' na classe Ljava.lang.Object; :(
Lotan
Ok, esse é o próximo erro, talvez também verifique se você tem o programa ativado, pois ele pode ofuscar o código java na compilação
Taras Leskiv
Não, o programa está desativado porque eu não tenho o diretório do programa, o que mais poderia ser?
Lotan
Também estou usando app-debug.aar em vez do release, para garantir que o Proguard não faça nenhum encolhimento.
Lotan
0

Talvez isso tenha a ver com a herança do java: seu currentActivity AndroidJavaObject é da classe, com.unity3d.player.UnityPlayer mas essa classe não possui SayHimétodo, você deve converter seu objeto MainActivityantes de chamar seu método.

Jean Bouvattier
fonte
Mas MainActivity também é um AndroidJavaClass, como você faria isso? Você pode postar um exemplo, por favor?
Lotan 25/02
Não posso ajudá-lo mais agora, mas este link provavelmente o ajudará: devua.co/2016/07/30/…
Jean Bouvattier
Eu tentei o link, mas não funciona, talvez eu esteja fazendo algo errado com o elenco? oO
Lotan
0

Meu código estava correto, o problema era a estrutura do projeto.

Meu projeto foi como:

Assets
├── Plugins
   ├── classes.jar

E deve ser como:

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

O obvius (não para mim) causou o erro de spam na mensagem que não conseguiu encontrar a assinatura; portanto, o software não pode ler essas classes.

Lotan
fonte
-1

Tudo o que você precisa fazer é declarar seu próprio contexto estático na classe de atividade:

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

E, em seguida, basta chamar qualquer método não estático do C # assim:

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 outros métodos para chamar métodos diretamente do código java. Você pode implementar seu próprio sistema de mensagens usando os comandos AndroidJavaProxy e Broadcast sem sequer atividade, mas é outra questão.

Nikolay Gonza
fonte
Essa abordagem (campos de contexto estático) causa vazamento de memória.
0xBFE1A8
sim, mas se houver muitos campos estáticos, isso é feito para entender como o ajo funciona
Nikolay Gonza
Uma referência estática não é uma opção. Primeiro, você não sabe quantas dessas atividades acabam na pilha. Se você realmente precisar fazer isso, certifique-se de limpar depois de entrar onDestroy.
tynn 3/03
Você tem apenas 1 atividade que implementa o Unity Player; para outras coisas (por exemplo, serviços, outras atividades), você sempre pode usar transmissões. Esta é uma solução muito simples e clássica
Nikolay Gonza
desculpe pela resposta tardia @NikolayGonza, mas com seu código, a atividade é Null :(
Lotan