您的位置:首页 > 移动开发 > Android开发

android studio中使用ndk编译.so文件,调用C/C++代码(jni编程)

2017-05-23 13:57 781 查看

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编程)就大工告成了,但是在实际开发中,我们还有很多要做的,加油!

Demo下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: