由于工作需要需要了解一下android的ndk开发,就做了一个简单的例子。
环境jdk1.6,ndk=android-ndk-r8-windows,eclips3.7,androidsdk=10
功能:android的调用一个c99写的基数排序方法
工程结构:
内容: 红色部分都是重点
编译一下目的生成HelloJin.clas字节码文件,我的的工程在D:\lyl_android\所以字节码文件的绝对路径在
D:\lyl_android\HelloJin\bin\classes\com\example\hellojin目录下面
假使我们已经配置好了jdk,ndk环境,(这个可以配好后用相应的命令验证一下看javah和ndk-build是否可以用)
我们在我们的工程目录下建立一个名字叫jni的目录(即D:\lyl_android\HelloJin\jni)用来存放我的本地化代码和
makefile文件Android.mk(如果想详细知道makefile是什么,可以看看linux)。
现在我们来生成我们本地化的JNI的头文件,JNI命名规则手动拼写容易出错,我们借助JAVAH命令
cmd:打开命令行
D:切换盘符
cd D:\lyl_android\hellojin 进入工程目录
javah -classpath bin\classess -d jni com.example.hellojin.HelloJin
这个命令的解释为:在本工程下bin\classes 目录下面.class文件中寻找类全名为com.example.hellojin.HelloJin的类,运行
javah命令生成java本地化的C头文件com_example_hellojin_HelloJin.h存放在工程目录下的jni目录(D:\lyl_android\HelloJin\jni)下。
com_example_hellojin_HelloJin.h的内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_hellojin_HelloJin */
#ifndef _Included_com_example_hellojin_HelloJin
#define _Included_com_example_hellojin_HelloJin
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_hellojin_HelloJin
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojin_HelloJin_stringFromJNI
(JNIEnv *, jobject);
/*
* Class: com_example_hellojin_HelloJin
* Method: notStringFromJNI
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_notStringFromJNI
(JNIEnv *, jobject);
/*
* Class: com_example_hellojin_HelloJin
* Method: radixSort
* Signature: ([II)V
*/
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_radixSort
(JNIEnv *, jobject, jintArray, jint);
#ifdef __cplusplus
}
#endif
#endif
建立一个hello-jni.c的文件,实现com_example_hellojin_HelloJin.h的方法如下所示:
#include <string.h>
#include <jni.h>
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
*/
JNIEXPORT jstring JNICALL Java_com_example_hellojin_HelloJin_stringFromJNI
(JNIEnv * env, jobject jb){
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
/*
* Class: com_example_hellojin_HelloJin
* Method: notStringFromJNI
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_notStringFromJNI
(JNIEnv *env, jobject jb){
return ;
}
int data[10]={73, 22, 93, 43, 55, 14, 28, 65, 39, 81}; //待排序的数组
typedef struct list //静态链表结构体类型
{
int data;
int next;
}List;
List bucket[10]; //构造十个桶
List d[10]; //将待排序数据构造成list类型的数组
int maxbit(int data[],int n) //计算待排序数组元数的最长的位数
{
int d=1;
int i=0;
for(;i<n;i++)
{
int c=1;
int p=data[i];
while(p/10)
{
p=p/10;
c++;
}
if(c>d)
d=c;
}
return d;
}
void init(int data[],int n) //清桶的过程,以及将临时的数组放到d【10】数组中
{
int j=0;
for(j=0;j<n;j++)
{
bucket[j].next=-1;
bucket[j].data=j;
}
for(j=0;j<n;j++)
{
d[j].data=data[j];
d[j].next=-1;
}
}
void RadioSort(int data[],int n) //基数排序的过程
{
int p=maxbit(data,n); //先求出最长的位数
int r=1;
int i=0;
for(;i<p;i++) //执行装桶倒桶的次数
{
init(data,n); //复位清桶的过程
if(i!=0) //第一次装桶的时候从小到大开始装,之后都从大到小装桶
{ int k=n-1;
for(;k>=0;k--)
{
int a=d[k].data/r;
int b=a%10;
d[k].next=bucket[b].next;
bucket[b].next=k;
}
}
else
{ int k=0;
for(;k<n;k++)
{
int a=d[k].data/r;
int b=a%10;
d[k].next=bucket[b].next;
bucket[b].next=k;
}
}
int c=0;
int k=0;
for(;k<n;k++) //倒桶的过程,将其放到data数组当中
{
if(bucket[k].next!=-1)
{
int p=bucket[k].next;
data[c++]=d[p].data;
while(d[p].next!=-1){
data[c++]=d[d[p].next].data;
p=d[p].next;
}
}
}
r=r*10; //为了后面对十位数以及高位求当前位置上的数字
}
}
JNIEXPORT void JNICALL Java_com_example_hellojin_HelloJin_radixSort
(JNIEnv * env, jobject jb, jintArray data, jint maxlen){
int size = (*env)->GetArrayLength(env, data);
jint i;
// (*env)->GetIntArrayRegion(data, 0, 10, buf);
jint *buf = (*env)->GetIntArrayElements(env, data, 0 );
RadioSort(buf,size);
/* for (i = 0; i < 10; i++) {
printf("%u",buf[i]);
}*/
(*env)->ReleaseIntArrayElements(env, data, buf, 0);
//env->SetIntArrayRegion(data, 0, 10, buf);
return;
}
在hello-jni.c文件同级目录中(D:\lyl_android\HelloJin\jni)建立一个名为Android.mk的文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
这个MK文件的具体含义可以看android ndk文档,我们需要改动的地方就包括
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
就可以了
好现在准备工作已经做好,在cmd下D:\lyl_android\HelloJin目录下运行命令ndk-build
大功告成,通过eclipse重新编译android项目搞定;