Android通过Jni实现Java对C/C++函数的调用示例说明

A.第一步

使用Java编写Android应用程序,HelloWorld为例:

<pre name="code" class="objc">package com.lucy;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class HelloWorld extends Activity {   @Override   public void onCreate(Bundle savedInstanceState){     super.onCreate(savedInstanceState);     setContentView(R.layout.main);     Log.v("dufresne", printJNI("I am HelloWorld Activity"));   }  static{    //加载库文件    System.loadLibrary("HelloWorldJni");  }   //声明原生函数 参数为String类型 返回类型为String  private native String printJNI(String inputStr);}编写完成之后,用eclipse编译Java应用程序。

B.第二步

生成共享库的头文件:

  进入到eclipse对应的AndroidProject中 :/HelloWorld/bin/classes/com/lucy/下:

  可以看到里面有很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:HelloWorld.class文件。

  退回到classes一级目录:/HelloWorld/bin/classes/执行如下命令:

  javah com.lucy.HelloWorld

  生成文件:com_lucy_HelloWorld.h

#include <jni.h>#ifndef _Included_com_lucy_HelloWorld#define _Included_com_lucy_HelloWorld#ifdef __cplusplusextern "C" {#endifJNIEXPORT jstring JNICALL Java_com_lucy_HelloWorld_printJNI(JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif

可以看到自动生成对应的函数:Java_com_lucy_HelloWorld_printJNI

  Java_ + 包名(com.lucy) + 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作。

  当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。

C.第三步

实现JNI原生函数源文件:

新建com_lucy_HelloWorld.c文件:

#include <jni.h>#define LOG_TAG "HelloWorld"#include <utils/Log.h>/* Native interface, it will be call in java code */JNIEXPORT jstring JNICALL Java_com_lucy_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr){  LOGI("dufresne Hello World From libhelloworld.so!");  const char *str = (const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );  LOGI("dufresne--->%s",(const char *)str);  (*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );  return (*env)->NewStringUTF(env, "Hello World! I am Native interface");}jint JNI_OnLoad(JavaVM* vm, void* reserved){  void *venv;  LOGI("dufresne----->JNI_OnLoad!");  if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {    LOGE("dufresne--->ERROR: GetEnv failed");    return -1;  }  return JNI_VERSION_1_4;}

OnLoad Java_com_lucy_HelloWorld_printJNI

函数里面做一些log输出,注意JNI中的log输出的不同。

  JNI_OnLoad函数JNI规范定义的,当共享库第一次被加载的时候会被回调,

这个函数里面可以进行一些初始化工作,比如注册函数映射表,缓存一些变量等,

最后返回当前环境所支持的JNI环境。本例只是简单的返回当前JNI环境。

D.第四步

编译生成so库

  编译com_lucy_HelloWorld.c生成so库可以和app一起编译,也可以都单独编译。

在当前目录下建立jni文件夹:HelloWorld/jni/下建立Android.mk ,并将com_lucy_HelloWorld.c和 com_lucy_HelloWorld.h 拷贝到进去

编写编译生成so库的Android.mk文件:

LOCAL_PATH:= $(call my-dir)# 一个完整模块编译include $(CLEAR_VARS)LOCAL_SRC_FILES:=com_lucy_HelloWorld.cLOCAL_C_INCLUDES := $(JNI_H_INCLUDE)LOCAL_MODULE := libHelloWorldJniLOCAL_SHARED_LIBRARIES := libutilsLOCAL_PRELINK_MODULE := falseLOCAL_MODULE_TAGS :=optionalinclude $(BUILD_SHARED_LIBRARY)

系统变量解析:

  LOCAL_PATH - 编译时的目录
  $(call目录,目录….)目录引入操作符

  include$(CLEAR_VARS) -清除之前的一些系统变量
  LOCAL_MODULE-编译生成的目标对象
  LOCAL_SRC_FILES-编译的源文件
  LOCAL_C_INCLUDES-需要包含的头文件目录
  LOCAL_SHARED_LIBRARIES-链接时需要的外部库
  LOCAL_PRELINK_MODULE-是否需要prelink处理
  include$(BUILD_SHARED_LIBRARY)-指明要编译成动态库

  android.mk编译模块添加具体方法参考:http://blog.csdn.net/yili_xie/article/details/4906865


编译此模块:输入编译命令

  ./make Mtkmm packages/apps/HelloWorld/jni/

  上面是我的工程根目录编译命令。具体编译方式根据自己系统要求执行。

编译输出:libHelloWorldJni.so (system/lib中视具体而定)

  此时库文件编译好了可以使用,如果在eclipse中模拟器上使用,需要将libHelloWorldJni.so导入到system/lib下,

  或者对应app的data/data/com.lucy/lib/下;

直接在真机上弄,看一下HelloWorld中Android.mk文件的配置:

  其中存在:

    include$(LOCAL_PATH)/jni/Android.mk 表示编译库文件

    LOCAL_JNI_SHARED_LIBRARIES:= libHelloWorldJni 表示app依赖库,打包的时候会一起打包。

E.第五步

验证执行

  将编译好的apk安装到手机上

  使用adbpush到手机上去需要自己去导入库文件libHelloWorldJni.so到data/data/com.lucy/lib/

  使用adbinstall方式安装则会自动导入。


更多相关文章

  1. C语言函数以及函数的使用
  2. Android 文件夹命名规范 国际化资源
  3. android读取文件权限
  4. Android文件存储
  5. Android 播放资源文件视频
  6. android 日志文件输出
  7. gradle 配置文件 build.gradle 属性详解
  8. android文件缓存,并SD卡创建目录未能解决和bitmap内存溢出解决

随机推荐

  1. 在Android中使用UDT
  2. 了解Android的编译器
  3. Android ley hash的生成
  4. Android基础教程(十)之-------ListView的
  5. android Activity android:launchMode="s
  6. 在Android(安卓)Studio配置中遇到问题的
  7. 关于Android usb host 总结
  8. android 进程
  9. This Android SDK requires Andriod Deve
  10. Android Apps开发环境搭建