cmake+JNI调用C/C++开发Base64编码解码APP

cmake+JNI调用C/C++开发Base64编码解码APP

声明:本人也是初学者,对于java语言也是刚开始学,下内容可能存在错误希望阅读者指正,部分内容也是参考其他网络文章,但是我找不到文件链接,表示很抱歉,也很感谢指导。

摘要:在Androidstudio中通过cmake分别实现了JNI调用C和JNI调用C++的两种方式实现Base64编码解码app开发

1 JNI
1.1 JNI简介
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境。

1.2 JNI的作用
JNI可以这样与本地程序进行交互:
  1. 你可以使用JNI来实现“本地方法”(native methods),并在JAVA程序中调用它们。
  2. JNI支持一个“调用接口”(invocation interface),它允许你把一个JVM嵌入到本地程序中。本地程序可以链接一个实现了JVM的本地库,然后使用“调用接口”执行JAVA语言编写的软件模块。
JNI是JAVA平台的一个重要特征,使用它我们可以重用以前用C/C++写的大量代码。JNI的部分设计思想来源于Netscape的Java Runtime Interface(JRI)。使用JNI可以结合C++和Java两种语言的不同优势,使得我们的开发产品具有更强大的功能和更好的体验。
一方面,C++具有很好的执行效率和广泛的算法开源库,但是C++的开发成本和维护成本都过高,而另一方面,Java有更广的应用场景(Web开发、服务器开发、移动开发等),Java提供JNI接口,能够使C++代码运行在Java的环境中,使C++具有更好的应用场景,一方面能够将海量的C++开源库进行代码复用,减少了开发成本。

2 Base64开发
2.1 开发环境
Android studio 3.0
JDK:Jdk是Java Development Kit的缩写,顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。
NDK:NDK是一系列工具的集合,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。
Cmake:是一个跨平台的编译(Build)工具,可以用简单的语句来描述所有平台的编译过程。

2.2 JNI调用C++开发Base64步骤
2.2.1 打开Android studio 新建一个工程base64,注意勾选Include C++ support 选项,勾选后会自动生成makeLists.txt文件
在这里插入图片描述
2.2.2 选择相应的安卓版本
2.2.3 添加一个空活动,择你所需要的C++标准,工程创建完成
可见自动生成了一个用于在应用程序启动时加载“native-lib”(本地)库,一个本地native调用的函数stringFromJNI(),并且在main文件夹下有一个cpp文件夹,在文件夹内的native-lib.cpp就有stringFromJNI()的接口
在这里插入图片描述
在这里插入图片描述
makeLists.txt文件
在这里插入图片描述
add_library( # Sets the name of the library.
native-lib – 设置库的名称

         # Sets the library as a shared library.
         SHARED   --将库设置为共享库。

         # Provides a relative path to your source file(s).
         src/main/cpp/native-lib.cpp  ---提供源文件的相对路径。此处可以根据自己的C/C++文件的具体位置更改设定)

build.gradle出现以下内容
在这里插入图片描述
2.2.4 设计app的应用界面
安卓app应用界面的设计是在app\res\layout\activity_main.xml下完成

2.2.6 编写接口
2.2.6.1 在MainActivity中编写本地调用接口,此时就是调用src/main/cpp/native-lib.cpp中的接口
在这里插入图片描述
2.2.6.2 在src/main/cpp/native-lib.cpp(此时native-lib.cpp是系统默认自动生成我们直接写入C++,不用其他操作)中编写C++源
写好接口函数如下:在这里插入图片描述
同样要加入你需要的.h 头文件,并且在cpp中声明:在这里插入图片描述
2.2.7 So文件生成
Make project一下就可以在cmake文件目录下看到生存了so文件
在这里插入图片描述
2.2.8 获取EditText的输入字符并且输出到TextView在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2.2.9 在布局按钮中设置响应,触发解码编码在这里插入图片描述
2.2.10 打包软件生成app
存在中文解码乱码错误!!!

2.3 JNI调用C开发Base64步骤
前期步骤同C++开发,界面完全相同,只是使用C语言进行JNI调用,以下是不同之处
2.3.1 创建c文件
在src/main/cpp目录下创建base64.c、base64.h文件
在这里插入图片描述
2.3.2 更改makeLists.txt使用C源码在这里插入图片描述
在这里插入图片描述
步骤可省略!

2.3.3 编写接口
在MainActivity中编写本地调用接口,此时就是需要调用src/main/cpp/base64.c中的接口
在这里插入图片描述
2.3.4 得到对应.class文件
Build project可在
app/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/dqp/base64
下得到MainActivity.class

2.3.5 生成对应的.h文件
使用命令javac -h + .class路径
就可以生成对应的.h文件,可在app\src\main\jni下
找到com_dqp_base64_MainActivity.h,其中就是C中对应的接口

在这里插入图片描述
将内容拷贝到之前创建的base64.h中

2.3.6 编写C代码,完成接口
同样也要先引入.h文件
在这里插入图片描述
2.3.7 So文件生成
在这里插入图片描述
2.3.8 完成MainActivity中数据的获取和输出并且调用base.c得到结果在这里插入图片描述
2.3.9 在布局按钮中设置响应,触发解码编码在这里插入图片描述
2.3.10 打包生成app

3 关于中文乱码问题
java 内部是使用的 16 bit 的 unicode 编码(utf-16)来表示字符串的,无论英文还是中文都是 2 字节。
JNI 内部是使用 utf-8 编码来表示字符串的,utf-8 是变长编码的 unicode,一般 ascii 字符是 1 字节,中文是 3 字节。
C/C++ 使用的是原始数据,ascii 就是一个字节,中文一般是 GB2312 编码,用 2 个字节表示一个汉字。
java 调用的时候使用的是 utf-16 编码的字符串,jvm 把这个参数传递给 JNI,C 得到的输入是 jstring,此时,可以利用 JNI 提供的两种函数进行解析:一个是 GetStringUTFChars,这个函数将得到一个 UTF-8 编码的字符串; 另一个是 GetStringChars 这个将得到 UTF-16 编码的字符串。无论那个函数,得到的字符串如果含有中文,都需要进一步转化成GB2312的编码。

解决方法:
1.C 端进行编码转换
C 端进行中文字符转换传递个 java 的时候,也是调用了 java 中 String 类的编码转换方式进行转换。
2.java 端进行编码转换
在 C 中,将 char* 转换为 jbyteArray,然后返回。在 Java端,获取数组,然后从”GB2312”格式生成 utf16 格式的java字符串。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值