"jmethodID was NULL" error when calling DeviceManager.initialiseWithDefaultDevices()

Using Projucer, I created a very basic library for Android, so I can play audio in a third party Android app (actually a Flutter app).

I initiate my player like the following:

AudioSamplePlayer::AudioSamplePlayer()
{
	player = std::make_unique<juce::AudioSourcePlayer>();
	player->setSource(this);
	deviceManager.addAudioCallback(player.get());
}

When I want to start playing audio, I call the following function of my library, from my app:

void AudioSamplePlayer::demarrer()
{
	deviceManager.initialiseWithDefaultDevices(0, 2);
}

But calling that function crashes my app, with the following stacktrace (I trunked it to keep it somehow readable):

I/JUCE    (10402): JUCE Assertion failure in juce_android_Threads.cpp:320
F/jay.wezeejayla(10402): java_vm_ext.cc:594] JNI DETECTED ERROR IN APPLICATION: jmethodID was NULL
F/jay.wezeejayla(10402): java_vm_ext.cc:594]     in call to CallObjectMethodV
F/jay.wezeejayla(10402): java_vm_ext.cc:594]     from void com.wezeejay.wezeejaylab.service.lecteur.managers.LecteurAudioManager.nativePlay(long, boolean)
F/jay.wezeejayla(10402): runtime.cc:675] Runtime aborting...
F/jay.wezeejayla(10402): runtime.cc:675] Dumping all threads without mutator lock held
F/jay.wezeejayla(10402): runtime.cc:675] All threads:
F/jay.wezeejayla(10402): runtime.cc:675] DALVIK THREADS (27):
F/jay.wezeejayla(10402): runtime.cc:675] "main" prio=10 tid=1 Runnable
F/jay.wezeejayla(10402): runtime.cc:675]   | group="" sCount=0 ucsCount=0 flags=0 obj=0x736b1318 self=0xb400007b5acee2c0
F/jay.wezeejayla(10402): runtime.cc:675]   | sysTid=10402 nice=-10 cgrp=default sched=0/0 handle=0x7c9d30f500
F/jay.wezeejayla(10402): runtime.cc:675]   | state=R schedstat=( 941114858 94427503 654 ) utm=75 stm=18 core=7 HZ=100
F/jay.wezeejayla(10402): runtime.cc:675]   | stack=0x7fe0fd3000-0x7fe0fd5000 stackSize=8188KB
F/jay.wezeejayla(10402): runtime.cc:675]   | held mutexes= "abort lock" "mutator lock"(shared held)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #00 pc 00000000005376cc  /apex/com.android.art/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+128) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #01 pc 00000000006f0e24  /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool, BacktraceMap*, bool) const+236) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #02 pc 00000000006fe6b0  /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+208) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #03 pc 0000000000364174  /apex/com.android.art/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+440) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #04 pc 00000000006fce50  /apex/com.android.art/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool)+280) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #05 pc 00000000006d7ec4  /apex/com.android.art/lib64/libart.so (art::AbortState::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+212) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #06 pc 00000000006d2b24  /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+1016) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #07 pc 0000000000016ea8  /apex/com.android.art/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_3::__invoke(char const*)+80) (BuildId: b77c57f68a484ed93d5a7eda59d83bf9)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #08 pc 0000000000016450  /apex/com.android.art/lib64/libbase.so (android::base::LogMessage::~LogMessage()+352) (BuildId: b77c57f68a484ed93d5a7eda59d83bf9)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #09 pc 0000000000445224  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1612) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #10 pc 0000000000329258  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbortV(char const*, char const*, std::__va_list)+108) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #11 pc 000000000048d59c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::AbortF(char const*, ...) (.__uniq.99033978352804627313491551960229047428)+144) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #12 pc 0000000000476624  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckMethodID(_jmethodID*) (.__uniq.99033978352804627313491551960229047428)+396) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #13 pc 0000000000452e98  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*) (.__uniq.99033978352804627313491551960229047428)+1520) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #14 pc 0000000000475e2c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CheckCallArgs(art::ScopedObjectAccess&, art::(anonymous namespace)::ScopedCheck&, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, art::InvokeType, art::(anonymous namespace)::VarArgs const*) (.__uniq.99033978352804627313491551960229047428)+76) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #15 pc 0000000000474d4c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, std::__va_list, art::Primitive::Type, art::InvokeType) (.__uniq.99033978352804627313491551960229047428)+268) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #16 pc 0000000000474c18  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::CallObjectMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list) (.__uniq.99033978352804627313491551960229047428.llvm.5591279935177935698)+72) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #17 pc 0000000000136b28  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (_JNIEnv::CallObjectMethod(_jobject*, _jmethodID*, ...)+116) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #18 pc 00000000002148d0  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::audioManagerGetProperty(juce::String const&)+268) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #19 pc 0000000000137e1c  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::OboeAudioIODevice::getDefaultSampleRates()+164) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #20 pc 00000000001373e4  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::OboeAudioIODeviceType::checkAvailableDevices()+48) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #21 pc 000000000012f624  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::OboeAudioIODeviceType::OboeAudioIODeviceType()+136) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #22 pc 000000000012a690  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::AudioDeviceManager::createAudioDeviceTypes(juce::OwnedArray<juce::AudioIODeviceType, juce::DummyCriticalSection>&)+48) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #23 pc 00000000001286d0  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::AudioDeviceManager::createDeviceTypesIfNeeded()+60) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #24 pc 000000000012c0ac  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (juce::AudioDeviceManager::initialiseWithDefaultDevices(int, int)+108) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #25 pc 000000000012557c  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (wzj::AudioSamplePlayer::demarrer()+196) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #26 pc 00000000001151c4  /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/lib/arm64/libnative-lib.so (PlayAudioEngine::play(bool)+40) (BuildId: 75405f13fdb3c906e06fabc8f00faa9c800ae5d3)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #27 pc 0000000000440554  /apex/com.android.art/lib64/libart.so (art_quick_generic_jni_trampoline+148) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #28 pc 0000000000209a9c  /apex/com.android.art/lib64/libart.so (nterp_helper+1948) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #29 pc 0000000000006f88  [anon:dalvik-classes9.dex extracted in memory from /data/app/~~a2806_SuK8pzz5laqn1F8Q==/com.wezeejay.wezeejaylab-u41GDyUIXqgwZX_n7DqTrg==/base.apk!classes9.dex] (com.wezeejay.wezeejaylab.service.lecteur.managers.LecteurAudioManager.access$nativePlay)
F/jay.wezeejayla(10402): runtime.cc:675]   native: #30 pc 0000000000209334  /apex/com.android.art/lib64/libart.so (nterp_helper+52) (BuildId: 56e704c544e6c624201be2ab4933e853)

I’m not sure at all, but it looks like the JUCE framework wants to call some functions from the Android SDK, in order to get the sample rate and the buffer size of the device.

So I modified my function like this, to test on my Android device (where I already know its sample rate and buffer size, so I hardcoded them for testing purposes):

void AudioSamplePlayer::demarrer()
{
	auto deviceSetup = deviceManager.getAudioDeviceSetup();
	deviceSetup.sampleRate = 48000;
	deviceSetup.bufferSize = 192;
	deviceSetup.inputChannels = 0;
	deviceSetup.outputChannels = 2;
	deviceSetup.useDefaultInputChannels = true;
	deviceSetup.useDefaultOutputChannels = true;
	deviceManager.setAudioDeviceSetup(deviceSetup, true);
	deviceManager.initialiseWithDefaultDevices(0, 2);
}

But still the same error.

How can I fix that?

Thanks.

1 Like

You may have forgotten to call Threads::initialiseJUCE before using any JUCE code. Have a look at this post which is probably helpful:

Thanks for you answer, and sure, it looks like that’s why it’s not working.
That being said, could you give me more details on how to call initialiseJUCE from my Java/Kotlin code?

Here is what I did so far:

import com.rmsl.juce.Java

class DemoApplication : FlutterApplication()
{
	override fun onCreate()
	{
		super.onCreate()
		Java.initialiseJUCE(this)
	}
}

But it can’t find the import, so I guess a dependency is missing in my app/build.gradle file of my Android app…

Thanks for your help.

You can find the file here. Just add this java file to your android project and the code that you posted above should work.

Remember, that you need to call Threads::initialiseJUCE/com.rmsl.juce.Java.initialiseJUCE on every thread that uses JUCE.

Thanks!

OK so in my Android app (not the library project), I copied the file you mentioned, in the same package (com.rmsl.juce).

But I get the following error:

Cannot resolve corresponding JNI function Java_com_rmsl_juce_Java_initialiseJUCE__Landroid_content_Context_2.

I believe it can’t find the juce_jni native library.

I’m sure I made a stupid mistake, but I can’t figure out which one :slight_smile:

I created a very basic library for Android

The Java_com_rmsl_juce_Java_initialiseJUCE__Landroid_content_Context_2. symbol is inside the library that you created. You need to edit the name of the library (juce_jni) in the System.loadLibrary ("juce_jni") command to whatever the name of your library is.

Also, I tried another approach:

  • In my library, I created the following function:
void AudioSamplePlayer::setupAndroid(void* jniEnv, void* context)
{
	juce::Thread::initialiseJUCE(jniEnv, context);
}
  • In my Android app, I call that function like the following (I removed some extra code to make it more readable):
PlayAudioEngine::PlayAudioEngine(void* jniEnv, void* context)
{
    audioSamplePlayer.setupAndroid(jniEnv, context);
    // ...
}
  • That PlayAudioEngine class is instantiated from my native-lib file:
extern "C" JNIEXPORT jlong JNICALL Java_com_wezeejay_wezeejaylab_service_lecteur_managers_LecteurAudioManager_createEngine(JNIEnv *env, jclass, jobject context)
{
	auto *engine = new(std::nothrow) PlayAudioEngine(env, context);
	auto engineHandle = reinterpret_cast<jlong>(engine);
	return engineHandle;
}
  • And the context I pass as an argument is the context of my app, that inherits FlutterApplication which itself inherits Application.

But when I run it, I have the following error: JNI DETECTED ERROR IN APPLICATION: IsInstanceOf received NULL jclass:

F/jay.wezeejayla(29657): java_vm_ext.cc:594] JNI DETECTED ERROR IN APPLICATION: IsInstanceOf received NULL jclass
F/jay.wezeejayla(29657): java_vm_ext.cc:594]     in call to IsInstanceOf
F/jay.wezeejayla(29657): java_vm_ext.cc:594]     from long com.wezeejay.wezeejaylab.service.lecteur.managers.LecteurAudioManager.createEngine(android.content.Context, java.lang.String, java.lang.String, java.lang.String, int, int)
F/jay.wezeejayla(29657): runtime.cc:675] Runtime aborting...
F/jay.wezeejayla(29657): runtime.cc:675] Dumping all threads without mutator lock held
F/jay.wezeejayla(29657): runtime.cc:675] All threads:
F/jay.wezeejayla(29657): runtime.cc:675] DALVIK THREADS (27):
F/jay.wezeejayla(29657): runtime.cc:675] "main" prio=10 tid=1 Runnable
F/jay.wezeejayla(29657): runtime.cc:675]   | group="" sCount=0 ucsCount=0 flags=0 obj=0x736b1318 self=0xb400007b5acee2c0
F/jay.wezeejayla(29657): runtime.cc:675]   | sysTid=29657 nice=-10 cgrp=default sched=0/0 handle=0x7c9d30f500
F/jay.wezeejayla(29657): runtime.cc:675]   | state=R schedstat=( 848214421 51364581 523 ) utm=71 stm=13 core=7 HZ=100
F/jay.wezeejayla(29657): runtime.cc:675]   | stack=0x7fe0fd3000-0x7fe0fd5000 stackSize=8188KB
F/jay.wezeejayla(29657): runtime.cc:675]   | held mutexes= "abort lock" "mutator lock"(shared held)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #00 pc 00000000005376cc  /apex/com.android.art/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+128) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #01 pc 00000000006f0e24  /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool, BacktraceMap*, bool) const+236) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #02 pc 00000000006fe6b0  /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+208) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #03 pc 0000000000364174  /apex/com.android.art/lib64/libart.so (art::ThreadList::RunCheckpoint(art::Closure*, art::Closure*)+440) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #04 pc 00000000006fce50  /apex/com.android.art/lib64/libart.so (art::ThreadList::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool)+280) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #05 pc 00000000006d7ec4  /apex/com.android.art/lib64/libart.so (art::AbortState::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+212) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #06 pc 00000000006d2b24  /apex/com.android.art/lib64/libart.so (art::Runtime::Abort(char const*)+1016) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #07 pc 0000000000016ea8  /apex/com.android.art/lib64/libbase.so (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_3::__invoke(char const*)+80) (BuildId: b77c57f68a484ed93d5a7eda59d83bf9)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #08 pc 0000000000016450  /apex/com.android.art/lib64/libbase.so (android::base::LogMessage::~LogMessage()+352) (BuildId: b77c57f68a484ed93d5a7eda59d83bf9)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #09 pc 0000000000445224  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbort(char const*, char const*)+1612) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #10 pc 0000000000329258  /apex/com.android.art/lib64/libart.so (art::JavaVMExt::JniAbortV(char const*, char const*, std::__va_list)+108) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #11 pc 000000000048d59c  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::AbortF(char const*, ...) (.__uniq.99033978352804627313491551960229047428)+144) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #12 pc 0000000000454cfc  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::CheckInstance(art::ScopedObjectAccess&, art::(anonymous namespace)::ScopedCheck::InstanceKind, _jobject*, bool) (.__uniq.99033978352804627313491551960229047428)+932) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #13 pc 0000000000452fac  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::(anonymous namespace)::JniValueType*) (.__uniq.99033978352804627313491551960229047428)+1796) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #14 pc 00000000005ca318  /apex/com.android.art/lib64/libart.so (art::(anonymous namespace)::CheckJNI::IsInstanceOf(_JNIEnv*, _jobject*, _jclass*) (.__uniq.99033978352804627313491551960229047428.llvm.5591279935177935698)+196) (BuildId: 56e704c544e6c624201be2ab4933e853)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #15 pc 0000000000212eac  /data/app/~~LhLfaxK6feAst6LftPx1_A==/com.wezeejay.wezeejaylab-gdOQiJlPVkGY5gaoRcBC0w==/lib/arm64/libnative-lib.so (juce::getAppContext()+176) (BuildId: f508c74ed3f8d5bd0261e9ff626a694ad0c787d3)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #16 pc 000000000025744c  /data/app/~~LhLfaxK6feAst6LftPx1_A==/com.wezeejay.wezeejaylab-gdOQiJlPVkGY5gaoRcBC0w==/lib/arm64/libnative-lib.so (juce::JuceActivityWatcher::JuceActivityWatcher()+116) (BuildId: f508c74ed3f8d5bd0261e9ff626a694ad0c787d3)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #17 pc 000000000021b4fc  /data/app/~~LhLfaxK6feAst6LftPx1_A==/com.wezeejay.wezeejaylab-gdOQiJlPVkGY5gaoRcBC0w==/lib/arm64/libnative-lib.so (juce::Thread::initialiseJUCE(void*, void*)+416) (BuildId: f508c74ed3f8d5bd0261e9ff626a694ad0c787d3)
F/jay.wezeejayla(29657): runtime.cc:675]   native: #18 pc 0000000000114a9c  /data/app/~~LhLfaxK6feAst6LftPx1_A==/com.wezeejay.wezeejaylab-gdOQiJlPVkGY5gaoRcBC0w==/lib/arm64/libnative-lib.so (PlayAudioEngine::PlayAudioEngine(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, void*, void*)+108) (BuildId: f508c74ed3f8d5bd0261e9ff626a694ad0c787d3)

This means that JUCE’s JNI_OnLoad hasn’t been called. Normally, when loading any native lib via Java’s System.loadLibrary, JNI_OnLoad gets called automatically. See here, for example. How are you loading your libnative-lib.so? You should be loading it via System.loadLibrary.

Thanks for your patience :wink:

I call the createEngine() function like this, from a Kotlin class:

class LecteurAudioManager
{
	companion object
	{
		init
		{
			System.loadLibrary("native-lib")
		}
		
		@JvmStatic private external fun createEngine(context: Context): Long
		// ...

	}
	
	private var engineHandle: Long = 0
	
	fun creerLecteur(context: Context)
	{
		if (engineHandle == 0L)
		{
			engineHandle = createEngine(context)
		}
	}
}

Calling native functions always worked out that way for me.

I just double checked, and System.loadLibrary("native-lib") is called before createEngine() and context is of type Application as expected.

Hmmm this is really strange. Can you try adding this file again, but change:

 System.loadLibrary ("juce_jni");

to load your library:

 System.loadLibrary ("native-lib");

Then, in your LecteurAudioManager, call com.rmsl.juce.Java.initialiseJUCE.

1 Like

Awesome! It works now!!

That being said, I think the reason why I tried the other solution is because, in that Java file, the initialiseJUCE() function is not recognized by Android Studio and is in red.

Anyway, thank you so much for your help! :smiley:

1 Like

This was definitely more complicated than I would have thought as well. Maybe we need to add some more documentation for this use case.

Having said that, I’m not quite sure why JNI_OnLoad wasn’t called in the LecteurAudioManager code that you provided.

I don’t know either. But after further investigation, it appears that, in the juce_android_Threads.cpp file, in the getAppContext() function, the bug appears in the following line:

if (env->IsInstanceOf (context, AndroidApplication) != 0)

And the problem is not context as I first thought, but AndroidApplication which, for some reason, was null.


Anyway, for those of you who are interested, here is how I did:

  • in my Android project, I created the following package com.rmsl.juce, in the java directory (or in the kotlin directory if, like me, you’re working on a Flutter app)
  • I created a class named Java, with the following in it:
package com.rmsl.juce;

import android.content.Context;

public class Java
{
    static
    {
        System.loadLibrary ("native-lib");
    }

    public native static void initialiseJUCE (Context appContext);
}
  • In my application class (in my case the class that inherits FlutterApplication, or, in a normal Android project, Application), I added the following in the onCreate() function:
Java.initialiseJUCE(this)
  • Then, in my native-lib.cpp file, I added:
#include <JuceHeader.h>

And voilà :slight_smile:

And the problem is not context as I first thought, but AndroidApplication which, for some reason, was null.

Yes, as mentioned above, this occurs when JNI_OnLoad is not executed. JNI_OnLoad initialises AndroidApplication. According to Java’s own documentation, if System.loadLibrary loads your shared library, then JNI_OnLoad should have been called.

1 Like

I have a shared library built on JUCE, and when I upgraded from 5.4.7 to 7.0.2, I had this same null AndroidApplication crash. JNI_OnLoad is being called when the library loads.

The problem is that JNIClassBase::initialiseAllClasses (env); was removed from JNI_OnLoad() (in 5.4.7) and moved to juce_JavainitialiseJUCE() (in 7.0.2), so just calling Thread::initialiseJUCE() from my c++ code wasn’t enough. I had to also call JNIClassBase::initialiseAllClasses() before that, and then my shared library once again works.