赞
踩
前言
都知道的,Android基于Linux系统,然后覆盖了一层由Java虚拟机为核心的壳系统。跟一般常见的Linux+Java系统不同的,是其中有对硬件驱动进行支持,以避开GPL开源协议限制的HAL硬件抽象层。
大多数时候,我们使用JVM语言进行编程,比如传统的Java或者新贵Kotlin。碰到对速度比较敏感的项目,比如游戏,比如视频播放。我们就会用到Android的JNI技术,使用NDK的支持,利用C++开发高计算量的模块,供给上层的Java程序调用。
本文先从一个最简单的JNI例子来开始介绍Android中Java和C++的混合编程,随后再介绍Android直接调用ELF命令行程序的规范方法,以及调用混合了第三方库略微复杂的命令行程序。
Android Studio配置
第一个配置是安装Android的SDK,这是开发Android程序必须的。
进入Android Studio的设置界面,Mac的快捷键是Command+,,Windows和Linux版本请自行从菜单中选择。
在设置界面中,从左侧顺序选择:Appearance&Behavior -> System Settings -> Android SDK,可以进入到SDK的设置。
右侧的SDK版本列表中,最前面显示了✔️或者后面显示了Installed,表示该版本的SDK已经安装。通常如果没有特殊需要,只安装1个最新版本的SDK即可。图中我是因为某些项目特殊的要求,安装了两个特定不同版本的SDK。
希望安装某版本的SDK,只要点选相应行最前面的多选框,然后单击右下角确认按钮即可安装。
如果不是自己从头开始,而是接手了其他开发人员的源码,源码中可能指定了特定版本的SDK。这时候可以修改其项目配置文件中版本的设置,到你安装的SDK版本。更简单的方法是直接在这里安装对应的SDK,防止因为版本依赖出现的很多繁琐问题。
第二个配置的是NDK,还在刚才SDK设置的界面中,点击界面上侧中间的“SDK Tools”标签,可以进入到NDK设置的界面。
NDK的设置没有那么多的选择,只要安装就好,已经安装碰到有新版本,也可以随性选择更新或者使用老版本继续。NDK不同版本间的兼容性都还不错,大多都不用担心。
NDK的设置是Android开发中,Java/C混合编程需要的。
第三个配置是增加一个外部工具javah,这个工具是将Java编写的“包装”文件,转换一个C/C++的.h文件。虽然Java/C++都是面向对象语言,但两者的面向对象实现是不同的。所以在Java中某个类的方法,转换到C++的世界中,是使用很长的函数名来做区分。这种情况使用手工编写虽然效果一样,但很容易出错,使用javah工具则能自动完成。
在Android Studio设置界面左侧的列表中,顺序选择Tools -> External Tools,单击右侧界面左下角的“+”,新建一个工具,比如就叫"javah"。
其中三个需要设置的内容分别是:
javah程序路径:$JDKPath$/bin/javah,这个跟jdk安装的路径有关。
命令行参数:-classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$,主要指定输出路径。
工作目录:$ModuleFileDir$/src/main/Java,当前项目路径。
至此Android Studio的主要设置就完成了,当然只是最基本必须的设置,如果自己还有其它需求,类似git仓库地址等,可以再自行设置。
下面就可以开始进行项目的开发。
先准备一个基本的Android程序
在Android Studio界面选择New Project,如果是在开始界面,直接点击主界面上的按钮;也可以在文件菜单中选择。
选择基本的Empty Activity就好。
接着是项目的设置,项目名称、存储位置这些都不用说了,最低的API版本决定了你的程序可以在最低什么版本的Android手机上执行,如果没有特殊需要,尽量可以低一点,毕竟Android手机的升级比例,比iOS是低了好多倍的。
这样,项目就建立完成,Android Studio使用标准模板,对项目做了初始化。我们可以在这个基础上再添加自己的内容。
从屏幕左侧项目文件的列表中,选择app -> res -> layout -> acitvity_main.xml文件,文件会在右侧打开,模式是交互式的界面设计器。在其中,按照下图的样子,我们增加一个TextView控件和一个按钮。文本框是为了将来显示输出的结果,按钮当然就是开始执行的触发器。
TextView控件我们修改一下名字,叫textView1。按钮的名字改为button1,另外为按钮的onClick属性增添一个调用:bt1_click。
界面部分就完成了,记着存盘,然后可以关掉这个文件。
这时候,Android Studio界面会显示在MainActivity.java文件的位置。这是新建项目之后自动打开的文件,也是这个项目的主窗口程序文件。我们首先编辑窗口布局文件的时候,这个文件被隐藏在了后面。
我们在文件的库引用部分,增加如下两行:
import android.widget.TextView;
import android.view.View;
这两行是我们接下来的程序会使用到的库引用。
在类的变量声明部分,增加这样两行:
TextView textview1;
int c=0;
第一行是声明一个文本框,用于关联到刚才界面编辑器中加入的文本框。
c变量就是一个简单的计数器,我们希望每点击一次按钮,这个计数器累加1,从而确认我们每次点击都被响应了,而不是程序没有任何反馈给用户。
在onCreate函数的最后,增加关联文本框的代码:
textview1=(TextView)findViewById(R.id.textView1);
R.id.后面的textView1就是我们在界面编辑的时候,为文本框起的名字。
接着,在类的最后,增加按钮点击响应的处理函数:
public void bt1_click(View view){
c = c+1;
textview1.setText("click:"+c);
}
清晰起见,我们把这部分完成的代码再抄过来一遍:
package com.test.calljni;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.view.View;
public class MainActivity extends AppCompatActivity {
TextView textview1;
int c=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textview1=(TextView)findViewById(R.id.textView1);
}
public void bt1_click(View view){
c = c+1;
textview1.setText("click:"+c);
}
}
程序完成,可以从Build菜单选择Make Project编译项目。然后在Run菜单选择Run 'app'。
如果是第一次使用Android Studio,你还可能会被提醒需要你新建一个Android模拟器来执行程序。当然也可以把打开了调试功能的Android手机插在电脑上进行真机调试。
执行的结果如图:
点击两次按钮后,画面变为:
好了,我们的基本实验平台准备完成,下面才是进入正题。
调用JNI库
每个JNI库都分为两部分,一个是C++编写的.so动态链接库,另一部分则是Java对这个动态链接库的封装。我们先从Java部分看起。
编写JNI库的Java封装类
开始写这个JNI库之前,我们首先要对这个库的总体功能、结构划分、接口类型充分做好规划,这样才能保证两种语言之间的顺畅调用。因为尚没有一种工具可以同时有效的对两种语言进行跟踪调试,所以在接口部分如果碰到问题,往往只能在大量的日志输出中去查找线索,费时费力。
作为一个简单的演示,我们的JNI库功能很简单,从Java封装的角度看,我们有一个名为JniL
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。