标签:
使用步骤
一、定义本地方法,通常情况下,应单独定义一个类来封装所有native方法
/** 存放native方法的类 */
public class MyNativeMethods {private static MyNativeMethods mEmployee;private MyNativeMethods() {}public static MyNativeMethods getInstance() {if (mEmployee == null) {mEmployee = new MyNativeMethods();}return mEmployee;}//相当于在java代码中定义了一个接口,然后用C语言实现了此接口public native String helloFromC();public native int passwordFromC(int x, int y);}二、在项目根目录下创建【jni文件夹】,在jni文件夹中创建一个【.c文件】,在c代码中,实现上面定义的方法
#include <stdio.h>
#include <stdlib.h>#include <jni.h>//必须添加的头文件jstring Java_com_bqt_hellofromc_MyNativeMethods_helloFromC(JNIEnv* env, jobject obj) { //【返回值】【方法名】【参数列表】返回值类型jstring就是java中的stringchar* cstr = "hello from c"; // char* 在c中可用来表示一个字符串。注意,这里绝对不能有中文jstring jstr = (*env)->NewStringUTF(env, cstr);return jstr;}JNIEXPORT jint JNICALL Java_com_bqt_hellofromc_MyNativeMethods_passwordFromC(JNIEnv *env, jobject obj, jint a, jint b) {return a + b + 10000; //c中的int占用字节数在不同环境下可能不同,可能是0-65535,所以,稍微大一点的数(十万级别)都得用double}
三、把C/C++代码编译成【动态链接库.so文件】1、在工程的jni目录下创建一个【Android.mk文件】,在里面定义打包成函数【库的名字】及对应的【c代码的文件名】
LOCAL_PATH := $(call my-dir)
# C/C++代码所在目录,也就是我们的jni目录,不必修改include $(CLEAR_VARS)LOCAL_MODULE := hello# 对应打包成函数库的名字,编译器会自动在前面加上lib,在后面加上.so,最终结果就是libhello.soLOCAL_SRC_FILES := hello.c# 对应的c代码的文件名,即hello.cinclude $(BUILD_SHARED_LIBRARY)
2、使用工具编译生成动态链接库.so文件可以使用cygwin工具编译,其中第三步中为Android工程的根目录
cd ../..
cd cygdrive/
cd d/Users/Android_workspace/HelloFromC
ndk-build
或直接用cmd编译,注意要先在系统变量path中增加NDK工具所在路径,如【D:\Android\android-ndk-r10d】过程:
cd/d D:\Users\Android_workspace\HelloFromC
ndk-build
编译成功后会在工程libs/armeabi目录下生成一个【libhello.so】文件PS,EABI的含义为:Embedded Application Binary Interface(嵌入式应用二进制接口)3、若要项目支持arm外的平台,需在jni目录中添加【Application.mk】文件,并加上以下内容
APP_ABI := armeabi armeabi-v7a x86
#Application.mk文件的目的是,描述在你的应用程序中所有需要的模块(即静态库或动态库)#APP_ABI 的值以空格区分,代表要支持的架构,默认值为【armeabi】。其他架构,ARMv7 【armeabi-v7a】;IA-32【 x86】#每增加一个架构,编译后都会在lib目录下生成一个相应的文件夹,文件夹下的文件都是同名的.so文件(当然文件内容不一样)
编译成功后,会在lib目录下生成对应的多个文件夹及.so文件4、细心观察会发现,除了自动生成了libs目录下的.so文件外,还产生了一个比libs目录大很多倍的obj目录,并且其结构及内容也很像网上找到的资料解释为:As part of the build process过程, the files in the libs folder have been stripped剥皮 of symbols符号 and debugging information. So you‘ll want to keep two copies of each of your .so files: One from the libs folder to install on the Android device, and one from the obj folder to install for GDB一个调试工具 to get symbols from.简单来说就是,obj下的是带符号和调试信息的,lib下的是去掉这些庞大信息后的动态链接库文件,在安装到Android设备上时只需libs目录下的.so文件即可5、当完成这一步后,如果我们以后不需要再重新编译,我们就可以直接删除jni目录和obj目录了四、在java代码中加载.so类库,之后就可以调用本地方法了
static {
System.loadLibrary("hello");// 在java代码中引入libs目录下的库函数,文件名为【libhello.so】。注意,引入时的文件名要去掉前面的lib和后面的.so}
String stringFromC = MyNativeMethods.getInstance().helloFromC();int intFromC = MyNativeMethods.getInstance().passwordFromC(1, 2);以上测试完美通过
标签:
原文地址:http://www.cnblogs.com/baiqiantao/p/5604121.html