Xie WeiXuan
Xie WeiXuan

Reputation: 21

Unity Android : no non-static method with name

I am making a Android plugin demo for unity,which when I click the button,it will launch another application.I can build an apk and install it to my device.However,when I click the button,nothing happened but sayings:Unity: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='shareToWX'

Here is Android code:

public class WXEntryActivity extends UnityPlayerActivity implements IWXAPIEventHandler {
private static final String APP_ID="";
private static final String APP_SECRET="";
private static IWXAPI api;
private static final int WXSceneSession=0;
private static final int WXSceneTimeLine=1;
private static final int WXSceneFavorite=2;

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    api= WXAPIFactory.createWXAPI(this,APP_ID,true);
    api.registerApp(APP_ID);
    api.handleIntent(getIntent(),this);
}


public void shareToWX(String text,int scene){
    WXWebpageObject webpage=new WXWebpageObject();
    webpage.webpageUrl="www.baidu.com";

    WXMediaMessage msg =new WXMediaMessage(webpage);
    msg.title="网页标题";
    msg.description="描述";
    Bitmap thumb=BitmapFactory.decodeResource(getResources(), R.drawable.test);
    //msg.thumbData=

    SendMessageToWX.Req req=new SendMessageToWX.Req();
    req.transaction=buildTransaction("webpage");
    req.message=msg;
    switch (scene){
        case WXSceneFavorite:
            req.scene=SendMessageToWX.Req.WXSceneFavorite;
            break;
        case WXSceneTimeLine:
            req.scene=SendMessageToWX.Req.WXSceneTimeline;
            break;
        case WXSceneSession:
            req.scene=SendMessageToWX.Req.WXSceneSession;
            break;
    }
    api.sendReq(req);
}

And here is my unity code:

public class test : MonoBehaviour {
   public GameObject btnObj;
   // Use this for initialization
   void Start () {
      Button button = btnObj.GetComponent<Button>();
      button.onClick.AddListener(share);
  }

  // Update is called once per frame
  void Update () {

  }

  void share()
  {
      AndroidJavaClass jc = new    AndroidJavaClass("com.unity3d.player.UnityPlayer");
      AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
      jo.Call("shareToWX", "unity test",0);
  }
 }

Manifest.xml:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.yrgame.wjqpyx">

<application android:allowBackup="true" android:label="@string/app_name"
    android:supportsRtl="true">
    <activity android:name="com.yrgame.wjqpyx.wxapi.WXEntryActivity"/>
</application>
 </manifest>

Error:

 I/Unity: AndroidJavaException: java.lang.NoSuchMethodError: no non-static method with name='shareToWX' signature='(Ljava/lang/String;I)V' in class Lcom.unity3d.player.UnityPlayerActivity;
                                                          java.lang.NoSuchMethodError: no non-static method with name='shareToWX' signature='(Ljava/lang/String;I)V' in class Lcom.unity3d.player.UnityPlayerActivity;
                                                              at com.unity3d.player.ReflectionHelper.getMethodID(Unknown Source)
                                                              at com.unity3d.player.UnityPlayer.nativeRender(Native Method)
                                                              at com.unity3d.player.UnityPlayer.c(Unknown Source)
                                                              at com.unity3d.player.UnityPlayer$c$1.handleMessage(Unknown Source)
                                                              at android.os.Handler.dispatchMessage(Handler.java:98)
                                                              at android.os.Looper.loop(Looper.java:136)
                                                              at com.unity3d.player.UnityPlayer$c.run(Unknown Source)
                                                            at UnityEngine.AndroidJNISafe.CheckException () [0x00000] in <filename unknown>:0 
                                                            at UnityEngine.AndroidJNISafe.CallStaticObjectMethod (IntPtr clazz, IntPtr methodID, UnityEngine.jvalue[] args) [0x00000] in <filename unknown>:0 
                                                            at UnityEngine.AndroidReflection.GetMetho

Please give me a hand!!!

Upvotes: 2

Views: 13032

Answers (2)

정영민
정영민

Reputation: 11

Unity Code(C#)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainManager : MonoBehaviour
{
    public Button button;
    // Start is called before the first frame update
    void Start()
    {
        button.onClick.AddListener(() =>
        {
            CallAndroidMethod("receiveStr", "howru");
        });
    }
    // 첫 번쨰 방식
    public static void CallAndroidMethod(string methodName, string str)
    {
        using (var clsUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) // "com.pingtech.swingtracker.UnityPlayerActivity"))
        {
            using (var objActivity = clsUnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
            {
                objActivity.Call(methodName, str);
            }
        }
    }

    public static void sendStr(string str)
    {
        CallAndroidMethod("receiveStr", str);
    }
}

Android Code(Java)

import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.os.Process;

public class UnityPlayerActivity extends Activity implements IUnityPlayerLifecycleEvents
{
    protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code

    // Override this in your custom UnityPlayerActivity to tweak the command line arguments passed to the Unity Android Player
    // The command line arguments are passed as a string, separated by spaces
    // UnityPlayerActivity calls this from 'onCreate'
    // Supported: -force-gles20, -force-gles30, -force-gles31, -force-gles31aep, -force-gles32, -force-gles, -force-vulkan
    // See https://docs.unity3d.com/Manual/CommandLineArguments.html
    // @param cmdLine the current command line arguments, may be null
    // @return the modified command line string or null
    protected String updateUnityCommandLineArguments(String cmdLine)
    {
        return cmdLine;
    }

    // Setup activity layout
    @Override protected void onCreate(Bundle savedInstanceState)
    {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);

        String cmdLine = updateUnityCommandLineArguments(getIntent().getStringExtra("unity"));
        getIntent().putExtra("unity", cmdLine);

        mUnityPlayer = new UnityPlayer(this, this);
        setContentView(mUnityPlayer);
        mUnityPlayer.requestFocus();
    }

    // When Unity player unloaded move task to background
    @Override public void onUnityPlayerUnloaded() {
        moveTaskToBack(true);
    }

    // Callback before Unity player process is killed
    @Override public void onUnityPlayerQuitted() {
    }

    @Override protected void onNewIntent(Intent intent)
    {
        // To support deep linking, we need to make sure that the client can get access to
        // the last sent intent. The clients access this through a JNI api that allows them
        // to get the intent set on launch. To update that after launch we have to manually
        // replace the intent with the one caught here.
        setIntent(intent);
        mUnityPlayer.newIntent(intent);
    }

    // Quit Unity
    @Override protected void onDestroy ()
    {
        mUnityPlayer.destroy();
        super.onDestroy();
    }

    // If the activity is in multi window mode or resizing the activity is allowed we will use
    // onStart/onStop (the visibility callbacks) to determine when to pause/resume.
    // Otherwise it will be done in onPause/onResume as Unity has done historically to preserve
    // existing behavior.
    @Override protected void onStop()
    {
        super.onStop();

        if (!MultiWindowSupport.getAllowResizableWindow(this))
            return;

        mUnityPlayer.pause();
    }

    @Override protected void onStart()
    {
        super.onStart();

        if (!MultiWindowSupport.getAllowResizableWindow(this))
            return;

        mUnityPlayer.resume();
    }

    // Pause Unity
    @Override protected void onPause()
    {
        super.onPause();

        MultiWindowSupport.saveMultiWindowMode(this);

        if (MultiWindowSupport.getAllowResizableWindow(this))
            return;

        mUnityPlayer.pause();
    }

    // Resume Unity
    @Override protected void onResume()
    {
        super.onResume();

        if (MultiWindowSupport.getAllowResizableWindow(this) && !MultiWindowSupport.isMultiWindowModeChangedToTrue(this))
            return;

        mUnityPlayer.resume();
    }

    // Low Memory Unity
    @Override public void onLowMemory()
    {
        super.onLowMemory();
        mUnityPlayer.lowMemory();
    }

    // Trim Memory Unity
    @Override public void onTrimMemory(int level)
    {
        super.onTrimMemory(level);
        if (level == TRIM_MEMORY_RUNNING_CRITICAL)
        {
            mUnityPlayer.lowMemory();
        }
    }

    // This ensures the layout will be correct.
    @Override public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        mUnityPlayer.configurationChanged(newConfig);
    }

    // Notify Unity of the focus change.
    @Override public void onWindowFocusChanged(boolean hasFocus)
    {
        super.onWindowFocusChanged(hasFocus);
        mUnityPlayer.windowFocusChanged(hasFocus);
    }

    // For some reason the multiple keyevent type is not supported by the ndk.
    // Force event injection by overriding dispatchKeyEvent().
    @Override public boolean dispatchKeyEvent(KeyEvent event)
    {
        if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
            return mUnityPlayer.injectEvent(event);
        return super.dispatchKeyEvent(event);
    }

    // Pass any events not handled by (unfocused) views straight to UnityPlayer
    @Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }
    @Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }
    /*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }

    public void receiveStr(String str) {
        Log.e(this.toString(), "receiveStr=" + str);
    }
}

Unity method code and Android method code must match. ex: Unity:"receiveStr" == Android="receiveStr"

Upvotes: 1

Michelle Morry
Michelle Morry

Reputation: 61

I believe it is because you have not declared your manifest correctly so it is still using the normal UnityPlayerActivity instead of your custom one.

Specifically adding this inside the activity tag in the manifest:

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

Check out the example that Unity gives here: https://docs.unity3d.com/Manual/AndroidUnityPlayerActivity.html

Upvotes: 2

Related Questions