3

I am working on an Android firmware for an embedded device which streams an encoded video signal using rtp. The underlying library is MediaStreamer2 because it comes with Android support, various codecs and libortp. Therefore I integrated libmediastreamer and its dependencies into my firmware build process.

As a second step, I wrote a simple Android command line application as a PoC which streams audio or video through the network. Unfortunatly, the first call to ms_init() fails due to:

bctbx-fatal-Calling ms_get_jni_env() while no jvm has been set using ms_set_jvm()

Digging a little deeper into the problem, it seems Androids version of libmediastreamer was designed from an NDK point of view: It can be called as a part of an Android app and therefore automatically gets a reference to the JVM (DVM?). Unfortunatly, this is not my use case.

I tried to to remove the dependencies (Querying Sdk version, hardware echo cancelation support, etc.) without success. So my next approach would be starting a VM manually and passing it to the library. I tried Oracles APIs like:

JNIEnv env;
JavaVM vm;
JavaVMInitArgs vm_args;
JavaVMOption options[4];
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-verbose:jni"; 
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 4;
vm_args.ignoreUnrecognized = TRUE;
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);

But the application quits with a simple "aborted". Nevertheless, I am not sure whether this is a way to go because its Android and Dalvik world.

Any suggestions?

Christian Ammann
  • 888
  • 8
  • 19

1 Answers1

1

It is possible to build executable for shell on Android on both rooted and non-rooted devices, see reference How to build an executable for Android shell .

Try below code and build it using NDK to get an executable:

#include <jni.h>
#include <iostream>
#include <string>
using namespace std;

int main(int argc, char **argv) {

   JavaVMOption jvmopt[1];
   jvmopt[0].optionString = "-Djava.class.path=" + ".";

   JavaVMInitArgs vmArgs;
   vmArgs.version = JNI_VERSION_1_2;
   vmArgs.nOptions = 1;
   vmArgs.options = jvmopt;
   vmArgs.ignoreUnrecognized = JNI_TRUE;

   // Create the JVM
   JavaVM *javaVM;
   JNIEnv *jniEnv;
   long flag = JNI_CreateJavaVM(&javaVM, (void**)
      &jniEnv, &vmArgs);
   if (flag == JNI_ERR) {
      cout << "Error creating VM. Exiting...\n";
      return 1;
   }

   /** ----------------------------------------------
    * Put your own JNI related code from here if any. 
    * -----------------------------------------------
    **/

   javaVM->DestroyJavaVM();
   return 0;
}

Do a check on <jni.h> about the interfaces you can use, e.g.

/*
 * VM initialization functions.
 *
 * Note these are the only symbols exported for JNI by the VM.
 */
jint JNI_GetDefaultJavaVMInitArgs(void*);
jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);

You can refer to below to see if they are helpful:

  1. how-to-create-a-jvm-instance-in-jni
  2. https://calebfenton.github.io/2017/04/05/creating_java_vm_from_android_native_code/
shizhen
  • 12,251
  • 9
  • 52
  • 88
  • Thanx for your code and the links :) Still not working, but I'll now give it a try on another device to see if its a device specific issue here. – Christian Ammann Feb 22 '19 at 09:05