Android Studio使用jni环境配置


使用AndroidStudio编写原生层应用,有两种方式:
1,官方示例,Gradle+Cmake+LLDB+NDK
官方示例,如何向安卓中添加C/C++代码

2,老方法通过NDK中的ndk-build编译Android.mk文件

官方的示例可以通过上述链接查看,有个缺点就是有时候会因为无法翻的问题,得通过自己去下载配置Cmake和LLDB这些工具。

因此,本文详细说明方法2,传统原生编写应用方法在AndroidStudio中的应用。

主要步骤:

1,下载NDK,ndroid-ndk-r13b
2,在app/build.gradle中添加sourceSets
3,配置javah,ndk-build命令
4,添加NDK支持
5,创建jni文件夹,build -> Make Project
6,调用javah命令
7,编写Android.mk,Application.mk文件
8,编写XXX.cpp,实现.h文件中的方法
9,调用ndk-build命令

1-4步是环境配置步骤
5-9步则是安卓应用的动态库创建的过程

详解:

1,下载ndk

这里要注意一下,最好下载高版本的ndk,有时候低版本的ndk会报错。。。不知道为什么

2,在app/build.gradle中添加代码
sourceSets.main{
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'

    }

jni.srcDirs = []代表告诉gradle,jni中的文件交给我们自己来处理,不需要gradle帮忙处理,而由我们手动调用ndk-build方式去生成so动态链接库;
jniLibs.srcDir ‘src/main/libs’代表我们生成的库文件(.so)所存放的位置;

app/build.gradle完整代码

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.yyt.myinject"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

       //如果要gradle来生成so库,则需要下列代码,可能还需要指定加载的其他库
       //这几行代码相当于Android.mk和Application.mk两个文件的作用
       // ndk {
       //     moduleName "MyLibrary" //库名称
       //     abiFilters "armeabi"   //指定平台类型
       // }
    }


    sourceSets.main{
        jni.srcDirs = []
        jniLibs.srcDir 'src/main/libs'

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
 ………………
}
3,配置javah,ndk-build命令

javah是通过java文件生成jni调用的.h头文件的命令。
ndk-build是用来编译动态库的命令。

一般的做法是点击AS下方的Terminal控制台,通过控制台进入指定目录下调用上述命令。这就比较麻烦。

参考这篇文章中的External Tools的方法定义javah和ndk-build命令
超级简单的Android Studio jni 实现(无需命令行)

打开File-Settings-Tools-External Tools

点击+号新建命令:

android studio 的配置文件存在哪 android studio如何配置环境_android-C+

主要是看Tool settings中的填写:

Program:指的是要运行的文件的地址,即命令所对应的程序的绝对路径,$JDKPath$ 是指JDK所在的文件路径,是通过右侧的Insert macro按钮添加的,里面还有很多参数。

Parameters:指的是命令执行的参数,这里的参数有两个,第一个是类文件所在的目录,第二个是目标类文件名称

Working directory:指的是该命令在哪个文件夹下执行,即当前目录是什么。

再添加ndk-build命令:

android studio 的配置文件存在哪 android studio如何配置环境_jni_02

在Windows下面ndk-build好像无法直接访问,只能访问ndk-build.cmd命令行代码。

4,添加NDK支持

File -> Project Structure ->SDK Location ->Android NDK location中添加下载的NDK的根目录地址

5,创建jni文件夹,然后build -> Make Project

android studio 的配置文件存在哪 android studio如何配置环境_Android_03

然后点击build -> Make Project生成 .class文件

6,调用javah命令

右键待生成.h头文件的类文件,选择在External Tools中定义的javah命令。

android studio 的配置文件存在哪 android studio如何配置环境_java_04

当我们右键我们要生成头文件的java类文件MainActivity调用External Tools中的javah命令时执行的命令是:

android studio 的配置文件存在哪 android studio如何配置环境_jni_05

会在jni文件夹创建出一个com_yyt_myinject_MainActivity.h文件。

7,编写Android.mk,Application.mk文件

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := MyInject
LOCAL_SRC_FILES := com_yyt_myinject_MainActivity.cpp
LOCAL_LDLIBS    := -lm -llog
include $(BUILD_SHARED_LIBRARY)

LOCAL_PATH := $(call my-dir),第一行好像都是这样子。。表示当前路径是调用的路径

include $(CLEAR_VARS) 表示清楚之前的参数定义和申明,如果一个mk文件中包含多个库需要编译,每个库之间都要调用include $(CLEAR_VARS)

LOCAL_MODULE := MyInject 是动态库的库名称,和MainActivity中的System.load(“MyInject”) 语句中的待加载的动态库的名称对应

LOCAL_SRC_FILES := com_yyt_myinject_MainActivity.cpp 表示当前动态库需要包含的源代码

LOCAL_LDLIBS := -lm -llog 表示当前需要用到的其他的库函数,包括系统的和第三方的

include $(BUILD_SHARED_LIBRARY) 好像是表示编译的库的类型

Application.mk

APP_MODULES := MyInject
APP_ABI := armeabi

表示需要编写的库对应的平台类型,即机器指令的类型。

8,编写XXX.cpp,实现.h文件中的方法

我们如果发现在编写CPP文件时,AS没有进行自动的代码不全时,我们需要进行一个设置。

File -> Link C++ Project with Gradle

android studio 的配置文件存在哪 android studio如何配置环境_Android_06

Build System 选择ndk-build

Project Path 选择当前项目对应的Android.mk文件的路径

android studio 的配置文件存在哪 android studio如何配置环境_Android_07

9,调用ndk-build命令

同第六步,右键jni文件夹,调用External Tools中的ndk-build命令。