Using jni in Android: UNsatisfiedLinkError
Your JNI signature doesn't match. In your .c file, change:
JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared
to
JNIEXPORT jint JNICALL Java_com_cookbook_jni_SquaredWrapper_squared
Generally there are two ways to "glue" native C through JNI to a Java function. The first is what you're attempting to do here, that is use a predetermined signature that JNI will recognize and associate with your appropriate Java code. The second is to pass function pointers, signatures, and Java class names into JNI when you include the library.
Here's the second method that would bind the native function to the appropriate Java code (this would be your .c file):
#include "squared.h"
#include <jni.h>
static const char* SquaredWrapper = "com/cookbook/jni/SquaredWrapper";
jint squared(JNIEnv * env, jobject this, jint base) {
return (base*base);
}
// Methods to register for SquaredWrapper
static JNINativeMethod SquareWrapperMethods[] = {
{"squared", "(I)I", squared}
};
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ( (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) != JNI_OK)
return JNI_ERR;
jclass class = (*env)->FindClass(env, SquaredWrapper);
(*env)->RegisterNatives(env, class, SquaredWrapperMethods, sizeof(SquaredWrapperMethods)/sizeof(SquaredWrapperMethods[0]));
return JNI_VERSION_1_6;
}
void JNI_OnUnload(JavaVM* vm, void* reserved) {
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
return;
jclass class = (*env)->FindClass(env, SquaredWrapper);
(*env)->UnregisterNatives(env, class);
return;
}
It's a good deal longer but it gives you a lot more flexibility when binding native code. The definition for squared and the includes are as you would expect. on the 4th line, the static const char* SquaredWrapper is an escaped string with the fully qualified package name of the class you want to bind squared to. Near the bottom are the JNI_OnLoad and JNI_OnUnLoad functions that take care of binding and unbinding the functions on library load and unload. The last piece is the JNINativeMethod array. This array contains as each entry an array of size 3 whose components are the Java name of the method as a const char*, the JNI signature of the Java method, and the native C function pointer to bind to that method. The JNI function signature tells the environment the argument list format and return value of the Java function. The format is "(Arg1Arg2Arg3...)Ret", so a function that takes an int and double and returns a float would have a signature of "(ID)F", and a function that takes no arguments and returns void would be "()V". I use this handy cheat sheet to remember most of the shorthand:
http://dev.kanngard.net/Permalinks/ID_20050509144235.html
Good luck :)
Edit: Oh, BTW, you'll likely want to add the signatures for JNI_OnLoad and JNI_UnOnLoad to your header, and change the name of your native function prototype to reflect the new .c file.