[Android][UE 5.3] Start an In-App Purchase Crash (w/ Callstack)

Crash calling Start an In-App Purchase in Blueprints in Unreal 5.3. Make an In-App Purchase v2 also crashes with the same error. In Unreal 4.27 Make an In-App Purchase v2 works fine.

When I use UE 5.3 and Android Target SDK 29 it works perfectly. When I upgrade to Target SDK >=30 a Java JNI crash occurs.

The call inside of:

AndroidJNI.cpp:
AndroidThunkCpp_Iap_BeginPurchase()

FJavaHelper::ToJavaStringArray() is failing on this call:
jclass JavaStringClass = AndroidJavaEnv::FindJavaClass(“java/lang/String”);
FJavaHelper::ToJavaStringArray() did not exist in UE 5.2, it is new in UE 5.3.

Here’s the callstack:

Assertion failed: false && “Java JNI call failed with an exception.” [File:./Runtime/Core/Private/Android/AndroidJavaEnv.cpp] [Line: 231]

D/UE : [2023.09.27-15.40.08:906][935]Assertion failed: false && “Java JNI call failed with an exception.” [File:./Runtime/Core/Private/Android/AndroidJavaEnv.cpp] [Line: 231]
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: === Critical error: ===
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: Assertion failed: false && “Java JNI call failed with an exception.” [File:./Runtime/Core/Private/Android/AndroidJavaEnv.cpp] [Line: 231]
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error:
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C8B6A89C libUnreal.so(0x0000000009F6189C)!FJavaHelper::ToJavaStringArray(_JNIEnv*, TArray<TStringView<char16_t>, TSizedDefaultAllocator<32> > const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D0089FB8 libUnreal.so(0x0000000011480FB8)!AndroidThunkCpp_Iap_BeginPurchase(TArray<TStringView<char16_t>, TSizedDefaultAllocator<32> > const&, FString const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D2EE1164 libUnreal.so(0x00000000142D8164)!FOnlinePurchaseGooglePlay::Checkout(FUniqueNetId const&, FPurchaseCheckoutRequest const&, TDelegate<void (FOnlineError const&, TSharedRef<FPurchaseReceipt, (ESPMode)1> const&), FDefaultDelegateUserPolicy> const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D027C744 libUnreal.so(0x0000000011673744)!UInAppPurchaseCheckoutCallbackProxy::TriggerCheckout(APlayerController*, FInAppPurchaseProductRequest2 const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D027BCD0 libUnreal.so(0x0000000011672CD0)!UInAppPurchaseCheckoutCallbackProxy::execCreateProxyObjectForInAppPurchaseCheckout(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C985C3C8 libUnreal.so(0x000000000AC533C8)!UObject::execCallMathFunction(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C986A1F4 libUnreal.so(0x000000000AC611F4)!UObject::execLetObj(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C985EE64 libUnreal.so(0x000000000AC55E64)!ProcessLocalScriptFunction(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C985E2E4 libUnreal.so(0x000000000AC552E4)!void ProcessScriptFunction<void ()(UObject, FFrame&, void*)>(UObject*, UFunction*, FFrame&, void*, void ()(UObject, FFrame&, void*))
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9860208 libUnreal.so(0x000000000AC57208)!ProcessLocalFunction(UObject*, UFunction*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C985EE64 libUnreal.so(0x000000000AC55E64)!ProcessLocalScriptFunction(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C985E9F8 libUnreal.so(0x000000000AC559F8)!UObject::ProcessInternal(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C95B6ACC libUnreal.so(0x000000000A9ADACC)!UFunction::Invoke(UObject*, FFrame&, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9864A48 libUnreal.so(0x000000000AC5BA48)!UObject::ProcessEvent(UFunction*, void*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C989D648 libUnreal.so(0x000000000AC94648)!void TMulticastScriptDelegate::ProcessMulticastDelegate(void*) const
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075CD85D274 libUnreal.so(0x000000000EC54274)!UButton::SlateHandleReleased()
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075CD8C07C0 libUnreal.so(0x000000000ECB77C0)!TBaseUObjectMethodDelegateInstance<false, UButton, void (), FDefaultDelegateUserPolicy>::ExecuteIfSafe() const
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C8BA848C libUnreal.so(0x0000000009F9F48C)!bool TDelegate<void (), FDefaultDelegateUserPolicy>::ExecuteIfBound<void, (void*)0>() const
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9EDC6E4 libUnreal.so(0x000000000B2D36E4)!SButton::Release()
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9EDC0F0 libUnreal.so(0x000000000B2D30F0)!SButton::OnMouseButtonUp(FGeometry const&, FPointerEvent const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9C8FD5C libUnreal.so(0x000000000B086D5C)!FSlateApplication::RoutePointerUpEvent(FWidgetPath const&, FPointerEvent const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9C5631C libUnreal.so(0x000000000B04D31C)!FSlateApplication::ProcessMouseButtonUpEvent(FPointerEvent const&)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9C98A4C libUnreal.so(0x000000000B08FA4C)!FSlateApplication::OnTouchEnded(UE::Math::TVector2 const&, int, FPlatformUserId, FInputDeviceId)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C998F35C libUnreal.so(0x000000000AD8635C)!FGenericApplicationMessageHandler::OnTouchEnded(UE::Math::TVector2 const&, int, int)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C9975C80 libUnreal.so(0x000000000AD6CC80)!FAndroidInputInterface::SendControllerEvents()
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075C99748DC libUnreal.so(0x000000000AD6B8DC)!FAndroidApplication::PollGameDeviceState(float)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D0094CD8 libUnreal.so(0x000000001148BCD8)!FEngineLoop::Tick()
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D008E600 libUnreal.so(0x0000000011485600)!AndroidMain(android_app*)
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D009DB10 libUnreal.so(0x0000000011494B10)!android_main()
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x00000075D00C64C0 libUnreal.so(0x00000000114BD4C0)Unknown
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x000000796E3EAE48 libc.so(0x00000000000B6E48)Unknown
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error: [Callstack] 0x000000796E387458 libc.so(0x0000000000053458)Unknown
D/UE : [2023.09.27-15.40.08:907][935]LogAndroid: Error:
D/UE : [2023.09.27-15.40.08:917][935]LogExit: Executing StaticShutdownAfterError
D/UE : [2023.09.27-15.40.08:917][935]LogAndroid: FAndroidMisc::RequestExit(1, FAndroidErrorOutputDevice::Serialize.!GIsGuarded)

Do Android In-App Purchases work for anyone with UE 5.3 and Android Target SDK >=30?

Hi, it doesn’t work for me neither :frowning:

Same thing here :frowning:
Kindly let me know if you find a solution and I will do the same!

While we are here, do you guys know how to upgrade “play-services-ads-lite:18.1.0” and “androidx.fragment:fragment”?

I have these 2 warnings when I try to upload a game on the Play Console.

IAP doesn’t work anymore and Ads won’t soon, why does Epic hate mobile devs so much xD

2 Likes

To solve this issue you can replace:
AndroidJavaEnv::FindJavaClass(“java/lang/String”);
with:
FJavaWrapper::FindClass(Env,“java/lang/String”,false);
in the AndroidJavaEnv.cpp

1 Like

Thank you, I will try this.

Does In-App purchases work for anyone in UE 5.3 on iOS? I haven’t been able to get it working either, due to this error:

UInAppPurchaseCallbackProxy::Trigger - Invalid player UniqueNetId

This is happening because in the InAppPurchaseCheckoutCallbackProxy::TriggerCheckout() function, this line is failing on IsValid() check:

if( FUniqueNetIdRepl PurchasingPlayer = PlayerController->GetLocalPlayer()->GetUniqueNetIdFromCachedControllerId(); PurchasingPlayer.IsValid())

I don’t have any IOS device to test this, but here are some facts about this:

  1. Android implementation never used UniqueNetId in App-Purchase.
  2. Function declaration in LocalPlayer.h (line: 493):
    // This should be deprecated when engine code has been changed to expect FPlatformUserId
    // UE_DEPRECATED(5.x, “Use GetUniqueNetIdForPlatformUser instead”)
    ENGINE_API FUniqueNetIdRepl GetUniqueNetIdFromCachedControllerId() const;
  3. GetUniqueNetIdForPlatformUser() and GetUniqueNetIdFromCachedControllerId() have the same implementation in LocalPlayer.cpp on UE 5.3.

On Android I just commented all places where IsValid() was called, because NetId is never used. I think similar situation is on IOS, because there is no need for application to have this information.

What’s intriguing about this to me is, how is it possible that in-app purchases are completely broken for both Android and iOS? Is it possible we are doing something wrong with our setups? Because I don’t know how this wouldn’t be a bigger issue.

@marekpawlowski Are you also seeing the same crash on Android since you don’t have iOS to test the other issue? And did that fix it for you?

I tried commenting out the IsValid() line on iOS but nothing happened and it didn’t seem to work. Trying to get more debug info. Compiling/building on Mac is a nightmare.

@gf11speed Do you compile on a source build? I had the same errors as you.

My setup is: UE 5.3, but I don’t want to use source build. I had to find some workaround. I downloaded only this folder:
https://github.com/EpicGames/UnrealEngine/tree/5.3/Engine/Plugins/Online
and put all of the files in: MyProject/Plugins/ (without online folder). Reopened the whole project and then I’ve got that OnlineSubsystem, OnlineSubsystem Google and OnlineSubsystem GooglePlay are recognize as project plugins and not as built-in plugins in Edit->Plugins window.

I had the error with PurchasingPlayer.IsValid(). I disabled every nullptr check connected with GetUniqueNetIdFromCachedControlledId(). Then I got the issue: Assertion failed: false && “Java JNI call failed with an exception.” in AndroidJavaEnv.cpp.
To solve this I’ve created the custom .h file in the folder: Android\OnlineSubsystemGooglePlay\Source\Private
Code inside my created file:

#include "Android/AndroidJNI.h"

#include "Android/AndroidJavaEnv.h"
#include "CoreMinimal.h"
#include "HAL/ThreadSingleton.h"
#include "HAL/PlatformMisc.h"
#include "HAL/ThreadManager.h"
#include "Containers/UnrealString.h"

#include "Android/AndroidApplication.h"
#include "Android/AndroidInputInterface.h"
#include "Android/AndroidPlatformCrashContext.h"
#include "Android/AndroidStats.h"
#include "Async/TaskGraphInterfaces.h"
#include "HAL/ExceptionHandling.h"
#include "HAL/PlatformStackWalk.h"
#include "Math/Vector.h"
#include "Misc/ConfigCacheIni.h"
#include "Misc/CoreDelegates.h"
#include "Misc/DateTime.h"
#include "Misc/EmbeddedCommunication.h"
#include "Misc/FeedbackContext.h"
#include "UnrealEngine.h"
#include "Widgets/Input/IVirtualKeyboardEntry.h"

THIRD_PARTY_INCLUDES_START
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
THIRD_PARTY_INCLUDES_END

#define JNI_CURRENT_VERSION JNI_VERSION_1_6

FScopedJavaObject<jobjectArray> ToJavaStringArray_v2(JNIEnv* Env, const TArray<FStringView>& UnrealStrings)
{
	jclass JavaStringClass = FJavaWrapper::FindClass(Env,"java/lang/String",false);
	jobjectArray ObjectArray = Env->NewObjectArray((jsize)UnrealStrings.Num(), JavaStringClass, NULL);
	for (int32 Idx = 0; Idx < UnrealStrings.Num(); ++Idx)
	{
		// FStringView of an empty FString contains a null pointer as data
		if (UnrealStrings[Idx].GetData())
		{
			Env->SetObjectArrayElement(ObjectArray, Idx, Env->NewStringUTF(TCHAR_TO_UTF8(UnrealStrings[Idx].GetData())));
		}
		else
		{
			Env->SetObjectArrayElement(ObjectArray, Idx, Env->NewStringUTF(""));
		}
	}
	return NewScopedJavaObject(Env, ObjectArray);
}

bool AndroidThunkCpp_Iap_BeginPurchase_v2(const TArray<FStringView>& ProductIds, const FString& AccountId)
{
	FPlatformMisc::LowLevelOutputDebugStringf(TEXT("[JNI] - AndroidThunkCpp_Iap_BeginPurchase_v2"));
	FPlatformMisc::LowLevelOutputDebugStringf(TEXT("ProductIds.size()=%d"), ProductIds.Num());
	FPlatformMisc::LowLevelOutputDebugStringf(TEXT("ProductIds[0]=%s"),*static_cast<FString>(ProductIds[0]));
	bool bResult = false;
	if (JNIEnv* Env = FAndroidApplication::GetJavaEnv())
	{
		//CHECK_JNI_METHOD(FJavaWrapper::AndroidThunkJava_IapBeginPurchase);

		auto ProductIdsJava = ToJavaStringArray_v2(Env, ProductIds);
		if (AccountId.IsEmpty())
		{
			FPlatformMisc::LowLevelOutputDebugStringf(TEXT("AccountId is Empty"));

			bResult = FJavaWrapper::CallBooleanMethod(Env, FJavaWrapper::GoogleServicesThis, FJavaWrapper::AndroidThunkJava_IapBeginPurchase, *ProductIdsJava, nullptr);
		}
		else
		{
			FPlatformMisc::LowLevelOutputDebugStringf(TEXT("AccountId is not Empty"));
			auto ObfuscatedAccountIdJava = FJavaHelper::ToJavaString(Env, AccountId);
			bResult = FJavaWrapper::CallBooleanMethod(Env, FJavaWrapper::GoogleServicesThis, FJavaWrapper::AndroidThunkJava_IapBeginPurchase, *ProductIdsJava, *ObfuscatedAccountIdJava);
		}
	}

	return bResult;
}

I had to do this because I can’t change any function in runtime folder in my engine. And of course I added include<MyFile.h> in OnlinePurchaseGooglePlay.cpp and replaced original line:

bStarted = AndroidThunkCpp_Iap_BeginPurchase(ProductIds, AccountId);

to use my code with this line:

bStarted = AndroidThunkCpp_Iap_BeginPurchase_v2(ProductIds, AccountId);

I got the last error in GooglePlayStoreHelper.java. I changed line 41 to: private boolean bIsIapSetup = true;

I packaged my game upload to google play console and I think it’s work fine. I use: Restore In-App Purchase, Make In-App Purchase and Finalize In-App Purchase.

This is my whole solution to repair In-App Purchase in my project on Android devices.

Edit: I use only non-consumable products in my game.

What do you mean you disabled every null check associated with GetUniqueNetIdFromCachedControllerId()? You mean every IsValid() call made on the object returned from GetUniqueNetIdFromCachedControllerId()?

I tried making IsValid() explictly return true but hit another crash when doing so on iOS.

My purchases ARE consumables.

Was anyone able to find a fix for both Android and iOS? My game is fully ready it’s just missing In-App Purchases so I can release it :smiling_face_with_tear:

I haven’t tried marekpawlowski’s solution yet but that sounds reasonable for an Android fix. As far as iOS, I don’t have a potential solution yet.

Great news! Well, I still haven’t figured out how to get In-App Purchases working with the built in UE 5.3 code for neither Android or iOS. I think it’s broken and Epic doesn’t care.

Good news is, I got it working using a plugin available on marketplace. It’s a custom solution for both Android/iOS. The flow is slightly different on each platform with the plugin but it isn’t bad. Most importantly, I just got it implemented in my game and IT WORKS! I would highly recommend going this route if you need In-App Purchases working for you game:

Monetization Goodies

I am on the same boat as everybody else in this thread. It’s absolutely ridiculous how something as basic as InApp purchases is not working.

2 Likes

Hey did you end up find a solution for this?

There is pretty much no solution for 5.3. The API just won’t work because of the IAP node rework.

Maybe it will be fixed in 5.4, but for now the only solution is to use 5.2 or a specific plug-in :slight_smile:

i did this but it didnt change, still crashes

edit: also if first time running the source code things=, you can use crtl+f5 to build without errors,

100$ for an iap, its great but i havent even published my first game

1 Like

Hi! Did someone figure out how to solve this problem? I’ve tried different ways, still no success however… Same situation as @araz01, I don’t have spare 100$ for IAP

yeah, ditch ads and iaps, or buy the plugin. for me paid is easiest route and good price like 0.79p