com.android.billingclient.api.ProductDetails ... not found

Hi Folks!

I’m trying to add Android In-App Purchase support to my JUCE app, but am getting this on app start-up:

JNI DETECTED ERROR IN APPLICATION: JNI NewGlobalRef called with pending exception java.lang.ClassNotFoundException: Didn't find class "com.android.billingclient.api.ProductDetails"

That has the look of a problem that others are very likely to have seen; but I can’t see it reported anywhere!

Can somebody please explain what I’m doing wrong?!

Best wishes, Pete

Tracked down to this:

"com/rmsl/juce/JuceBillingClient"

Failing to load, in:

void JNIClassBase::initialise (JNIEnv* env)

OK, all resolved. I had to add JuceBillingClient.java to my project.

I simply couldn’t find that documented anywhere :slight_smile:

Pete

Most JUCE Java classes are loaded from precompiled bytecode, but I found it difficult to get this working for the JuceBillingClient. Specifically, I was able to precompile the class, but at runtime I was getting the following error, followed by a crash:

java.lang.ClassNotFoundException: Didn't find class "com.android.billingclient.api.PurchasesUpdatedListener" on path: DexPathList[[dex file "InMemoryDexFile[cookie=[0, 493697350096]]"],nativeLibraryDirectories=[/system/lib64, /system_ext/lib64, /product/lib64]]

I’ll take another look at this now and see whether I can get it working, but I’m not particularly hopeful…

Currently, for Projucer-generated projects, the JuceBillingClient.java is automatically added to the app’s gradle config. This is probably the reason that this issue hasn’t been reported by other users.

1 Like

Thanks @reuk, and no worries!

On a separate note, I’ve added Amazon App Store support for IAP purchases (added some .java, and some JNI glue). To get this working, I found that I had to patch this function:

extern "C" jint JNIEXPORT JNI_OnLoad (JavaVM* vm, void*)

Reason was here:

https://developer.android.com/training/articles/perf-jni

You can get into trouble if you create a thread yourself (perhaps by calling pthread_create and then attaching it with AttachCurrentThread). Now there are no stack frames from your application. If you call FindClass from this thread, the JavaVM will start in the “system” class loader instead of the one associated with your application, so attempts to find app-specific classes will fail.

There are a few ways to work around this:

Do your FindClass lookups once, in JNI_OnLoad, and cache the class references for later use. Any FindClass calls made as part of executing JNI_OnLoad will use the class loader associated with the function that called System.loadLibrary (this is a special rule, provided to make library initialization more convenient). If your app code is loading the library, FindClass will use the correct class loader.

Best wishes,

Pete

Thanks for your patience, we now bundle pre-generated bytecode for the juce_product_unlocking module:

Thanks @reuk!

It’d be useful if there were an easy way to extend JNI_OnLoad, rather than by having to patch the JUCE source code!

Best wishes, Pete