一个小实例介绍 Android JNI 如何实现步骤,其中有个遇到的加载库失败的教训:


1.  编写JAVA代码,写明要调用的本地动态链接库的本地方法:

wnplib.javapublic class wnplib{    public native void SayHello(String name);    static    {        System.loadLibrary("wnp");    }    public static void main(String [] argv)    {        wnplib wp = new wnplib();        wp.SayHello("myName");    }}

2. 编译javac 成.class文件

     

javac wnplib.java


3.  使用javah 生成该类对应的C语言.h文件

     

javah -classpath . wnplib


4. 使用C/C++实现C的各函数


5. 在Android Source code 中编译代码生成.so库文件

     注意:此处需要注意,目前Android 有两种支持ARM 和 X86 两种,在不同的代码里编译的库有限制,是不是能弄个不依赖的? NDK编译我还没有实验。


    当编译ARM 和 X86 不一致的.so会出现如下的错误:

   

08-14 16:24:58.572 I/ActivityManager(  240): Start proc jni.wnptest.wnpjnitest for activity jni.wnptest.wnpjnitest/.WnptestActivity: pid=22268 uid=10000 gids={}08-14 16:24:58.592 E/jdwp    (22268): Failed sending reply to debugger: Broken pipe08-14 16:24:58.592 D/dalvikvm(22268): Debugger has detached; object registry had 1 entries08-14 16:24:58.602 D/WNP-TEST(22268): /vendor/lib:/system/lib:/system/lib/arm08-14 16:24:58.612 D/houdini (22268): [22268] Loading library(version: 2.0.7.42789 RELEASE)... successfully.08-14 16:24:58.612 D/houdini (22268): [22268] Open Native Library /system/lib/libwnp.so failed.08-14 16:24:58.612 W/dalvikvm(22268): Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Ljni/wnptest/wnpjnitest/WnptestActivity;08-14 16:24:58.612 W/dalvikvm(22268): Class init failed in newInstance call (Ljni/wnptest/wnpjnitest/WnptestActivity;)08-14 16:24:58.612 D/AndroidRuntime(22268): Shutting down VM08-14 16:24:58.612 W/dalvikvm(22268): threadid=1: thread exiting with uncaught exception (group=0x4194e6f0)08-14 16:24:58.612 I/Process (22268): Sending signal. PID: 22268 SIG: 908-14 16:24:58.612 E/AndroidRuntime(22268): FATAL EXCEPTION: main08-14 16:24:58.612 E/AndroidRuntime(22268): java.lang.ExceptionInInitializerError08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.Class.newInstanceImpl(Native Method)08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.Class.newInstance(Class.java:1319)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.Instrumentation.newActivity(Instrumentation.java:1023)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1872)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1984)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.ActivityThread.access$600(ActivityThread.java:124)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1148)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.os.Handler.dispatchMessage(Handler.java:99)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.os.Looper.loop(Looper.java:137)08-14 16:24:58.612 E/AndroidRuntime(22268):     at android.app.ActivityThread.main(ActivityThread.java:4436)08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.reflect.Method.invokeNative(Native Method)08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.reflect.Method.invoke(Method.java:511)08-14 16:24:58.612 E/AndroidRuntime(22268):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)08-14 16:24:58.612 E/AndroidRuntime(22268):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)08-14 16:24:58.612 E/AndroidRuntime(22268):     at dalvik.system.NativeStart.main(Native Method)08-14 16:24:58.612 E/AndroidRuntime(22268): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: get_lib_extents[753]:   121 - /system/lib/libwnp.so is not a valid ELF object08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.Runtime.loadLibrary(Runtime.java:370)08-14 16:24:58.612 E/AndroidRuntime(22268):     at java.lang.System.loadLibrary(System.java:535)08-14 16:24:58.612 E/AndroidRuntime(22268):     at jni.wnptest.wnpjnitest.WnptestActivity.(WnptestActivity.java:39)08-14 16:24:58.612 E/AndroidRuntime(22268):     ... 15 more08-14 16:24:58.612 W/ActivityManager(  240):   Force finishing activity jni.wnptest.wnpjnitest/.WnptestActivity


6. Android APK 测试代码:

    注意:在加载库的时候需要 去掉库前缀字符串"lib", libwnp.so 加载的时候只需写wnp即可。

package jni.wnptest.wnpjnitest;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class WnptestActivity extends Activity {        /*     * Create a game room.     */    public native int wnpCreateRoom(int port);            static    {           Log.d("WNP-TEST", System.getProperty("java.library.path"));        //System.out.println(System.getProperty("java.library.path"));         try {            System.loadLibrary("wnp");        } catch (UnsatisfiedLinkError ule) {            System.err.println("WARNING: Could not load library!");        }    }        /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }}


7. 注意Android APK 加载库需要在JNI中指定JAVA测试的类名及路径

 *Java Application class path */static const char *classPathName = "jni/wnptest/wnpjnitest/WnptestActivity";static JNINativeMethod methods[] = {  {"wnpSendDdata", "([BI)I", (void*)JNICALL Java_WNP_wnpSendDdata },  {"wnpGetData", "()[B", (void*)JNICALL Java_WNP_wnpGetData },  {"wnpCreateRoom", "(I)I", (void*)JNICALL Java_WNP_wnpCreateRoom },  {"wnpJoinRoom", "(Ljava/lang/String;I)I", (void*)JNICALL Java_WNP_wnpJoinRoom },  {"wnpQuitRoom", "()I", (void*)JNICALL Java_WNP_wnpQuitRoom },};/* * Register methods for one class. */static int registerNativeMethods(JNIEnv* env, const char* className,    JNINativeMethod* gMethods, int numMethods){    jclass clazz;    clazz = (*env)->FindClass(env, className);    if (clazz == NULL)        return JNI_FALSE;    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)    {        printf("register nativers error");        return JNI_FALSE;    }    return JNI_TRUE;}/*  * Register methods for all classes.  *  * returns JNI_TRUE on success.  */static int registerNatives(JNIEnv* env){  if (!registerNativeMethods(env, classPathName,                 methods, sizeof(methods) / sizeof(methods[0]))) {    return JNI_FALSE;  }  return JNI_TRUE;}/*  * Called by the VM when the shared library is loaded.  */jint JNI_OnLoad(JavaVM* vm, void* reserved){    JNIEnv* env = NULL;    jint result = -1;    WNP_LOGD("Entering JNI_OnLoad\n");    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)        goto bail;    assert(env != NULL);    if (!registerNatives(env))        goto bail;    /* success -- return valid version number */    result = JNI_VERSION_1_6;bail:    printf("Leaving JNI_OnLoad (result=0x%x)\n", result);    return result;}


8. 好的现在你可以测试实现的JNI了。


更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. 一款常用的 Squid 日志分析工具
  3. GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
  4. RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
  5. Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
  6. android studio信鸽推送10004错误
  7. Android开发笔记
  8. android EOFException异常解决办法 (SharedPreferences保存对象)
  9. Android(安卓)envsetup.sh剖析

随机推荐

  1. android 通话记录次数
  2. android中的Inflater
  3. android DragLayer源码
  4. 理解 Android(安卓)的 ONE_SHOT_MAKEFILE
  5. [Android] 录音与播放录音实现
  6. android 升级包检测并更新实现
  7. Activity 技巧 屏幕 进度条 控制
  8. 记录一下maven android 的启动命令
  9. Android图像变化
  10. android 2.2 apidemos 赏析笔记 4