首页 > 代码库 > JNI入门-学习笔记

JNI入门-学习笔记

JNI入门-学习笔记

可执行文件  Windows - *.exe | linux - *.elfc函数库文件 Windows - *.dll | linux - *.so批处理文件  Windows - *.bat | linux - *.sh

工具

NDK -- native developer kits

Cygwin -- Linux系统模拟器

  • 安装过程要点: ——安装时可以联网安装也可以通过本地文件安装(如果有本地文件) ——Select Packages:没必要全部安装,安装Devel和Shells这两个即可 ——安装好后双击桌面快捷图标进入Cygwin命令控制台 指令:cd.. | cd.. | ls | cd cygdrive
  • 为了方便在任何目录执行指令ndk-build,需要环境变量的配置: 来到Cygwin的安装目录 ../cygwin/etc/profile,打开profile文件,修改PATH的值,多个环境变量之间用冒号(:)分隔。例如这样:PATH="...:/cygdrive/c/android-ndk-r7b:...", 如果不成功,也可以配置Windows下的系统环境变量使用cmd运行

CDT -- 为了方便在eclipse开发c代码 让c代码高亮显示

  • 全称: CDT:c/c++ developer tools ADT:android developer tools
  • 安装步骤: eclipse --> help --> install new software --> add --> Name:cdt|Location:adt.zip --> next。 这时有两个插件供选择CDT Main Features和CDT Optional Features,只选择前者即可,Contact all update sites...这个选项是联网更新,可以不选,next,安装好后eclipse中会有个C/C++的视图

JNI开发之HelloWorld

第一步: 新建一个Android工程,定义一个本地方法

public class MainActivity extends Activity {    // 定义一个本地方法,相当于c的接口,需要用c代码对这个方法做实现    public native String helloFromC();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    ...}

第二步: 在工程下新建一个文件夹叫jni,必须是这个文件名,然后再该文件夹下新建一个文件,比如叫Hello.c,在Hello.c文件中编写C代码,这个方法名比较长,快捷生成方式:cmd--cd到工程src目录下,输入命令javah com.example.helloworldformc.MainActivity(全类名),会在src目录下回生成一个.h的头文件,将此文件拷贝到jni目录下,打开该文件复制里面的方法去掉分号加上{}即可

#include <stdio.h>#include <jni.h>// Java+全类名+方法名,用_连接每个单词jstring Java_com_example_helloworldformc_MainActivity_helloFromC(JNIEnv* env,jObject obj){    return (*env)->NewStringUTF(env,"hellofromc");}

第三步: 在jni文件夹下创建Android.mk文件

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# 对应打包成函数库的名字,你想打包成什么文件名,这里就写成什么,LOCAL_MODULE    := hello# 对应C代码的文件名LOCAL_SRC_FILES := Hello.cinclude $(BUILD_SHARED_LIBRARY)

第四步:

把C代码打包成函数库:cmd--> cd到Android工程所在目录 --> ndk-build(交叉编译命令),刷新下工程,在libs/armeabi中就会有一个.so文件,文件名是lib+hello(mk中定义的库名),并且工程中会多出来一个obj的文件夹,主要存放的是中间文件

第五步: 在Java代码中引入函数库

// 使用静态代码块在Java代码中引入函数库static{    System.loadLibrary("hello"); }

第六步:

public void method(){    // 调用    String str = helloFromC();    Toast.makeText(getApplicationContext(), str, 1).show();}

** 注意 **

  • 引用别人的.so函数库时,需要你自己native方法对应类的包名 和之前他人打包成.so函数库时的包名一致
  • 如果需要在C语言中打印日志,需要引入头文件

    eg:#include <android/log.h>

    但是log的方法名太长不好记,我们需要做下处理

    eg: #define LOGTAG "clog" #define LOGD(...) androidlogprint(ANDROIDLOGDEBUG, LOGTAG, __VAARGS) #define LOGI(...)androidlogprint(ANDROIDLOGINFO, LOGTAG, _VAARGS)

    另外在mk文件中加上一句:LOCAL_LDLIBS += -llog

    在C代码中类似这样调用:LOGD("x = %d",x);

C调用Java

原理:C通过反射的方法调用Java的方法 C中有类似获取class对象,获取methodId,调用五返回值方法CallVoidMethod等等方法 上述方法可以到头文件jni.h中去找, jni.h所在目录:android-ndk-r7b\platforms\android-8\arch-arm\usr\include 通过这些方法可以实现C代码调用Java代码 获取方法签名:cd到bin目录下的classes文件夹下,javap -s 方法所在类的全类名

C

头文件 *.h库文件 *.so/*.o两者关系的比喻:头文件相当于Java中的接口文件,库文件相当于Java中的实现类文件


工具下载:http://pan.baidu.com/s/1mg2zvN6

JNI入门-学习笔记