2023-01-19 330
我试图从c#调用Java方法,从Java称为这样的Java:
EgamePay.pay(thisActivity, payAlias, new EgamePayListener() {
@Override
public void paySuccess(String alias) {
}
@Override
public void payFailed(String alias, int errorInt) {
}
@Override
public void payCancel(String alias) {
}
});
前两个参数还可以,但是如何通过c#传递egamepaylistner?简单地创建具有相同函数的C#类是行不通的…
这是我目前正在做的:
using (AndroidJavaClass jc = new AndroidJavaClass("cn.egame.terminal.smspay.EgamePay"))
{
System.IntPtr cls_Activity = AndroidJNI.FindClass("com/unity3d/player/UnityPlayer");
System.IntPtr fid_Activity = AndroidJNI.GetStaticFieldID(cls_Activity, "currentActivity", "Landroid/app/Activity;");
object[] p = { fid_Activity, "payAlias", new EgamePayListener() };
jc.CallStatic("pay", p);
}
..
class EgamePayListener
{
public void paySucess(string alias)
{
}
public void payFailed(string alians, int errorInt)
{
}
public void payCancel(string alias)
{
}
}
显然这是错误的,我该如何处理这种情况,以便在发射这些功能时可以在C#土地上收到通知?
如果您处于Unity3D的上下文中,那么从Java本机代码到Unity3D C#脚本进行交互的更好方法将是调用UnitySendMessage方法.您可以在Java代码中调用此方法,并将消息发送到C#,因此您可以在C#中执行指定的方法.
.
您可以在Unity场景中添加GameObject,并创建一个包含这三种方法的Monobehavior脚本(PaySucess(字符串消息),PayFailed(字符串消息)和PayCancel(Message)).然后将新创建的脚本连接到GameObject(让我们假设此GameObject的名称为” PayListener”),并确保执行Java代码时在场景中存在的GameObject(您可以调用 DontDestroyOnLoad 在Awake中的gameObject上).
然后,在您的Java代码中,只需写下这些:
EgamePay.pay(thisActivity, payAlias, new EgamePayListener() {
@Override
public void paySuccess(String alias) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","paySuccess", alias);
}
@Override
public void payFailed(String alias, int errorInt) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","payFailed", alias + "#" + errorInt);
}
@Override
public void payCancel(String alias) {
com.unity3d.player.UnityPlayer.UnitySendMessage("PayListener","payCancel", alias);
}
});
它将阻止Java文件在没有com.unity3d.player.UnityPlayer类的情况下成功构建.您可以找到/Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/bin/classes.jar文件,并将其添加为Java项目的依赖项库.然后,您可以构建,生成和使用新的JAR文件而无需错误.
由于使用UnitySendMessage方法只能采用1个参数,因此您可能必须通过策略连接payFailed结果别名和错误int,然后将其解析为Unity C#side.
通过使用新的已建立jar文件并将其加载为AndroidJavaClass或AndroidJavaObject,当调用Java中的一个时,应调用PayListener脚本中的相应方法.
有关UnitySendMessage的Android插件的文档,您可以访问如何实现Android JNI插件的官方指南在这里,在示例3中.
您可以通过参考将这些项目链接在一起.从这里开始,您应该能够填充其他层(JNI/Java),然后开始在系统周围传递指针(长时间)并调用您的功能.
program.cs
namespace CSharpLayer
{
class Program : CLILayer.CLIObject
{
static void Main(string[] args)
{
Program p = new Program();
p.invokeJava();
}
public void invokeJava()
{
//Call into CLI layer function to loadJVM, call Java code, etc
loadJava();
}
public override void callback(string data)
{
//This will be called from the CLI Layer.
}
}
}
cliObject.h
#pragma once
namespace CLILayer
{
public ref class CLIObject
{
public:
CLIObject();
~CLIObject();
void loadJava(System::String^ jvm, System::String^ classpath);
virtual void callback(System::String^ data) = 0;
};
}
cliObject.cpp
#include "CLIObject.h"
#include <string>
#include <msclr/marshal_cppstd.h>
#include <msclr/marshal.h>
using namespace msclr::interop;
using namespace CLILayer;
CLIObject::CLIObject()
{
}
CLIObject::~CLIObject()
{
}
CLIObject::loadJava(System::String^ jvmLocaion, System::String^ classpath)
{
std::string _jvmLoc = marshal_as<std::string>(jvmLocation);
std::string _classpath = marshal_as<std::string>(classpath);
}
这是 jni字段描述符
JavaLanguage Type
--------------------------------
Z boolean
B byte
C char
S short
I int
J long
F float
D double
Ljava/lang/String; string
[Ljava/lang/Object; object[]
方法描述符利用字段描述符,并描述Java方法的结构.方法描述符中的字段描述符之间没有空格.
除了用V表示的void返回类型外,所有其他返回类型都使用字段描述符.下表描述了Java方法声明和相应的JNI描述符.从C#通过JNI调用JNI方法描述符.
Java Method Declaration JNI Method Descriptor
----------------------------------------------------
String foo(); "()Ljava/lang/String;"
Void bar(int I, bool b); (IZ)V
需要完成的第一件事是创建一个字典对象,该对象将包含所有参数传递给Java虚拟机.在下面的示例中,我正在竭尽全力设置类路径,以告诉JVM在哪里寻找类和软件包.
private Dictionary<string, string> jvmParameters = new Dictionary<string, string>();
jvmParameters.Add("-Djava.class.path", Location of the java class);
一旦将JVM参数分配给字典对象,就可以创建Javanative Interface的实例.创建后,需要使用JVM参数调用方法loadJVM,然后将加载Java虚拟机.加载后,用户调用了实例化Java对象的方法(请注意,该方法的使用InstantiateJavaObject是可选的,因为用户可能只想调用静态方法,在这种情况下,无需调用此方法;但是,此方法不需要;但是,不会造成任何伤害).
Java = new JavaNativeInterface();
Java.LoadVM(jvmParameters, false);
Java.InstantiateJavaObject(Name of the java class excluding the extension);
一旦加载了JVM并实例化了类,用户可以调用他们希望的任何方法.首先创建一个将包含所有参数传递到Java方法的对象列表.由于它是一个对象列表,因此可以将不同类型的参数保存,因为一切都从对象继承.
List<object> olParameters = new List<object>();
olParameters.Add(Value of the parameter to be passed to the java method);
接下来,只需将Java方法的返回类型中的通用方法调用作为模板类型.在下面的示例中,我正在调用CallMethod,这意味着我要调用的Java方法的返回类型是字符串.
接下来,以呼叫的Java方法的名称和方法描述符(请参见上文);最后,传递所有参数列表. (注意:如果不需要参数,请在空列表中传递.)
Java.CallMethod<string>("AddTwoNumbers", "(IILjava/lang/String;)I", olParameters);
好吧,我想这将其全部包裹起来,但是请记住,JNI可以做更多的事情.测试应用程序只是证明JNI组件的基础知识的一种快速而肮脏的方法.为了充分了解JNI.
您可以在此链接
以上所述是小编给大家介绍的如何将JNI C#类传递到Java或处理这种情况?,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!
原文链接:https://77isp.com/post/25787.html
=========================================
https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。
数据库技术 2022-03-28
网站技术 2022-11-26
网站技术 2023-01-07
网站技术 2022-11-17
Windows相关 2022-02-23
网站技术 2023-01-14
Windows相关 2022-02-16
Windows相关 2022-02-16
Linux相关 2022-02-27
数据库技术 2022-02-20
抠敌 2023年10月23日
嚼餐 2023年10月23日
男忌 2023年10月22日
瓮仆 2023年10月22日
簿偌 2023年10月22日
扫码二维码
获取最新动态