现在的位置: 首页 > 综合 > 正文

JNI开始

2018年01月29日 ⁄ 综合 ⁄ 共 5613字 ⁄ 字号 评论关闭

第一个工具:
NDK (native develop kits)  
交叉编译的工具链:
交叉编译: 在一个平台(处理器,操作系统)下 编译出来另外一个平台下可以运行的代码.
windows AMD intel x86 架构-> 手机 android arm处理器
之前想要访问是这样:$ ./ndk-build
环境变量的作用: 方便的在任何目录下 都可以使用 指定目录里面的工具
之前必须在liunx下,不过r7b也支持windows,不过现在它正在开发中,不过它
不是很稳定。

.c .java 
1. 编译  把源代码(高级语言)编译成一个低级语言 (汇编语言)
2. 连接  根据具体平台的特性,(cpu的类型 x86 arm,操作系统的类型) 
         把低级语言连接成一个可以执行的二进制可执行的程序.

第二个工具: 
cygwin: windows下linux环境的模拟器.
cygwin的安装目录 不能有空格,最好不要中文 

第三个工具:
cdt : c/c++ develop tools  (主要是用来让c和c++代码 完成高亮显示的作用)
adt : android develop tools 

JNI步骤:
1.创建一个android工程
2.JAVA代码中写声明native 方法 public native String helloFromJNI();
3. 创建jni目录,编写c代码,方法名字要对应
4.编写Android.mk文件
5.Ndk编译生成动态库
6.Java代码load 动态库.调用native代码

Android.mk告诉编译器,以什么样的规则去编译C代码。
chen@chen-THINK /cygdrive/e/androidworkspace/ndkhelloworld/jni
$ ndk-build
Cygwin         : Generating dependency file converter script
Compile thumb  : Hello <= Hello.c
SharedLibrary  : libHello.so
Install        : libHello.so => libs/armeabi/libHello.so

chen@chen-THINK /cygdrive/e/androidworkspace/ndkhelloworld/jni

本地代码里面的方法名里面就有代码。

javah生成JNI文件的签名。因为我们自己写方法签名太麻烦了,所以我们可以直接用javah去
自动生成,非常牛逼。如果有包名,要有相应的文件夹。

mk文件:交叉编译器编译C/c++代码,依赖的配置文件,linux理makefile的语法 
的子集。

ndk-build clean,清除缓存。obj目录,libs目录,手工给它删除。
来这找:
F:\安卓笔记\JNI\2\ziliao\android-ndk-r7b\docs\ANDROID-MK.html

文件可以知道怎么写。

JNI开发中常见的错误:

LOCAL_PATH := $(call my-dir) 
# 交叉编译器 在编译c代码/c++代码依赖的配置文件    linux下 makefile的语法的子集 
# 获取当前Android.mk的路径  
#变量的初始化操作 特点: 不会重新初始化LOCAL_PATH 的变量
include $(CLEAR_VARS) 

#libHello.so 加lib前缀 .so后缀 makefile的语法约定的
LOCAL_MODULE    := libHello
LOCAL_SRC_FILES := Hello.c

include $(BUILD_SHARED_LIBRARY)

ndk开发常见错误
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.  C语言错误为依赖错误,一般第一个出现错误,之后的就都错了。
只需要修复第一个错误即可。
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代码库没有找到
Caused by: java.lang.UnsatisfiedLinkError: Library Hell0 not found

静态加载代码库的时候 代码库没有找到.

5.c代码函数签名出现错误
Caused by: java.lang.UnsatisfiedLinkError: hello_from_c

6.逻辑性的错误, 使用了已经回收的内存空间, 访问了不可以被访问的内存空间,
修改了不能被修改的内存空间 

断点. ndk-gdb 
通过log 方式来观察程序执行流程 (NDK本身支持的)
Android.mk文件增加LOCAL_LDLIBS += -llog
C代码中增加
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
 LOGI("info\n");
 LOGD("debug\n");
 
 学会开发OPenGL.

复习 :
第一步:
//第一步
public native String getStringFromC(); 
第二步:
E:\androidworkspace\ndk-utf\bin\classes>javah cn.itcast.utf.DemoActivity
第三步:
把cn_itcast_utf_DemoActivity.h  copy到jni的目录下。
第四步:
建立C文件
#include <stdio.h>
#include <jni.h>
#include "cn_itcast_utf_DemoActivity.h"

JNIEXPORT jstring JNICALL Java_cn_itcast_utf_DemoActivity_getStringFromC
  (JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env,"你好中国");
}
第五步:在JNI目录下建立一个Android.mk,否则无法编译。
用ndk-build进行编译。
#mk文件:交叉编译器编译C/c++代码,依赖的配置文件,linux理makefile的语法 的子集。
 
#获取当前Android.mk的路径。
   LOCAL_PATH := $(call my-dir)
#变量初始化操作  特点:不会重新初始化LOCAL_PATH的变量。
   include $(CLEAR_VARS)
#生成so文件的名字。  libHello.so,这样加也是linux下makefile语法所约定的。
   LOCAL_MODULE    := Hello
   LOCAL_SRC_FILES := Hello.c
   include $(BUILD_SHARED_LIBRARY)
   
//第六步,最后一步,加载类库。
static{
System.loadLibrary("Hello");
}
   

高版本解决中文乱码问题:
先把Hello.c里面的东西全部copy出来,
把Hello.c的编码变成UTF-8,然后再copy进去 。

低版本:
new String(getStringFromC().getBytes("iso-8859-1"),"utf-8");

ndk开发的中文乱码问题:
1.低版本ndk 不支持中文 ndk-r4-crystal
iso-8859-1 转码 

//重要的课程开始啊。。。。。。。。。。。。。。。。。。
java传递数据给C,然后C再返回给JAVA。
有参数的方法。默认方法签名里面有都会有两个默认参数。

如果代码有更改就用ndk-build clean,然后再重建,还要清除项目class文件。
(JNIEnv * env, jobject obj)
第一个参数:指的是java虚拟机结构体C实现的指针包含的有很多JNI方法。
第二个参数:代表的是调用C代码的JAVA对象代表的是DataProvider对象。
如果是静态方法,第二个参数变成了 jclass clazz 它是指实例化后的对象。

比较高级一点的东西,让C代码调用JAVA的代码。
1. 当c代码接受到特定的消息 让c代码通知 java代码

2. c程序员 c代码想复用java里面的函数和方法 

第一、E:\androidworkspace\ndkcallback\bin\classes>javah cn.itcast.ndkcallback.DataProv
ider
方法签名:
E:\androidworkspace\ndkcallback\bin\classes>javap -s cn.itcast.ndkcallback.DataP
rovider
Compiled from "DataProvider.java"
public class cn.itcast.ndkcallback.DataProvider extends java.lang.Object{
public cn.itcast.ndkcallback.DataProvider();
  Signature: ()V
public void helloFromJava();
  Signature: ()V
public int Add(int, int);
  Signature: (II)I
public void printString(java.lang.String);
  Signature: (Ljava/lang/String;)V
public static void printStaticStr(java.lang.String);
  Signature: (Ljava/lang/String;)V
public native void callmethod1();
  Signature: ()V
public native void callmethod2();
  Signature: ()V
public native void callmethod3();
  Signature: ()V
public native void callmethod4();
  Signature: ()V
}

//为了避免现实中出现这种场景:
在这个里面调用native里面的方法,应该把所有的native方法放在一个类中。

阿里旺旺 : 
登陆的具体实现 c/c++ 
socket http

int login(char* username,char * password){
   //开启一个socket 连接服务器 , 把username 和 password传给服务器.
   //服务器返回 200 登陆成功 
   //服务器返回404 登陆失败 
}

public native int Login(String username, String pwd);

javah 生成native方法的签名 

jint Java_xxx_xxx_xxx_xxx_Login(JNIENV* env , jobject obj , jstring username, jstring pwd){
   char*  cusername = JStr2Cstr();
   char*  cpwd = JStr2Cstr();
   int result = login(cusername ,cpwd);
    if(result == 200){
    }
}

kiss :  keep it simaple stupid 

int String byte[] 

int[]  
1,2,3,4,5

c代码写文件

java读文件

java jni 粘合剂 胶水

c工程实现 具体的代码 

jni native ->jni ->.c 

1. 当c代码接受到特定的消息 让c代码通知 java代码

2. c程序员 c代码想复用java里面的函数和方法 

抱歉!评论已关闭.