当前位置: 代码迷 >> Android >> android NDK/JNI环境配备及实例开发流程
  详细解决方案

android NDK/JNI环境配备及实例开发流程

热度:72   发布时间:2016-05-01 17:25:06.0
android NDK/JNI环境配置及实例开发流程
一cygwin安装
cygwin精简版下载地址:http://down.51cto.com/download.php?do=comment&tid=200381
网速可以的可下载完整版
安装完成后再 cygwin bash shell窗口中分别输入gcc -v;make -v查看是否安装成功
在cygwin.bat文件中设置ndk的位置
@echo offD:chdir D:/develop/cygwin_a/binset HOME=/cygdrive/d/develop/cygwin_a/home/set NDK=/cygdrive/e/ndk/r4bash --login -i
?
启动cygwin,进入命令窗口,切换目录到android NDK 安装目录samples/hello-jni目录,执行$NDK/ndk-build clean,
随后执行 $NDK/ndk-build,这个时候看到清除了原来的文件,重新编译生成了 libhello-jni.so,即大功告成.
二、简单实例配置过程
1、创建工程目录
mkdir -p $NDKROOT/apps/HelloNDK/project
说明:
1)$NDKROOT/apps/HelloNDK --是NDK的工程目录
2)$NDKROOT/apps/HelloNDK/project --是Android的工程目录
?
2、在Eclipse中创建Android工程
工程Location为:

$NDKROOT/apps/HelloNDK/project

?
3、创建native方法所在的class
package com.myq.android.HelloNDK;
public class Jni {
?public native int getCInt(int x , int y) ;
?public native String getCString(String name) ;
}
?
4、创建com_myq_android_HelloNDK_Jni.h文件
1)重新编译Jni.java文件
拷贝Jni.java到$NDKROOT/HelloNDK/project/bin
#进入NDK根
cd $NDKROOT
?
#进入bin目录
cd apps/HelloNDK/project/bin/
?
#拷贝?Jni.java文件
cp apps/HelloNDK/project/src/com/myq/android/HelloNDK/Jni.java cd ./
?
#编译
javac Jni.java
?
2)创建Jni.h文件
移动apps/HelloNDK/project/bin/下的Jni.class文件
cd $NDKROOT
cd apps/HelloNDK/project/bin/
mv Jni.class com/myq/android/HelloNDK/
?
生成Jni.h文件,在bin文件夹位置下执行
javah -jni com.myq.android.HelloNDK.Jni
注:
此时在bin下生成如下文件:com_myq_android_HelloNDK_Jni.h
?
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_myq_android_HelloNDK_Jni */
#ifndef _Included_com_myq_android_HelloNDK_Jni
#define _Included_com_myq_android_HelloNDK_Jni
#ifdef __cplusplus
extern "C" {
#endif
/*
?* Class:???? com_myq_android_HelloNDK_Jni
?* Method:??? getCInt
?* Signature: (II)I
?*/
JNIEXPORT jint JNICALL Java_com_myq_android_HelloNDK_Jni_getCInt
? (JNIEnv *, jobject, jint, jint);
/*
?* Class:???? com_myq_android_HelloNDK_Jni
?* Method:??? getCString
?* Signature: (Ljava/lang/String;)Ljava/lang/String;
?*/
JNIEXPORT jstring JNICALL Java_com_myq_android_HelloNDK_Jni_getCString
? (JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
?
?
5、在android工程根目录下创建jni文件夹,移动刚才的.h文件至此目录下
mkdir $NDKROOT/apps/HelloNDK/project/jni
注:该jni文件夹主要存放c\c++方面的头文件和源文件及Android.mk文件
?
移动刚才的.h文件至jni目录下
mv com_myq_android_HelloNDK_Jni.h ../jni/
?
6、在jni下创建com_myq_android_HelloNDK_Jni.c文件
?
#include<stdio.h>
#include<stdlib.h>
#include"com_myq_android_HelloNDK_Jni.h"
JNIEXPORT jint JNICALL Java_com_myq_android_HelloNDK_Jni_getCInt(JNIEnv *env , jobject thiz , jint x , jint y)
{
? return x+y ;
}
JNIEXPORT jstring JNICALL Java_com_myq_android_HelloNDK_Jni_getCString(JNIEnv *env , jobject thiz , jstring name)
{
? const jchar *str = (*env)->GetStringChars(env,name,JNI_FALSE);
? jsize len = (*env)->GetStringLength(env,name) ;
? (*env)->NewString(env,str,len) ;
? //(*env)->ReleaseStringChars(env,name,str) ;
}
?
7、在jni下创建Android.mk文件
?
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := HelloNDK
LOCAL_SRC_FILES := com_myq_android_HelloNDK_Jni.c
include $(BUILD_SHARED_LIBRARY)
?
注:相关参数说明自行查询
?
8、在HelloNDK的工程目录[$NDKROOT/apps/HelloNDK]下创建Application.mk文件
?
APP_PROJECT_PATH := $(call my-dir)/project
APP_MODULES := HelloNDK
注:
该文件时必须的,否则make无法编译
?
9、在$NDKROOT下编译生成.so文件
make APP=HelloNDK
编译成功后:
在apps/HelloNDK/project/libs/armeabi下生成libHelloNDK.so
?
注:
重新编译 make -B APP=HelloNDK
?
10、创建java文件,调用native方法
package com.myq.android.HelloNDK;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class HelloNDK extends Activity {
?public static final String TAG = "------HelloNDK-------" ;
?private Jni mJni ;
?
?static
?{
??System.loadLibrary("HelloNDK") ;
?}
?
??? @Override
??? public void onCreate(Bundle savedInstanceState) {
??????? super.onCreate(savedInstanceState);
??????? mJni = new Jni() ;
???????
??????? final String cString = mJni.getCString("myq") ;
??????? final int cInt = mJni.getCInt(1, 2) ;
???????
??????? Log.i(TAG, "cString--" + cString + "--cInt--" + cInt) ;
???????
??????? setContentView(R.layout.main);
??? }
}
?
注:
加载库文件
static
?{
??System.loadLibrary("HelloNDK") ;
?}
11、在eclipe中运行
来自:http://wsqwsq000.iteye.com/blog/1120716
三、Android.mk文件
可以看到,和Java应用一样,Native模块也需要使用Android.mk文件设置编译选项和参数,但内容有较大不同。对于Native模块而言,一般需要了解如下几类标签:
?
1.???????? LOCAL_MODULE:定义了在整个编译环境中的各个模块,其名字应当是唯一的。此外,这里设置的模块名称还将作为编译出来的文件名:对于原生可执行文件,文件名即为模块名称;对于静态/动态库文件,文件名为 lib+模块名称。例如hello-jni的模块名称为“hello-jni”,则编译出来的动态库就是libhello-jni.so。
2.???????? LOCAL_SRC_FILES:这里要列出所有需要编译的C/C++源文件,以空格或制表符分隔;如需换行,可放置“\”符号在行尾,这和GNU Makefile的规则是一致的。
3.???????? LOCAL_CFLAGS:定义gcc编译时的CFLAGS参数,与GNU Makefile的规则一致。比如,用-I参数可指定编译所需引用的某个路径下的头文件。
4.???????? LOCAL_C_INCLUDES:指定自定义的头文件路径。
5.???????? LOCAL_SHARED_LIBRARIES:定义链接时所需要的共享库文件。这里要链接的共享库并不限于NDK编译环境中定义的所有模块。如果需要引用其他的库文件,也可在此处指定。
6.???????? LOCAL_STATIC_LIBRARIES:和上个标签类似,指定需要链接的静态库文件。需要注意的是这个选项只有在编译动态库的时候才有意义。
7.???????? LOCAL_LDLIBS:定义链接时需要引入的系统库。使用时需要加-l前缀,例如-lz指的是在加载时链接libz这个系统库。libc、libm和libstdc++是编译系统默认会链接的,无需在此标签中指定。
?
欲了解更多关于标签类型及各类标签的信息,可参考<ndk>/docs/ANDROID-MK.txt文件,其中详细描述了Android.mk中各个标签的含义与用法。如下给出的就是我们的示例所用的Android.mk:
?
?
view plain copy to clipboard print ?
  1. LOCAL_PATH?:=?$(call?my-dir)??
  2. include?$(CLEAR_VARS)??
  3. LOCAL_MODULE????:=??hello-jni??
  4. LOCAL_C_INCLUDES?:=??$(LOCAL_PATH)/include??
  5. LOCAL_SRC_FILES???:=??src/call_java.c?\??
  6. ??????????????????????????????????????????src/hello-jni.c???
  7. include?$(BUILD_SHARED_LIBRARY)??
Java代码 复制代码?收藏代码
  1. LOCAL_PATH?:=?$(call?my-dir) ??
  2. include?$(CLEAR_VARS) ??
  3. LOCAL_MODULE????:=??hello-jni ??
  4. LOCAL_C_INCLUDES?:=??$(LOCAL_PATH)/include ??
  5. LOCAL_SRC_FILES???:=??src/call_java.c?\ ??
  6. ??????????????????????????????????????????src/hello-jni.c? ??
  7. include?$(BUILD_SHARED_LIBRARY)??
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    :=  hello-jniLOCAL_C_INCLUDES :=  $(LOCAL_PATH)/includeLOCAL_SRC_FILES   :=  src/call_java.c \                                          src/hello-jni.c include $(BUILD_SHARED_LIBRARY)
?
Application.mk文件
APP_PROJECT_PATH:=$(call my-dir)/projectAPP_MODULES:=HelloNDK
1、APP_MODULES变量是强制的,并且会列出所有你的应用程序所需要的模块(通过Android.mk)文件来描述
2、?APP_PROJECT_PATH变量也是强制性的,并且会给应用程序工程的根目录一个绝对路径这是用来复制或者安装一个没有任何版本限制的JNI库,从而给APK生成一个详细的路径
另外还有两个变量APP_OPTIM决定为发布版或者测试版
APP_CFLAGS则是当编译模块中有任何c文件的时候,c编译器的信号就会发出,这样可以在你的的应用中需要这些模块的时候,进行编译调整,这样就不用直接更改Android.mk文件本身了
  相关解决方案