Jni使用流程:
1. 工程下建立一个jni目录,目录下建立一个Android.mk文件(可以到ndk文档中copy)
2. 在java 文件中建立需要的 native方法
3. 到工程的bin/classes目录下用javah 生成所要的头文件
4. 将头文件copy到jni目录下,再建立一个.c文件在该文件中实现头文件中的方法
5. 到/cygdrive/d/workspace/工程名 ndk-build 编译
示例:
Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Hello 生成的库文件的名称
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c quantize.c reservoir.c tables.c util.c VbrTag.c encoder.c gain_analysis.c lame.c newmdct.c psymodel.c quantize_pvt.c set_get.c takehiro.c vbrquantize.c version.c Hello.c
需要被编译的C文件
LOCAL_LDLIBS += -llog 加入log功能
include $(BUILD_SHARED_LIBRARY)
实现头文件的.c文件
#include
#include
#include
#include "com_itheima_lame_LameActivity.h"加入有本地方法签名的头文件
引入log功能
#include
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
Jni使用过程中出现的错误:
1. android.mk文件不存在
$ ndk-build
Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/add-application.mk:133: *** Android NDK: Aborting... 。 停止。
2.android.mk文件 的配置信息有错误
$ ndk-build
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/build-shared-library.mk:23:
*** Android NDK: Missing LOCAL_MODULE before including BUILD_SHARED_LIBRARY in jni/Android.mk 。 停止。
3.c代码 语法出现错误,编译不通过 Error 1.
Compile thumb : Hello <= Hello.c
jni/Hello.c: In function 'Java_cn_itcast_ndk_DemoActivity_helloFromC':
jni/Hello.c:21: error: 'ctr' undeclared (first use in this function)
jni/Hello.c:21: error: (Each undeclared identifier is reported only once
jni/Hello.c:21: error: for each function it appears in.)
jni/Hello.c:21: error: expected ';' before 'c'
/cygdrive/h/heima6/jni2/ziliao/android-ndk-r7b/build/core/build-binary.mk:240: recipe for target `obj/local/armeabi/objs/Hello/Hello.o' failed
make: *** [obj/local/armeabi/objs/Hello/Hello.o] Error 1
4.java层c代码库没有找到,java代码没有引入库文件
Caused by: java.lang.UnsatisfiedLinkError: Library Hell0 not found
静态加载代码库的时候 代码库没有找到.
5.c代码函数签名出现错误
Caused by: java.lang.UnsatisfiedLinkError: hello_from_c
6.逻辑性的错误, 使用了已经回收的内存空间, 访问了不可以被访问的内存空间,
修改了不能被修改的内存空间
断点. ndk-gdb
通过log 方式来观察程序执行流程
7.c语言中某些头文件没有引入
8.耗时的操作要开子线程,线程忘记.start()
ndk开发的中文乱码问题:
1.低版本ndk 不支持中文 ndk-r4-crystal
iso-8859-1 转码
2.高版本中,只需要将文件保存为UTF-8
将java中的string转化为c语言中的字符串
char*Jstring2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String");
jstring strencode = (*env)->NewStringUTF(env, "GB2312");
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr);
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*) malloc(alen + 1); //"\0"
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba, 0); //
return rtn;
}
javap 生成native方法的签名
javap –s 全类名
开发环境的搭建:
第一个工具:
NDK (native develop kits)
交叉编译的工具链:
交叉编译: 在一个平台(处理器,操作系统)下 编译出来另外一个平台下可以运行的代码.
windows AMD intel x86 架构-> 手机 android arm处理器
.c .java
1. 编译 把源代码(高级语言)编译成一个低级语言 (汇编语言)
2. 连接 根据具体平台的特性,(cpu的类型 x86 arm,操作系统的类型)
连接成一个可以执行的二进制可执行的程序.
第二个工具:
cygwin: windows下linux环境的模拟器.
cygwin的安装目录 不能有空格,最好不要中文
第三个工具:
cdt : c/c++ develop tools (主要是用来让c和c++代码 完成高亮显示的作用)
adt : android develop tools
环境变量的作用: 方便的在任何目录下 都可以使用 指定目录里面的工具
C:\cygwin\etc 下找到profile文件
PATH="/usr/local/bin:/usr/bin:/cygdrive/d/android/android-ndk-r7b:${PATH}"
将ndk-build所在目录加入到环境变量中即可
Lame编解码器的移植步骤
解压libmp3lame 到jni目录.
拷贝 lame.h
创建Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mp3lame
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c quantize.c reservoir.c tables.c util.c VbrTag.c encoder.c gain_analysis.c lame.c newmdct.c psymodel.c quantize_pvt.c set_get.c takehiro.c vbrquantize.c version.c
include $(BUILD_SHARED_LIBRARY)
删除 GNU autotools, Makefile.am Makefile.in libmp3lame_vc8.vcproj logoe.ico depcomp, folders i386 等无用文件
编辑 jni/utils.h,
把 extern ieee754_float32_t fast_log2(ieee754_float32_t x);
替换为 extern float fast_log2(float x);
编译库文件
不用jni运行C语言
纯c语言开发程序
1.下载编译器和链接器软件.Sourcery G++ Lite Edition for ARM.
arm-none-linux-gnueabi-gcc.exe是编译命令
bin/arm-none-linux-gnueabi-ld.exe是链接命令
2.编写c源文件
#include
int main()
{
printf("Hello, Android!\n");
return 0;
}
3.编译hello.c源文件
进入cmd
执行 arm-none-linux-gnueabi-gcc HelloWorld.c -static -o hellostatic
4.将hellostatic文件传输手机
adb push hellostatic /data/data/hellostatic
5.改变文件的授权
adb shell chmod 777 /data/data/hellostatic
6.运行程序
adb shell
cd /data/data
./hellostatic
7.查看执行结果
在代码中运行二进制文件,即C语言
Process process = Runtime.getRuntime().exec("date");
InputStream is = process.getInputStream();
DataInputStream dis = new DataInputStream(is);
String result ;
StringBuilder sb = new StringBuilder();
while((result = dis.readLine())!=null){
sb.append(result);
sb.append("\n");
}
System.out.println(sb.toString());