我的Android笔记--Hello Jni

来源:互联网 发布:windows 编译so 编辑:程序博客网 时间:2024/06/05 10:38

本人在学习NDK开发的时候,走了很多弯路,连一个普通Hello Jni的Demo都写不出来,网上也有很多相关资料,但是我比较笨,一直学不会。现在整理下思绪,分享一下如何写一个Hello Jni的小Demo,希望能帮到有需要的朋友。另外感叹一下,学习新东西并不难,难就难在没有思绪,毫无进展和难以坚持。成就感是最好的学习动力,如果在每个阶段都能有所收获,那么学习将会是一件很快乐的事情。

JNI

Java Native Interface,它提供了若干接口实现了Java语言和C&C++(主要的)的通信。官方的学习资料有Oracle的Java Native Interface Specification等,看这个文档很要命啊,不过也让我的阅读能力有了很大长进。国内的学习资料目前好像比较少,我在网上搜到了一篇叫《JNI完全技术手册》的很有帮助。

  • 编写Java类并生成头文件
  • 编写c语言文件
  • 编写Android.mk和Application.mk文件
  • 编译成动态库并调用

编写Java类

我这里使用C语言进行开发,IDE是Android studio,ndk版本是r12,另外需要在在Path中配置sdk和ndk的路径,否则使用起来比较麻烦。
首先,编写一个类,名字叫HelloJNI,在里面完成以下代码。

package cn.wdh.myself.hellojni.utils;public class HelloJNI {    static {        System.loadLibrary("hellojni");    }    public static native String getString();}

然后,进入到该Java文件的目录中去,生成.class文件,然后退出到cn文件夹的父目录,也就是module中的java目录,使用
javah -jni cn.wdh.myself.hellojni.utils.HelloJNI
命令,生成一个头文件,这个时候,他的文件名应该叫
cn_wdh_myself_hellojni_utils_HelloJNI.h
这个文件名是根据的类全名生成的,里面的内容是根据你的Java文件中定义的方法生成的。我的头文件的内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class cn_wdh_myself_hellojni_utils_HelloJNI */#ifndef _Included_cn_wdh_myself_hellojni_utils_HelloJNI#define _Included_cn_wdh_myself_hellojni_utils_HelloJNI#ifdef __cplusplusextern "C" {#endif/* * Class:     cn_wdh_myself_hellojni_utils_HelloJNI * Method:    getString * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_cn_wdh_myself_hellojni_utils_HelloJNI_getString  (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif

注意上文件内容,在extern “C” {}的这个括号里面,定义了Java类中哪些使用C语言(或其他语言)编写的方法。这个头文件我们可以自己写,但是为了省事,使用javah -jni命令生成的头文件还是很方便和安全的,不必为拼写错误烦恼。
另外,很多教程里面并没有该头文件的名称,其实这个头文件不必要这么长,头文件名称只要符合命名规则,长短是无所谓,为了编写C语言文件方便,我们将其改为hello.h。然后在module下,新建一个jni文件夹,将头文件丢进去。

编写C文件

在jni文件夹下,新建一个C文件,后缀是.c,文件名前缀和刚才生成并更改的头文件同名也叫hello。下面是代码内容

#include "hello.h"#include <stdio.h>JNIEXPORT jstring JNICALL Java_cn_wdh_myself_hellojni_utils_HelloJNI_getString(JNIEnv *env, jclass jc){    return (*env)->NewStringUTF(env,"Hello JNI!");}

方法名是从头文件中复制过来的,我们只要把形参写上就好了,方法体中的函数是JNI提供的一个方法,在Oracle的Java Native Interface Specification中列出了该接口提供的所有方法。

编写Android.mk文件

使用NDK开发,Android.mk文件的编写是关键,关于Android.mk的语法,Google提供的Android Developer有详细说明,下面是官网
https://developer.android.com/ndk/guides/android_mk.html[Android.mk语法]
文件同样放置在jni文件夹下,下面是Hello Jni工程的Android.mk文件的内容

#开头必须这么写LOCAL_PATH := $(call my-dir)#编译模块之前必须调用下面的语句include $(CLEAR_VARS)#指定生成的库文件名称LOCAL_MODULE = hellojni#指定源代码文件LOCAL_SRC_FILES = hello.c#编译的目标CPU架构库,all生成全部7个TARGET_ARCH_ABI = all#编译动态库include $(BUILD_SHARED_LIBRARY)

另外Application.mk在这个Demo中暂时用不到,他的语法在上面Android.mk中有跳转。

编译和引用

完成以上代码文件编写以后,我们只需要打开命令行串口,cd到项目的jni文件夹下面,使用ndk-build命令,就可以生成相应的动态库文件,后缀名是.so,我们只需要在项目main文件夹下面新建一个jniLIbs文件夹,然后将.so库放置进去即可。

后话

使用JNI配合NDK工具开发可以解决很多使用纯SDK开发解决不了的问题。例如加密解密,使用c进行文件加密解密的性能比使用java更快速,并且更难以被反编译获取加密和解密规则;我们也可以将用其他开源库编译到我们的项目中来,完成一些android平台提供不了的功能等等等。
哎,敲了这么长时间代码,真心觉得自己越来越low,岁数越来越大但却一事无成。技术也没长进,另使用Android Studio配置ndk开发环境也可以直接生产相应的C文件,这里的教程也可适用于eclipse,导包方式略微不同。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 信美分期没额度怎么办 家里人不给我钱怎么办 商场租金收不上来怎么办 魅蓝2电池坏了怎么办 格力空调不制冷怎么办 空调外机不好放怎么办 美的空调显示e3怎么办 发现安装空调条码被撕怎么办 删除了国美安装码怎么办 海信空调保修卡丢了怎么办 海尔空调保修卡丢了怎么办 科龙空调不制冷怎么办 魅族s6屏幕碎了怎么办 格力空调化霜怎么办 一开空调就跳闸怎么办 洗衣机顶盖的安全开关损坏怎么办 苹果平板电脑拍照坏了怎么办 苹果hom键不灵了怎么办 平板电脑home键发烫怎么办 华为平板无法输入资料怎么办 安卓平板没声音怎么办? 平果手机充不了电怎么办 苹果6s用电太快怎么办 平板充不起电了怎么办 日本买的电器国内售后怎么办 海淘地址试投不成功怎么办 怀孕了吐得厉害怎么办 玩网页游戏好卡怎么办 网页游戏占cpu高怎么办 微信有余额绑定其他名下怎么办 银行卡绑定支付余额不对怎么办 可乐机不制冷了怎么办 被淘宝卖家威胁怎么办 征信不好想贷款怎么办 急用钱征信不好怎么办 急用钱逾期不还怎么办 急用钱借款不还怎么办 做b超按压疼痛怎么办 做b超没有尿怎么办 b超憋不到尿怎么办 做b超前没有尿意怎么办