close
当前位置: 物联网在线 > 技术文库 > android >

android studio下,JNI和NDK的简单编程

Java JNI 本意是Java Native Interface(java 本地接口),他是为了方便Java调用C、C++等本地代码所封装的一层接口。

NDK 是android所提供的一个工具集合,通过NDK可以在Android中更加方便地通过JNI来访问本地代码,比如C或者C++。NDK还提供了交叉编译器,开发人员只需要简单的修改mk文件就可以生成特定的CPU平台的动态库。

使用NDK有如下好处:

提高代码安全性。由于so库反编译比较困难,因此NDK提高了Android程序的安全性。

可以很方便的使用目前已有的C/C++开源库。

便于平台间的移植。通过C/C++实现的动态库可以很方便地在其他平台上使用。

提高程序在某些特定情形下的执行效率,但是并不能明显提升android程序的性能。

NDK的开发流程(本文以android studio 为例)

下载配置NDK

首先到官网下载NDK: NDK下载入口

下载完成后,如图找到 Project Structure 完成配置。

android studio下,JNI和NDK的简单编程

屏幕快照

创建一个Android项目,并声明所需的native方法

public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textView); set("hello world from JniTestApp"); textView.setText(get()); } /** * A native method that is implemented by the 'jni-test' native library, * which is packaged with this application. */ public native void set(String str); public native String get(); // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("jni-test"); } }

实现Android项目中所声明的native方法

首先说一下android studio 的自动编译产生so库。

先创建test.cpp文件

//test.cpp #include <jni.h> #include <stdio.h> #ifdef __cplusplus extern "C" { #endif jstring Java_com_ryg_JniTestApp_MainActivity_get(JNIEnv *env, jobject thiz) { printf("invoke get in c++\n"); return env->NewStringUTF("Hello from JNI in libjni-test.so !"); } void Java_com_ryg_JniTestApp_MainActivity_set(JNIEnv *env, jobject thiz, jstring string) { printf("invoke set from C++\n"); char* str = (char*)env->GetStringUTFChars(string,NULL); printf("%s\n", str); env->ReleaseStringUTFChars(string, str); } #ifdef __cplusplus } #endif

为了能够让androidStudio自动编译JNI代码,首先需要在APP 的build.grade 的 defaultConfig 区域内添加NDK选项,其中moduleName指定了模块的名称,这个名称指定了打包后的so库的文件名。

android { ... defaultConfig { ... ndk { moduleName "jni-test" } } }

接着需要将JNI的代码放在 app/src/main/jni 目录下,

android studio下,JNI和NDK的简单编程

屏幕快照

注意存放 JNI代码的目录名必须为jni,如果不想采用jni这个名称,可以通过如下方式来指定JNI的代码路径,其中jni.srcDirs 指定了JNI 代码的路径:

android { ... sourceSets.main { jni.srcDirs 'src/main/jni_src' } }

经过上面步骤,AndroidStudio就可以自动编译JNI代码了,但是这个时候AndroidStudio 会把所有CPU平台的so库都打包apk,一般来说实际开发只需要打包armeabi 平台的so库即可。 解决这个问题也简单,按照如下方式修改build.gradle配置。

android { ... productFlavors { arm { ndk { abiFilter "armeabi" } } x86 { ndk { abiFilter "x86" } } } }

然后找到Build Variants 面板中选择armDebug 选项进行编辑就可以了。

android studio下,JNI和NDK的简单编程

屏幕快照

android studio下,JNI和NDK的简单编程

屏幕快照

除了以上方法,我们还可以使用NDK 手动的去生成所需要的so库

这里首先我们需要配置我们的环境变量(Macbook为例):

首先打开配置文件

open ~/.bash_profile

然后添加如下信息:

export PATH=/Users/vince/Downloads/adt-bundle-mac-x86_64-20140702/sdk/ndk-bundle/:$PATH

其中 /Users/vince/Downloads/adt-bundle-mac-x86_64-20140702/sdk/ndk-bundle/ 是我本地NDK的存放路径。

添加完成后,执行

source ~/.bash_profile

来刷新刚设置好的环境变量。设置完成后,我们通过 ndk-build 命令来编译生成so库。

接下来需要 在外部创建一个名为jni的目录,然后创建三个文件:test.cpp、Android.mk、Application.mk。

//Application.mk APP_ABI := armeabi
(责任编辑:ioter)

用户喜欢...

Android Weekly #276 安卓开发周刊 中文版

您是否了解过Android的Lifecycle-Aware库?(android.jlelse.eu) 我们如何了解Lifecycle-Aware库代码? Nishant Srivastava展示了可以跟踪活动或Lifecycle-Aware的Lifecycle Arch组件的片段,并相应地调整其行为。 为Mos...


Android Weekly #275 安卓开发周刊 中文版

MapMe — Android地图适配器 (medium.com) Josh Burton介绍MapMe,是一个用Kotlin编写的Android库,可以将适配器模式带到地图上。 赞助 CloudRail - 连接到API 10x更快 (cloudrail.com) 当我们用单一的界面连接到所...


使用Android Studio开发可独立运行(runnable)混淆过的Jar程序

之前开发Java程序一直都是使用Eclipse 开发Jar程序,现在开发基本上都已经弃用Eclipse了,但是有时偶尔开发个小的Jar程序,还要切换回去好麻烦,刚好前几天有人问几个相关的问题,就顺便整...


Android Weekly #274 安卓开发周刊 中文版

探索Android Oreo上的别后执行限制(medium.com) 在这篇文章中,Joe Birch解释了关于Android Oreo在后台运行服务的变化。 non-Time领主的time – 第5部分 (blog.stylingandroid.com) Mark Allison继续分析JSR 310 date和...


Android Weekly #273 安卓开发周刊 中文版

开源你的Android代码(android.jlelse.eu) 通过您的开源Android代码,您将(希望地)为Android社区提供有价值的代码,收到建设性的反馈,并与您最初建立的内容进行协作从而使您的代码变得更好。这...


Android Weekly #272 安卓开发周刊 中文版

Android Dev 101:每个初学者都应该知道的一些做法() 看一些初学者或媒介等级开发人员(不要错过任何人)应该知道的一些做法,以便更好地摆脱Android框架。 99.9% crash free sessions (medium.com) Chr...


Android Weekly #271 安卓开发周刊 中文版

依赖注入检查(medium.com) 在本文中,MihályNagy引入了依赖注入检查,一种开源注释处理器,可帮助您解决一些出现在所有JSR 330 DI库中常见的问题。 使用Android Studio插件提高效率 (blog.mindorks.com...


Android Weekly #270 安卓开发周刊 中文版

带有RxJava2的SOLID Android分析 (medium.com) 在这篇文章中,Aris Papadopoulos将解释如何正确创建一个分析系统,同时遵循SOLID原则,并使用RxJava2来解决问题。 (blog.stylingandroid.com) Java中的编程时间很难...


Android内存泄漏思考

Android内存泄漏是一个经常要遇到的问题,程序在内存泄漏的时候很容易导致OOM的发生。那么如何查找内存泄漏和避免内存泄漏就是需要知晓的一个问题,首先我们需要知道一些基础知识。...


Android Weekly #269 安卓开发周刊 中文版

在Google上快速提出操作 () Wolfram Rittmeyer分享了开始在Google上快速创建操作所需的所有信息(为了家庭与助理)。 RxJava中的错误处理(rongi.github.io) 一旦开始编写RxJava代码,你就会意识到有些事...