android studio中使用ndk编译.so文件,调用C/C++代码(jni编程)
android studio中使用ndk编译.so文件,调用C/C++代码(jni编程)一.前言什么是NDK?NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和Java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或Linux系统环境),并提供了相应的mk文件隔离CPU、平台、A
android studio中使用ndk编译.so文件,调用C/C++代码(jni编程)
一.前言
什么是NDK?
NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和Java应用一起打包成apk。NDK集成了交叉编译器(交叉编译器需要UNIX或Linux系统环境),并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。
为什么使用NDK?
1、代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
2、可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
3、提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
4、便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。
什么是JNI?
JNI的全称是Java Native Interface,它提供了若干的API实现了Java和其他语言的通信(主要是C和C++)。
为什么使用JNI?
JNI的目的是使java方法能够调用c实现的一些函数。
安卓中的so文件是什么?
Android中用到的so文件是一个c++的函数库。在android的JNI中,要先将相应的C语言打包成so库,然后导入到lib文件夹中供java调用。
Android Studio NDK及so文件开发
在实际项目开发中,针对项目各异,我们一般都会调用底层的c/c++代码,或者一些开源项目,会用到它们的.so文件,但是我们根据项目不需要全部的功能,这时我们也会对它们的源码进行编译,生成自己想要的.so文件,这样也能有效缩减项目的体积.
二:安装NDK
1.打开android studio上的Tools选项,选择android选项中的sdk Manager,然后选择SDK Toos勾上LLDB和NDK,然后等待下载即可!
这里的LLDB是一个高效的c/c++的调试器,是与LLVM编译器一起使用,提供了丰富的流程控制和数据检测,有效的帮忙我们调试程序。
下载完后我们的NDK文件默认在sdk目录下的文件名为 ndk-bundle
2.配置NDK环境变量
在系统环境变量中新建变量名为NDK_ROOT,变量值为C:\Users\Administrator\AppData\Local\Android\sdk\ndk-bundle ,变量值为你的ndk路径
然后把你新建的NDK_ROOT系统变量配置到系统变量Path里,编辑Path,在后面加上 %NDK_ROOT%
这样NDK的环境变量就配置完成了
测试一下,打开cmd,输入ndk-build
这样我们的NDK都配置完毕了!
三.jni编程开发(生成.so库)
1.新建android项目,在MainActivity中新建一个getStrFromJNI()方法
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public native String getStrFromJNI();
}
getStrFromJNI()方法,通过native关键字,表示这个方法是通过本地代码(c/c++)实现的.
注意点 :
a. 在local.properties文件中配置ndk的路径
b.配置app的build.gradle
在build.gradle文件中的android中增加sourceSets节点,如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.administrator.ndkproject"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets{
main{
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.2.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
2.编译得到.h文件
在android studio底部栏切换到Terminal,找到你项目的java文件目录下输入javah -jni com.example.administrator.ndkproject.MainActivity, 其中com.example.administrator.ndkproject.MainActivity 为你包名下的在写了通过本地代码实现的方法所在的类
然后它会生成一个.h文件
3.编写.C文件
在我们项目的App目录下新建jni文件夹,在jni文件夹里新建demo.c文件,
编写测试代码,如下:
#include <jni.h>
jstring
Java_com_example_administrator_ndkproject_MainActivity_getStrFromJNI(JNIEnv *env,jobject thiz) {
return (*env)->NewStringUTF(env, "I`m Str from jni libs!");
}
4.编写Android.mk文件
在jni目录下新建Android.mk文件,mk文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := demo
LOCAL_SRC_FILES := demo.c
include $(BUILD_SHARED_LIBRARY)
其中LOCAL_MODULE := demo //要生成的so库的名称,但实际为libdemo.so
LOCAL_SRC_FILES := demo.c //要使用的文件,刚才编写的demo.c文件
5.编译生成.so库
打开cmd,找到你项目的app目录下,输入ndk-build
这样在libs目录就生成了各个版本的.so库文件
6.使用.so库
在MainActivity的onCreate中添加一个Log打印日志,并在类添加一个加载.so库文件方法并调用,代码如下:
package com.example.administrator.ndkproject;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("我的so文件", getStrFromJNI());
}
public native String getStrFromJNI();
static {
System.loadLibrary("demo");
}
}
运行程序,可以看到Android Monitor栏中打印出来的日志如下:
getStrFromJNI方法的内容为I’m Str form jni libs,也就是我们在一开始编写的demo.c文件自定义的字段
这样我们使用ndk编译.so文件,调用c/c++代码(jni编程)就大工告成了,但是在实际开发中,我们还有很多要做的,加油!
更多推荐
所有评论(0)