android下JNI开发--02

c基本语法

  • #include import stdlib.h stdio.h
  • system
  • C基本数据类型 C没有byte boolean 0非0表示false true
  • char c1字节 long 4字节
  • signed unsigned 修饰整形变量 有符号无符号
  • sizeof 取出类型所占字节数
  • C 输出函数 printf (“输出的内容+占位符”,变量)
  • 占位符跟变量类型匹配
  • C的字符串 字符数组 {手动加上结束符 ‘\0’} char cstr[] = “abcd”;
  • char* cstr = “abcd”; “%s”
  • 输入函数 scanf(“占位符”,内存地址); &取地址符
  • 内存地址 计算机中一般用16进制数来表示内存地址
  • 指针 int* p; int 变量来保存一个地址(32位系统)
  • int i; int* p = &i; p &p *p
  • 野指针 指针类型要匹配 int* 指向int变量地址
  • 值传递 引用传递
  • 指针和数组之间的关系
  • 多级指针
  • 栈内存 堆内存
  • 静态内存分配 malloc free realloc
  • 结构体 struct Student
  • 结构体长度 大于等于所有变量长度的和 是最大的那个变量的长度的整数倍
  • 函数指针 返回值类型(*指针名字)(参数)
  • 结构体的指针 (*stup).age stup->age;
  • 联合体 枚举
  • typedef

交叉编译

  • 在一个平台下编译出另一个平台下可以运行的本地代码
  • cpu平台 x86 arm mips
  • 操作系统平台 windows linux mac os unix
  • 原理 在一个平台下模拟另一个平台的特点去编译本地代码

  • NDK native develop kit SDK

  • NDK 目录结构
    • docs 帮助文档
    • platforms 根据不同的android版本号分文件夹
      • include 头文件
      • lib 谷歌提供的做jni开发可以用到的库
    • samples 谷歌提供的样例工程 供参考
    • sourcese jni相关源代码
    • build->tools .sh文件 linux平台下的批处理文件 交叉编译时会自动调用
    • ndk-build.cmd
  • CDT 高亮C的关键字 代码提示

JNIHElloWORLD

  • jni开发流程
  • java native interface

    • ①写java代码 声明本地方法 用关键字 native 本地方法不用实现 具体的实现在C代码中
    • ② 创建jni目录 在项目的根目录下创建
    • ③ 创建Android.mk linux下的makefile文件

      • 向编译系统描述一下 我要编译的代码在哪儿 生成一个叫什么名字的文件

        * LOCAL_PATH := $(call my-dir)
        
        include $(CLEAR_VARS)
        
        LOCAL_MODULE    := hello   #System.loadlibrary("hello")
        LOCAL_SRC_FILES := hello.c #.c源文件的名字
        
        include $(BUILD_SHARED_LIBRARY)
        
    • ④ 创建C源码 本地函数名的命名规则 本地函数命名规则 Java_包名类名本地方法名
      • //JNIEnv* env env 是JNIEnv 的一级指针 env就是结构体 JNINativeInterface的二级指针
        //(**env).函数指针 (*env)->函数指针
        //JNIEnv 是结构体 JNINativeInterface的一级指针
        //结构体 JNINativeInterface定义了大量的函数指针
      • //jobject thiz 那个类调用的本地函数 这个thiz 就是这个类的对象 在这个例子中 thiz 指的就是Mainactivity的对象
      • 必须导入 jni.h头文件
    • ⑤ 调用ndk-build编译源代码 到项目根目录下运行ndk-build
    • ⑥ java代码中 调用System.loadlibrary(“”)
  • jni开发常见错误
    • 本地方法没有找到 java.lang.UnsatisfiedLinkError: Native method not found:
      • 本地方法名写错
        • 避免写错 javah生成头文件
        • jdk1.7以上 到项目/src目录下去运行 生成的头文件就在src目录下
        • jdk1.6 到项目/bin/classes 目录下运行javah 生成的头文件在 /bin/classes去找
        • javah +声明本地方法的类的全类名
      • 忘记加载动态链接库 没有调用
        • System.loadLibrary(“hello”);
    • 找动态链接库返回空 java.lang.UnsatisfiedLinkError: ….. findLibrary returned null
      • System.loadLibrary(“hello”); 动态链接库的名字写错
      • 没有编译出对应平台的.so文件 需要手动创建 Application.mk 指定
        • APP_ABI := armeabi x86
        • APP_PLATFORM := android-14

简便开发流程

  • ①写java代码 声明本地方法 用关键字 native 本地方法不用实现 具体的实现在C代码中
  • ② 添加本地支持 右键单击项目->android tools->add native surrport 添动态链接库的名字
    • 如果发现finish不能点击 需要配置NDK目录(每一个工作空间只需要配置一次NDK目录)
    • window->preferences->android->ndk 指定一下ndk解压的目录
  • ③ jni目录创建好之后 会有.cpp的源文件 Android.mk如果需要些.c文件 修改扩展名,修改Android.mk, Application.mk 需要手动创建 如果是x86的模拟器 需要创建Application.mk
  • ④ javah生成头文件
  • ⑤ 解决CDT插件报错的问题 右键单击项目->properties->c/c++ general->paths and symbols->includes选项卡->add…->File system->找到ndk解压目录 ->platforms文件夹 找到项目支持的最小版本文件夹下的include目录 指定进来
  • ⑥ 编写C代码 运行之前不要忘记 java中System.loadLibrary(“hello”);

C代码中打log

Android.mk文件增加以下内容
LOCAL_LDLIBS += -llog
# 加载android提供的.so库 如果加载liblog.so 
#LDLIBS load librarys的意思  -l就是加载的意思
C代码中增加以下内容
#include 
#define 是C的宏定义 可以给 字符串 和函数起别名
#define LOG_TAG "System.out"
//给__android_log_print函数起别名 第一参数 有限及 第二个参数打log的TAG
//LOGD 就是打印优先级是DEBUG的LOG 用法跟printf一样
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

C回调java

  • ①拿到字节码对象
  • // jclass (FindClass)(JNIEnv, const char*);
  • //第二个参数 要回调的java类的路径com/itheima/Ccallback/JNI
  • ②拿到方法
  • //第二个参数 刚创建的字节码对象
  • //第三个参数 要回调的java方法名 第四个参数 方法签名
  • //如何获取方法签名 javap命令 项目/bin/classes目录下运行javap -s 要获取方法签名的类的全类名
  • //jmethodID (GetMethodID)(JNIEnv, jclass, const char*, const char*);
  • ③通过字节码对象获取到java对象(可选)
  • //当回调方法跟本地方法没有声明到一个类中就要创建java对象
  • //jobject (AllocObject)(JNIEnv, jclass); jclass 刚创建的字节码对象
  • //需要注意的是 如果回调的方法在Activity中 不能自己new activity
  • ④调用方法
  • //void (Call***Method)(JNIEnv, jobject, jmethodID, …);
  • //根据返回值的类型选择不同的函数
  • //第二个参数 回调的方法所在的java对象 第三个参数刚创建的java方法对应的jmethodID
  • //可选的参数 回调方法要传的数据

你可能感兴趣的:(Android知识体系)