I am getting this message which is not allowing my apps to run which contain some native C/C++ files, which I build using NDK. Apps is closing and opening again and crashing in a loop. I am getting below compilation warning after making some awk related changes in android.mk
C:/android-ndk-r8/build/core/add-application.mk 128:Android NDK : Warning: APP-PLATFORM android-14 is larger than android:minsdkVersion 8 in ./AndroidManifest.xml
I have checked relevant threads associated with it, but couldn't find anything which can help me. Can anyone please help me, what I am missing here.
Logcat Output:
15:44:15.815: E/Trace(3026): error opening trace file: No such file or directory (2)
05-28 15:44:16.007: D/dalvikvm(3026): Trying to load lib /data/app-lib/com.example.raptorjni-2/libraptorq-test.so 0x40ce6428
05-28 15:44:16.035: D/dalvikvm(3026): Added shared lib /data/app-lib/com.example.raptorjni-2/libraptorq-test.so 0x40ce6428
05-28 15:44:16.035: D/dalvikvm(3026): No JNI_OnLoad found in /data/app-lib/com.example.raptorjni-2/libraptorq-test.so 0x40ce6428, skipping init
05-28 15:44:16.255: D/RaptorQ(3026): Entering the main function
Java main file snippet from where the C function is called :
Log.d(TAG,"isteps Ecoded" + isteps);
/* Call the JNI-ized version of DFRQEncPerfTest */
String res =
resultRQEncPerfString(nSrcSymbols, symbolSize, loss, niter,
mode, 0, header);
.C file function Snippet:
jstring
Java_com_example_raptorjni_RaptorJni_resultRQEncPerfString
(JNIEnv *env, jobject thiz,
jint nSrcSymbols, jint symbolSize, jint lossrate, jint nLoop,
jint mode, jint nRepair, jint header)
{
Implementation ....
JNI_Onload is optional initialization function introduced since JNI 1.4 (more or less), that allows developers to do some init jobs while library is loaded (for example, register native methods to jvm).
So we really don't need javah or something stupid to implement native java methods in c/c++, just call JNIEnv::registerNatives inside JNI_Onload .
For this issue, I think something else was wrong.
Related
I have an NDK shared library and I want to do some tests against it. I currently used googletest to create an native executable that links to the library, followed instructions in the README.NDK. A dummy executable can run on a Android emulator. Good.
Now, the tricky thing is that the shared library calls a lot of functions of an JNIEnv instance, for example:
env->NewStringUTF()
...
The question is, how can an Android native executable get an instance of JNIEnv?
One method is to use the invocation API described below.
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/invocation.html
However, I looked at the jni.h of NDK, and it seems disallow the usages of this API:
/*
* VM initialization functions.
*
* Note these are the only symbols exported for JNI by the VM.
*/
#if 0 /* In practice, these are not exported by the NDK so don't declare them */
jint JNI_GetDefaultJavaVMInitArgs(void*);
jint JNI_CreateJavaVM(JavaVM**, JNIEnv**, void*);
jint JNI_GetCreatedJavaVMs(JavaVM**, jsize, jsize*);
#endif
Any suggestions are highly appreciated!
(I am new to Android so please correct me if I am wrong. Thanks!)
This is done via AttachCurrentThread().
It is benign to call this if the thread is already attached.
I'm trying to add MP3 read and write capabilities to my Android app. I'm using the lame4android app as a starting point. Encoding a file works for me, but I'm having a problem with the decode functions -- I'm getting undefined references to the decode functions.
Here are excerpts from my wrapper.c:
#include "libmp3lame/lame.h"
#include "jni.h"
lame_t lame;
jint Java_com_intonia_dandy_WavStream_initEncoder(JNIEnv *env,
jobject jobj,
jint in_num_channels,
jint in_samplerate)
{
lame = lame_init();
...
return lame_init_params(lame);
}
hip_t hip;
jint Java_com_intonia_dandy_WavStream_initDecoder(JNIEnv *env, jobject jobj)
{
hip = hip_decode_init();
return hip != 0;
}
And here are the declarations from lame.h:
lame_global_flags * CDECL lame_init(void);
typedef hip_global_flags *hip_t;
hip_t CDECL hip_decode_init(void);
I'm getting an error message:
C:/ACode/dandy/src/main/jni/./wrapper.c:62: undefined reference to `hip_decode_init`
I'm also getting undefined references to hip_decode and and hip_decode_exit. But lame_init, lame_init_params, lame_encode_buffer, and lame_encode_flush do not generate any errors. I get these errors using the command line to run ndk-build, and I get the same errors when I let Android Studio manage the compilation.
How are the lame_* functions different from the hip_decode_* functions? Should I be using the deprecated lame_decode_*?
EDIT: I'm looking at the output of the ndk-build command. The .c files are listed on the console as they are compiled. hip_decode_init is defined in jni/libmp3lame/mpglib_interface.c, but mpglib_interface is not getting compiled, even though it's listed in jni/Android.mk. Why not???
It turns out that the LAME library as distributed does not have decoding enabled. To get it working, I had to do the following:
Add #define HAVE_MPGLIB 1 to mpglib_interface.c
Copy all .c and .h files from the mpglib directory of the LAME distribution.
Edit Android.mk to include the .c files from mpglib.
EDIT: instead of modifying mpglib_interface.c to define HAVE_MPGLIB,
it's better to set compilation flags.
Working with Android Studio 2+, build.gradle should contain
android {
defaultConfig {
ndk {
moduleName "libmp3lame"
cFlags "-DSTDC_HEADERS -DHAVE_MPGLIB"
}
}
}
Or in Android.mk:
LOCAL_CFLAGS = -DSTDC_HEADERS -DHAVE_MPGLIB
I'm trying to use short[] and jshortArray between C/JAVA as follows in Eclipse:
JNIEXPORT void JNICALL Java_com_testingForFun_testFunc
(JNIEnv *env, jclass clazz, jshort num, jshortArray data) {
jshort outCArray[] = {100, 200};
jshortArray outJNIArray = (*env)->NewShortArray(env, 2); // allocate
if (NULL == outJNIArray) return;
(*env)->SetShortArrayRegion(env, outJNIArray, 0 , 2, outCArray); // copy
//return outJNIArray;
}
I've created the header file using javah and included it. However, Eclipse says NewShortArray and SetShortArrayRegion are unresolved and I can't build the apk. However, not using arrays (jshort and short) works fine. I looked in jni.h and it seems that NewShortArray other related functions are defined if __cplusplus is defined, but I'm using C. I also built the apk on the command line using ndk-build and ant and I read outJNIArray[0] or [1] = 0 in the calling function, so it's not working there either. How do I resolve this issue?
Additionally, Eclipse can't resolve ANDROID_LOG_DEBUG in:
__android_log_print(ANDROID_LOG_DEBUG, "FibLib.c", "fibNI(%lld)", n);
even though
#include <android/log.h>
is at the beginning of the file.
I used Eclipse restart and seems to have cleared up these issues. But every time I edit my .c file, the unresolved errors pop up, and I need to restart. It's very annoying. Any fix for this?
The issue of outJNIArray[] not being set is a separate topic, so I will ask another question on the forum in the future if necessary.
My Android application comprises two parts: frontend written in Java and game written in C++ using NativeActivity NDK stuff. I have a problem integrating Flurry into my application. Flurry works fine from within Java part, but crashes from within C++.
More specifically, call
jni_env->FindClass("com/flurry/android/FlurryAgent");
results in ClassNotFoundException.
jni_env variable is not broken because I am able to get some Intent params using it.
FlurryAgent.jar is added to libs dir and into .classpath. I've even checked 'Order and Export' checkbox for FlurryAgent.jar (though I have no idea what does it mean). Nothing helps.
One more detail: my application is divided into Library and App parts. I have added FlurryAgent.jar to both parts and checked 'Order and Export' in both parts, but it still does not help. Clean & rebuild does does not help either. Did I miss something?
The answer is here: http://archive.is/QzA8
In other words, NativeActivity cannot find a third-party class and instead of
jni_env->FindClass("com/flurry/android/FlurryAgent");
one should use
jobject nativeActivity = state->activity->clazz;
jclass acl = jni_env->GetObjectClass(nativeActivity);
jmethodID getClassLoader = jni_env->GetMethodID(acl, "getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = jni_env->CallObjectMethod(nativeActivity, getClassLoader);
jclass classLoader = jni_env->FindClass("java/lang/ClassLoader");
jmethodID findClass = jni_env->GetMethodID(classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring strClassName = jni_env->NewStringUTF("com.flurry.android.FlurryAgent");
jclass flurryClass = (jclass)(jni_env->CallObjectMethod(cls, findClass, strClassName));
jni_env->DeleteLocalRef(strClassName);
I've spent my last two days on an JNI issue and it's driving me crazy...
I just try to do:
SWIGEXPORT void JNICALL Java_com_my_package_CM_1CoreJNI_CM_1Property_1name_1set(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
const char *arg2 = (*jenv)->GetStringUTFChars(jenv, jarg2, 0);
....
}
I'm calling this function through a JAR and it keeps crashing.
All that I can read from my LogCat is:
03-27 12:44:29.162: E/dalvikvm(1599): JNI ERROR (app bug): accessed stale weak global reference 0x4080f657 (index 15765 in a table of size 0)
03-27 12:44:29.172: W/dalvikvm(1599): JNI WARNING: jstring is an invalid weak global reference (0x4080f657)
03-27 12:44:29.172: W/dalvikvm(1599): in Lcom/my/package/CM_CoreJNI;.CM_Property_name_set:(JLjava/lang/String;)V (GetStringUTFChars)
After long investigations, I've tried to call that function directly from my activity (by adding native void set...) and worked fine!
I'm blocked and don't know how to do...
Did any one managed to call JNI from JAR successful?
EDIT: fixed by removing the jar and and adding the .java files...