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.
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.