I've updated to Android Studio 3.0 and I'm trying to migrate from deprecated NDK to CMake for building the native components of my Android app.
I've followed the guide at https://developer.android.com/studio/projects/configure-cmake.html and here is my CMakeLists.txt file:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
myappNative
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/src
)
include_directories(src/main/cpp/include)
SET_TARGET_PROPERTIES(myappNative PROPERTIES LINKER_LANGUAGE CXX)
(the last line isn't in the tutorial but I was getting errors before adding it).
Here is my folder structure:
Here is my native method:
public class Native {
static {
System.loadLibrary("myappNative");
}
public native static String sign(String[] tokens);
}
Here is my header file (generated by javah
):
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_myapp_system_Native */
#ifndef _Included_com_myapp_system_Native
#define _Included_com_myapp_system_Native
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_myapp_system_Native
* Method: sign
* Signature: ([Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_myapp_system_Native_sign
(JNIEnv *, jclass, jobjectArray);
#ifdef __cplusplus
}
#endif
#endif
And I have corresponding C++ files that compile correctly. My APK contains the libmyapp.so
file, everything looks as expected. My app builds, it starts running, it loads the library: (logcat)
D/dalvikvm: Trying to load lib /data/app-lib/com.myapp.myapp-1/libmyappNative.so 0x41e09aa0
D/dalvikvm: Added shared lib /data/app-lib/com.myapp.myapp-1/libmyappNative.so 0x41e09aa0
Then, the moment I try to call the native method, I get this:
W/dalvikvm: No implementation found for native Lcom/myapp/system/Native;.sign:([Ljava/lang/String;)Ljava/lang/String;
Followed by this:
E/AndroidRuntime: FATAL EXCEPTION: com.myapp.client.queue
Process: com.myapp.myapp, PID: 19542
java.lang.UnsatisfiedLinkError: Native method not found: com.myapp.system.Native.sign:([Ljava/lang/String;)Ljava/lang/String;
at com.myapp.system.Native.sign(Native Method)
[...]
And my app crashes. I've seen many questions about this including Android NDK C++ JNI (no implementation found for native...) but those solutions don't help either.
In the log, I see:
:app:externalNativeBuildDebug
Build myappNative armeabi-v7a
[1/1] Linking CXX shared library ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libmyappNative.so
:app:compileDebugSources
Which seems to be alright.
I've also read somewhere that Proguard might be mangling the method names, so I've also added a rule for that too:
-keep class com.myapp.system.Native
I don't know if it changes anything though.
Here is also the related part of my gradle file:
android {
compileSdkVersion 26
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.myapp.myapp"
minSdkVersion 16
targetSdkVersion 26
versionCode 2043
versionName "2.1"
ndk {
moduleName "myappNative"
cFlags "-DNATIVE_DEBUG=1"
}
}
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
}
I've also tried implementing a JNI_OnLoad
method and declaring it in the header but it doesn't seem to be found either, which might be a clue for something general with my configuration, rather than a specific method:
No JNI_OnLoad found in /data/app-lib/com.myapp.myapp-2/libmyappNative.so 0x41e10aa0, skipping init
Why is Android unable to find my native method?