env->GetMethodID returns null

eray_ozr
Wed, 08 Feb 2023 23:02:15 +0000
Mobile

I need to use JNI to start an NSD service on mobile (For NDI android plugin).
I can package my app but it crashes when I call JNI because it can not find MethodID.

Other C++ codes (for example NSI SDK) works because I can use it with NDI HX Camera’s NSD service without a problem.

My Java code in UPL.xml is this.

	<gameActivityImportAdditions>
		<if condition="bCpuArchSupported">
			<insert>
				import android.os.IBinder;
				import android.app.Service;
				import android.net.nsd.NsdManager;
				import android.net.nsd.NsdServiceInfo;
			</insert>
		</if>
	</gameActivityImportAdditions>

	<gameActivityClassAdditions>
		<if condition="bCpuArchSupported">
			<insert>
				public NsdManager nsdManager;
				public NsdServiceInfo nsdServiceInfo;
				NsdManager.RegistrationListener listener;

				public void startNsdService(int Port, String ServiceName) {
				nsdManager = (NsdManager)Get().getApplicationContext().getSystemService(Context.NSD_SERVICE);

				nsdServiceInfo = new NsdServiceInfo();
				nsdServiceInfo.setServiceName(ServiceName);
				nsdServiceInfo.setServiceType("_ndi._tcp.");
				nsdServiceInfo.setPort(Port);

				nsdManager.registerService(nsdServiceInfo, NsdManager.PROTOCOL_DNS_SD, new NsdManager.RegistrationListener() {

				@Override
				public void onRegistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {}

				@Override
				public void onUnregistrationFailed(NsdServiceInfo nsdServiceInfo, int i) {}

				@Override
				public void onServiceRegistered(NsdServiceInfo nsdServiceInfo) {}

				@Override
				public void onServiceUnregistered(NsdServiceInfo nsdServiceInfo) {}
				});
				}
			</insert>
		</if>
	</gameActivityClassAdditions>

	<proguardAdditions>
		<if condition="bCpuArchSupported">
			<insert>

				-keepattributes Signature,MethodParameters,InnerClasses
				-dontskipnonpubliclibraryclassmembers
				-keepclassmembers class com.epicgames.unreal.GameActivity

			</insert>
		</if>
	</proguardAdditions>

In order to call it I use this C++ code.

	JNIEnv* env = FAndroidApplication::GetJavaEnv(true);

	if (FJavaWrapper::GameActivityClassID == nullptr)
	{
		OutCode = "Unable to get GameActivity class.";
		return false;
	}

	jmethodID MethodID = env->GetMethodID(FJavaWrapper::GameActivityClassID, "startNsdService", "(ILjava/lang/String;)V");

	if (MethodID == nullptr)
	{
		OutCode = "Unable to find \"startNsdService\" Java method in GameActivity class. Look at NDI_UPL_Android.xml";
		return false;
	}

	auto ServiceName = env->NewStringUTF(TCHAR_TO_UTF8(*In_Name_Stream));

	FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityClassID, MethodID, In_Port, *ServiceName);

Also tried these

I added UPL.xml and PrivateDependencyModuleNames.Add(“Launch”); to my build.cs for Android platform.

I tried FJavaWrapper::GetMethod()

I got method’s signature from “javac -h” and “javap -s”.

I changed method’s arguments and signature to “()V”

I tried to delete proguard section from UPL.xml

I tried to add my java code in a class but FindClass functions didn’t find that class.
There are samples for additions without class.
https://github.com/EpicGames/UnrealEngine/blob/46544fa5e0aa9e6740c19b44b0628b72e7bbd5ce/Engine/Plugins/Online/OnlineSubsystemGoogle/Source/OnlineSubsystemGoogle_UPL.xml

I tried Shipping Build

My log’s last section.

[2023.02.08-22.33.41:076][427]LogBlueprintUserMessages: [UI_Capture_Devices_C_2147482447] Unable to find "startNsdService" Java method in GameActivity class. Look at NDI_UPL_Android.xml

5 posts - 2 participants