NDK Demo 程序
简单的 NDK Demo 程序
好了,环境已搭建好, 现在我们开始建立一个简单的 ndk 程序来体验下整个 ndk 开发流程 :
第一步:首先我们在eclipse 中新建一个工程,工程名这里是NdkPassNormalData 。 在工程 中新建一个java 类:CallNativeDemo.java
内容如下:
package com.jiubang.Demo.Ndk.PassNormalData;
public class CallNativeDemo {
static {
System.loadLibrary ( "NdkPassDataDemo" );
// 注意库文件名,对于 NdkPassDataDemo 系统会在该类初始化时加载 //libNdkPassDataDemo.so 库 , 切记勿画蛇添足加上前面的 lib 与 .so 扩展名
}
public native int Sum( int a , int b); // 加上 native 表示该方法由 .so 实现
public native String StrCat(String str1 , String str2);
}
编写好该 java 文件后,先编译,然后用 javah 生成 ndk 中我们需要的 c 头文件 :
进入到工程的 bin 目录下输入:
javah -jni com.jiubang.Demo.Ndk.PassNormalData.CallNativeDemo
然后会在当前目录下生成com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo.h 文件
内容大概如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo */
#ifndef _Included_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo
#define _Included_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo
* Method: Sum
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_Sum
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo
* Method: StrCat
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_StrCat
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
第二步:在我们新的工程中加一个名为:jni 的文件夹。这个文件夹就是放原生态c/c++ 的源码的地方,我们make 的时候cygwin 就是编译这个文件夹的。
第三步:在jni 文件夹里新建一个Android.mk 文件。注意,后缀为.mk , 且文件夹一定要小写
Android.mk 的内容为:
LOCAL_PATH := $(call my-dir) <--------- 返回当前路径,默认的,不需要更改
include $(CLEAR_VARS) <-------- 清除先前定义的环境变量,默认的,不需要更改
LOCAL_MODULE := NdkPassDataDemo <-------- 在 java 类引用时的名称
LOCAL_CPP_EXTENSION := cpp
LOCAL_SRC_FILES := Fun.cpp <------ 需要编译的源文件
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib –llog <-- 打 log 要用到的库,这里暂时不大明白为什么库名是这样 …
include $(BUILD_SHARED_LIBRARY) <-- 这里指的是动态库,默认的,不需要更改
第四步:在jni 文件夹里新建一个 Fun.cpp 的文件。这个文件就是c/c++ 文件。
Fun.cpp 的内容为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <android/log.h>
#include "com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo.h"
// 对应 public native int Sum( int a , int b) 的实现
jint JNICALL Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_Sum(JNIEnv* aEnv, jobject aThis, jint aParamA, jint aParamB)
{
int sum = 0;
__android_log_print(ANDROID_LOG_INFO , "Ndk_PassNormalData" , "CallNativeDemo_Sum Coming");
sum = aParamA + aParamB;
FILE* file = fopen("/sdcard/hello.txt","w+");
if (file != NULL)
{
fputs("HELLO WORLD!/n", file);
fflush(file);
fclose(file);
}
__android_log_print(ANDROID_LOG_INFO , "Ndk_PassNormalData" , "CallNativeDemo_Sum Leaving");
return sum;
}
// 对应 public native String StrCat(String str1 , String str2) 实现
jstring JNICALL Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_StrCat(JNIEnv *aEnv, jobject aThis, jstring aStr1, jstring aStr2)
{
__android_log_print(ANDROID_LOG_INFO , "Ndk_PassNormalData" , "CallNativeDemo_StrCat Coming");
const char* str1 = aEnv->GetStringUTFChars(aStr1 , 0);
const char* str2 = aEnv->GetStringUTFChars(aStr2 , 0);
//char* str1 = (char*)(*aEnv)->GetStringUTFChars(aEnv ,aStr1 , 0);
//char* str2 = (char*)(*aEnv)->GetStringUTFChars(aEnv ,aStr2 , 0);
int str1_len = strlen(str1);
int str2_len = strlen(str2);
// char* pszRet = malloc(str1_len + str2_len + 1);
char* pszRet = new char[str1_len + str2_len + 1];
strcpy(pszRet, str1);
strcat(pszRet, str2);
//jstring jstrRet = (*aEnv)->NewStringUTF(aEnv, pszRet);
jstring jstrRet = aEnv->NewStringUTF(pszRet);
// free(pszRet);
delete pszRet;
__android_log_print(ANDROID_LOG_INFO , "Ndk_PassNormalData" , "CallNativeDemo_StrCat Leaving");
return jstrRet;
}
然后就可以开始编译了 :
打开 cygwin, 进入到工程的 jni 目录,然后执行 ndk-build
有看到 Install 就 OK 了
然后会发现工程目录下会多了一个 lib 与 obj 的目录
最后在 android 工程里加上调用这些 ndk 本地方法的代码:
CallNativeDemo nativeDemo = new CallNativeDemo();
int value = nativeDemo.Sum(10, 20);
String str = nativeDemo.StrCat("who", "are you");
TextView v = (TextView)findViewById(R.id.textview1);
v.setText(str);