c知识
stdlib 头文件即standard library标准库头文件 常用系统函数,跟系统调用相关的,比如内存申请malloc和释放free stdio是标准io函数,比如printf和scanf函数
windows和linux文件区别
windows .exe .dll .bat
linux .elf .so .sh
x86对 jni兼容性能很差
由于ndk一开始是做给linux下用的,所有wind下用ndk会有很多问题。
所以还要装个软件 cygwin
只要装2个功能 devel shells
ndk环境变量设置
windows下 1.直接解压缩ndk,然后搭建环境变量. 在path目录下面C:\android-ndk-r7b . 这是直接在cmd命令行下运行 ndk-build
Cygwin Terminal下 这个配置环境变量在 cygwin/etc/profile的32行
/cygdrive/c/android-ndk-r7b 把这个添加 不同ndk的安装路径不一样
每个环境变量用:分隔.
在cygwin下配置了环境便利ndk但是在别的目录 运行ndk-build一直找不到目录 .
执行./ndk-build -C samples/hello-jni 这个代码可解决 博客:http://blog.sina.com.cn/s/blog_4c73bcc80101177e.html
Jni.h 目录:C:\android-ndk-r7b\platforms\android-14\arch-arm\usr\include
log.h目录:C:\android-ndk-r7b\platforms\android-14\arch-arm\usr\include\android
实现步骤
1 定义一个c方法的接口 相当于在java代码中定义了一个接口 接口的实现方法是C语言实现的
2 步 实现C代码
3步骤 创建android.mk 告诉编译器 如何把c代码打包成函数库
4步 把c代码 打包成函数库 用到了安装的环境 通过cygwin terminal
5 步在java代码中 引入库函数
static{
System.loadLibrary("hello");// 注意事项 去掉前面的lib 后面的.so
}
6 使用方法
Anroid.mk 文件
LOCAL_PATH := $(call my-dir) // 返回当前c代码目录
include $(CLEAR_VARS) // 清楚了所有 已local 开头的配置文件 唯独不清楚LOCAL_PATH
LOCAL_MODULE := hello // 库函数的名字 严格遵守makefile 格式 lib .so 如果前面加lib 不会自动生成了
LOCAL_SRC_FILES := Hello.c
include $(BUILD_SHARED_LIBRARY) // 加入库函数
jni 常见的错误
1错误1 忘记方法的参数
2 错误2 203-28 03:41:56.758: E/AndroidRuntime(821): java.lang.UnsatisfiedLinkError: Native method not found: com.example.error.DemoActivity.helloWorld:()Ljava/lang/String; 方法名错误
3 错误3 一般没有日志打印 直接报错工程停止 一般c代码有运行错误
4 错误4 在交叉编译的工具链上报错 c代码有编译错误 比如 一些函数没有声明 一些类型没有声明 少符号
5 错误5 没有Android.mk 文件
6 错误6 Android.mk 文件有错
7 错误7 引用别人.so 函数库 需要你自己native方法对应类的包名 和之前打包成.so函数库的包名一致
使用javah时 有时一直报错:找不到类文件 要添加环境变量classpath
把安卓adt adt\adt\adt-bundle-windows-x86_64-20140702\sdk\platforms\android-10
这个目录下的android.jar 解压出来.然后把这个目录放在classpath里面加入
例: classpath:.;D:\Program Files\Android\android-sdk\platforms\android-8\android
然后到src目录下 javah 包名.类名. 如果报错找不到类文件就到 bin/classes下
获取方法签名:
使用javap -s 获取内部类型签名 这个在反射方法时候要用到
在bin/classes 下执行:javap -s 包名.类名字
1 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
第一个:helloworld
创建jni目标.
创建Hello.c
#include<stdio.h> #include<jni.h> jstring Java_com_example_myhello_MainActivity_helloworldFromc(JNIEnv* env,jobject obj){ return (*env)->NewStringUTF(env,"onehello"); }
创建Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello LOCAL_SRC_FILES := Hello.c include $(BUILD_SHARED_LIBRARY)
然后activity里面加载library
package com.example.myhello; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { public native String helloworldFromc(); static{ System.loadLibrary("hello"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View view) { // TODO Auto-generated method stub Toast.makeText(getApplicationContext(), helloworldFromc(), 0).show(); } }
c代码调用java代码事例
要调用的方法
1 2 3 4 5 6 7 |
|
在c里面的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
|
c代码调用java代码 log
先导入 头文件 : #include <android/log.h>
在 Android.mk 里面加入 LOCAL_LDLIBS += -llog 这个动态链接库在C:\android-ndk-r7b\platforms\android-14\arch-arm\usr\lib 目录下
c代码回调java代码
事例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
相当于java的反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
c代码调用java 其他类里的方法
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 |
|
c代码回调java的静态方法
1 2 3 |
|
1 2 3 4 5 6 7 8 |
|
jni在项目开发的用途 通过jni直接调用c方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|