I have a functional implementation of native (C++) WebRTC in Windows, which I'm trying to get working on every other platform now. Currently, I'm attacking Android.
When I call webrtc::CreatePeerConnectionFactory
, it cannot create the java class org.webrtc.voiceengine.WebRtcAudioManager
. I get the following result (followed by a crash!):
I audio_processing_impl.cc: (line 292): Injected APM submodules:
I audio_processing_impl.cc: Echo control factory: 0
I audio_processing_impl.cc: Echo detector: 0
I audio_processing_impl.cc: Capture analyzer: 0
I audio_processing_impl.cc: Capture post processor: 0
I audio_processing_impl.cc: Render pre processor: 0
I audio_processing_impl.cc: (line 301): Denormal disabler: supported
I webrtc_voice_engine.cc: (line 312): WebRtcVoiceEngine::WebRtcVoiceEngine
I webrtc_video_engine.cc: (line 648): WebRtcVideoEngine::WebRtcVideoEngine()
I webrtc_voice_engine.cc: (line 334): WebRtcVoiceEngine::Init
I audio_device_impl.cc: (line 76): Create
I audio_device_impl.cc: (line 84): CreateForTest
I audio_device_buffer.cc: (line 65): AudioDeviceBuffer::ctor
I audio_device_impl.cc: (line 121): AudioDeviceModuleImpl
I audio_device_impl.cc: (line 125): CheckPlatform
I audio_device_impl.cc: (line 133): current platform is Android
I audio_device_impl.cc: (line 155): CreatePlatformSpecificObjects
I audio_device_impl.cc: (line 947): PlatformAudioLayer
I jvm_android.cc: (line 72): JvmThreadConnector::ctor
I jvm_android.cc: (line 77): Attaching thread to JVM
I jvm_android.cc: (line 262): JVM::environment
I jvm_android.cc: (line 184): JNIEnvironment::ctor
I audio_manager.cc: (line 71): ctor
I jvm_android.cc: (line 196): JNIEnvironment::RegisterNatives: org/webrtc/voiceengine/WebRtcAudioManager
I jvm_android.cc: (line 134): NativeRegistration::ctor
I jvm_android.cc: (line 146): NativeRegistration::NewObject
I org.webrtc.Logging: WebRtcAudioManager: ctor@[name=Thread-15, id=21131]
W System.err: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
W System.err: at org.webrtc.voiceengine.WebRtcAudioManager.<init>(WebRtcAudioManager.java:176)
E rtc : #
E rtc : # Fatal error in: ../../modules/utility/source/jvm_android.cc, line 151
E rtc : # last system error: 0
E rtc : # Check failed: !jni_->ExceptionCheck()
E rtc : # Error during NewObjectV
F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 28384 (Thread-15), pid 27615 (.qgroundcontrol)
This what that failing Java line looks like:
audioManager =
(AudioManager) ContextUtils.getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
I'm using WebRTC M103 (branch-heads/5060
).
I've linked to libwebrtc.a
, dynamically loaded libjingle_peerconnection_so.so
, and bundled libwebrtc.jar
. All of those seemed to be required dependencies, and advanced the ball for me one-by-one as I added them into the equation.
Fixed! This is what I was missing:
I was calling webrtc::JVM::Initialize
prior to webrtc::CreatePeerConnectionFactory
(which is one of many Droid specific requirements they don't bother mention in any docs...). But, I missed the fact there is an overload which takes the Droid app context (i.e. static void Initialize(JavaVM* jvm, jobject context);
). That is to say, I was only passing the jvm pointer when initializing.
After a mini adventure (for which I'll omit the details) to get the context
reference on C side, and not have it go "stale" (when the Java GC would delete it), I passed that along to the initialization. That, in turn, allowed that (original issue) of the Java invocation of ContextUtils.getApplicationContext()
to work!