【转】Android下编译jni库的二种方法(含示例) -- 不错

原文网址:http://blog.sina.com.cn/s/blog_3e3fcadd01011384.html

总结如下:两种方法是:
1)使用Android源码中的Make系统
2)使用NDK(从NDK r5开始)

---------------------------------
源码要求: 如果Android工程的顶层目录为my_android_project_name:
1) my_android_project_name/jni/Android.mk文件的示例内容如下(以生成libjni_mouse.so的C代码为例):
  LOCAL_PATH:= $(call my-dir)
  include $(CLEAR_VARS)
  LOCAL_PRELINK_MODULE := false
  LOCAL_MODULE := libjni_mouse
  LOCAL_SRC_FILES := jni_mouse.c
  LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
  LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib  -llog
  LOCAL_SHARED_LIBRARIES := libcutils
  include $(BUILD_SHARED_LIBRARY)

2)源文件的部分内容(仅供参考):
  #include <stdio.h>
  #include <unistd.h>
  #include <errno.h>
  #include <linux/input.h>
  #include <linux/uinput.h>

#include <jni.h>                    // located in $JDK/include
  #include <cutils/log.h>         // for Android Make system: $Android_SRC/system/core/include/cutils/log.h
  //#include <android/log.h>   // for NDK compiler

#define LOG_DBG(tag,fmt,args...)  __android_log_print(ANDROID_LOG_DEBUG,tag,fmt,##args)
  #define LOG_ERR(tag,fmt,args...)  __android_log_print(ANDROID_LOG_ERROR,tag,fmt,##args)
  #ifdef ___DEBUG
    #define DBG(fmt, args...)  __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
  #else
    #define DBG(fmt, args...)
  #endif //___DEBUG
  #define OUT(fmt, args...)    __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

#define JNIREG_CLASS            "com/my_organization/my_pkg/JniMouse"

static JNINativeMethod JniMouseMethods[] = {
     { "nativeOpenMouse",            "()I",                   (void*) openMouse },
     { "nativeCloseMouse",           "()V",                   (void*) closeMouse },
     { "nativeMoveCursor",           "(II)V",                 (void*) moveCursor },
     ...
  };

static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* methods,
                                                       int   numMethods)
  {   
    jclass clazz;
   
    // C++ way:  clazz= env->FindClass(className);
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        LOG_ERR(TAG, "Native registration error: unable to find class\n");
        return JNI_FALSE;
    }
    // C++ way:  if (env->RegisterNatives(clazz, methods, numMethods) < 0)
    if ((*env)->RegisterNatives(env, clazz, methods, numMethods) < 0) {
        LOG_ERR(TAG, "RegisterNatives failed\n");
        return JNI_FALSE;
    }

return JNI_TRUE;
  }

static int registerNatives(JNIEnv* env)
  {
    if (!registerNativeMethods(env, JNIREG_CLASS, JniMouseMethods,
                 sizeof(JniMouseMethods) / sizeof(JniMouseMethods[0])))
        return JNI_FALSE;
    return JNI_TRUE;
  }

jint JNI_OnLoad(JavaVM* vm, void* reserved)
  {
   JNIEnv* env = NULL;
   jint result = -1;
  
    // this is for C++: if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOG_ERR(TAG, "ERROR: GetEnv failed\n");
        goto bail;
    }
    assert(env != NULL);
       
    if (!registerNatives(env)) {
        LOG_ERR(TAG, "ERROR: jni_mouse native registration failed\n");
        goto bail;
    }
   
    result = JNI_VERSION_1_4;

bail:
    return result;
  }

---------------------------------
编译过程具体如下:
1)使用Android源码中的Make系统:
$  cd   $ANDROID_SRC    # (e.g. /u_data/android/sourcecode/and22)
$  .      build/envsetup.sh
# 这样就会生成许多shell工具,实际上是shell函数。

$  lunch  MY_LUNCH_NUMBER    # 如果你的项目需要用到PLATFORM相关的内容(共享库/java库等)

# 把Android工程的顶层目录符号链接(或者拷贝)到 $ANDROID_SRC/packages/apps,如
$  ln  -fs  /abs/path/to/my_android_project_name  $ANDROID_SRC/packages/apps

$  mmm  packages/apps/my_android_project_name
# 如果没有错误,就会生成以下文件(取决于你使用的PRODUCT名字):
#       $ANDROID_SRC/out/target/product/$PRODUCT_NAME/system/lib/libjni_mouse.so

# 最后拷贝生成的库文件到Android工程的libs/armeabi/目录下:
$  mkdir -p $ANDROID_SRC/packages/apps/my_android_project_name/libs/armeabi
$  cp  $ANDROID_SRC/out/target/product/$PRODUCT_NAME/system/lib/libjni_mouse.so   \ 
          $ANDROID_SRC/packages/apps/my_android_project_name/libs/armeabi

#  这样,在eclipse中正常编译/生成.apk文件时,就会把生成的jni库自动包含进.apk文件中,这可以使用unzip命令来验证:
#      cp my.apk /tmp/tmp/my.zip; cd /tmp/tmp; unzip my.zip; ls -l  lib/armeabi/lib*.*

2)使用NDK(from NDK r5)
从NDK r5开始,NDK正式作为独立的工具来编译jni的代码,但它往往缺少某些头文件,如<linux/uinput.h>。
0)准备环境变量,如:
   $ export  NDK=/u_data/android/sourcecode/android-ndk-r6b
   $ export        CC=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc
   $ export  STRIP=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-strip
   $ export  SYSROOT=$NDK/platforms/android-8/arch-arm   # 要看你使用的目标Android的版本 :)

1) 对于缺少的头文件,可以借用PC上的x86下的同名文件,如:
    cd   $NDK/platforms/android-8/arch-arm/usr/include/linux
    ln   -fs   ../../../../arch-x86/usr/include/linux/uinput.h   .

2) 编译出可执行文件(如果有main函数),如:
   $   $CC --sysroot=$SYSROOT   -o  my_jni_mouse_exe    jni_mouse.c   my_main_func.c
   #注: ‘--sysroot=dir‘:Use dir as the logical root directory for headers and libraries.

3) 编译出共享库(如果没有main函数),如:
   $   $CC --sysroot=$SYSROOT -fPIC     -o     jni_mouse.o     -c  jni_mouse.c        # optional ‘-o ...‘
   $   $CC --sysroot=$SYSROOT -shared -o libjni_mouse.so        jni_mouse.o
   # 再strip一下,以便减少其大小(直接覆盖原来的库文件):
   $   $STRIP    libjni_mouse.so

4)(可选)链接如上刚生成的共享库:
   $   $CC --sysroot=$SYSROOT -L. -ljni_mouse  -o  my_hello  my_hello.c

<EOF>

时间: 2024-12-28 20:15:15

【转】Android下编译jni库的二种方法(含示例) -- 不错的相关文章

android中获取SharedPreference对象的二种方法

我们在保存一些小量数据时,特别是一些key,value这种数据就保存在SharedPreferences中,在android获取SharedPreferences有二种方式, 1:通过Context上下文获取,ctx.getSharedPreferences 2:通过 PreferenceManager.getDefaultSharedPreferences(ctx) 但是这二种保存数据的文件名确不一样,第一种文件名是自己定义的,第二种是系统写死的,是packageName+"_preferen

android ndk-build 编译静态库libxx.a 以及Android studio openssl 静态库配置(cmake)

android ndk-build 编译静态库libxx.a 需求场景: 目前有安卓编码好的现在的openssl的两个.a,我们需要调用openssl的函数,并把功能再封装成.a; 这样使用时,在android studio jni项目 cmake 里面,需要先引用openssl的.a再引用 上面封装的.a; 如果使用so,那么,直接在android studio jni项目的 cpp里面直接调用openssl的方法,对外提供jni java接口,打包成so即可: 先来说用ndk-build 打

在Ubuntu下编译Assimp库

在Ubuntu下编译Assimp库 如何在Ubuntu下编译Assimp库?这是我以前编译成功后做的笔记,供参考. 1.去下面的网站去下载Assimp库: http://assimp.sourceforge.net/ 2.安装cmake,似乎Assimp库只能通过cmake和vs工程文件进行构建,普通的makfile是通过它来产生的.Ubuntu下使用sudo apt-get install cmake.然后通过cmake --version查看cmake的版本,我cmake版本是2.8.11.

Android下拉刷新库,利用viewdraghelper实现,集成了下拉刷新,底部加载更多,数据初始加载显示loading等功能

项目Github地址:https://github.com/sddyljsx/pulltorefresh Android下拉刷新库,利用viewdraghelper实现. 集成了下拉刷新,底部加载更多,以及刚进入加载数据的loadview.包括了listview与gridview的改写. 效果1: 效果2: 效果3: 效果4: 效果5: 使用说明: imageList=(ListView)findViewById(R.id.image_list); imageAdapter=new ImageA

win下编译ffmpeg库,Compile and build ffmpeg library and dll on Windows x64( 正版)

转载请注明:来自EricKing,thanks 从没想到编一个library这么坑爹,再次提醒各位百度的东西只能参考,想节约时间还是要到官网上去查看docum.不废话了,开始详细过程: ——>1.搭建Win下的GCC编译环境(因为win下vs不支持ffmpeg的compile 和build,官网上也有说这一点) ——>2.下载latest ffmpeg source(后面附官网地址),想办法将编译后的文件做成dll,这是win下编程调试的核心 (这里就用到vs下的一个vc的bash文件叫vcv

debian下编译libev库

系统为Linux debian 2.6.32-5-686.这是裸系统,连xwindows都没有.帐户为root,不是的注意一下权限.这里想说明安装过程及出现的问题,故打印的信息较多,以供出现错误的读者对比.不需要这些信息的读者勿喷. 网上流行的安装方法: sh autogen.sh 或 ./configure make make install 注意,sh autogen.sh 或 ./configure 只运行其中一个就可以,功能一样.只是autogen.sh调用autoconf来配置参数,.

Android下编译cocos2d-x项目报错 ***&#39;AssetsManager.o&#39;. Stop

具体错误提示: make: *** No rule to make target `***/extensions/AssetsManager/AssetsManager.cpp', needed by `obj/local/armeabi/objs/cocos_extension_static/AssetsManager/AssetsManager.o'.  Stop. 很头疼的问题,一时间无从下手,从网上搜索论坛,终于找到了大神的答案. 具体的解决办法如下: 删除projec.andriod 

win7下编译boost库总结

很多情况下都会用到boost库,之前可能通过boostpro直接下载编译好的二进制库,不过遗憾的是目前不再可用了. 下面给出手动编译的过程说明,以版本1.44为例进行说明: 第一步,执行bootstrap.bat,将会在同目录下生成bjam.exe.后面的编译将依赖于bjam.exe 注:bjam.exe --show-libraries可以看到可以编译的库的名称,根据需要进行适当的挑选,也可以全部编译,不过会需要较长时间,建议选择编译自已需要的 第二步,开始编译bjam.exe toolset

NDK下编译JNI

NDK环境下编译JNI 下载demo.tar.gz然后解压 弄个套路 1.编辑build.sh设置好NDK目录 2.把cpp文件放到code下面 运行sh build.sh即可 原文地址:https://www.cnblogs.com/yuandaozhe/p/9711166.html