目录
一、环境配置
1、安装NDK
2、配置环境变量
二、创建jni工程
三、Android studio的jni环境的配置
四、打开终端,进入到app/src/main/jni下生成so文件
五、编译项目,可以获取到c层的代码
六、想当然的几个坑
1、生成的so文件就要拷贝到项目中,否则不能调用jni的代码
2、生成的so文件可以直接给第三方使用
一、环境配置
1、安装NDK
在使用android studio进行jni开发的时候,需要配置ndk,ndk是Android的开发工具。
把下载下来的android-ndk-r15c-x86_64.bin放到你要解压的文件夹中。 之后打开你的终端,cd到android-ndk-r15c-x86_64.bin所在的目录,修改bin文件的执行权限,并进行安装。
$ chmod a+x android-ndk-r15c-x86_64.bin 回车
$ ./android-ndk-r15c-x86_64.bin 回车
2、配置环境变量
在终端回到根目录下,输入open -e .bash_profile进入环境配置,
$ vi ~/.bash_profile
export NDK_PATH=/Users/linyong/Documents/android/android-ndk-r10e
export PATH=$NDK_PATH:$PATH
$ source ~/.bash_profile
二、创建jni工程
1、在项目的目录下创建关于native接口的java文档
public class UrlBusiness{
static {
System.loadLibrary("retrofit");
}
public static String native xxx();
}
2、编译项目生成class文件
3、通过终端进入到在app/build/intermediates/classes/debug,生成.h文件
$ javah -d jni com.j1.retrofit.UrlBusiness //UrlBusiness所在的包名也要加上
将生成的com_j1_retrofit_UrlBusiness.h文件拷贝到项目的app/main/jni/的目录下;
4、创建.c文件实现响应的代码。最好有一个empty.c的空文件
5、创建Android.mk文件
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := retrofit //编译的so文件名
LOCAL_SRC_FILES := UrlBusiness.c //指定的编译文件
include $(BUILD_SHARED_LIBRARY)
三、Android studio的jni环境的配置
1、 配置Android studio 的NDK
在local.properties中添加配置
ndk.dir=/Users/j1/Documents/android/sdk-macosx/ndk-bundle
2、添加旧版本的支持
在gradle.properties中添加
android.useDeprecatedNdk=true
3、添加ndk节点
在build.gradle中添加
defaultConfig {
........
ndk {
moduleName "retrofit"
abiFilters "arm64-v8a", "armeabi", "armeabi-v7a","mips","mips64", "x86", "x86_64"
}
}
sourceSets{
main{
jni.srcDirs = []
}
}
四、打开终端,进入到app/src/main/jni下生成so文件
$ndk-build
将会在src/main/下生成两个文件夹libs和obj,只要将libs文件夹重命名为jniLibs即可。
五、编译项目,可以获取到c层的代码
在java中只要调用UrlBusiness.getBaseUrl()就可以获取到对应c层代码对应的功能
六、想当然的几个坑
1、生成的so文件就要拷贝到项目中,否则不能调用jni的代码
上述的几个步骤,是要将生成的so文件放到项目中。所以我就有一种理解误区,以为生成的so文件就要拷贝到项目中才能用。
其实还有一种方式是直接通过gradle进行NDK编译,不需要再将生成的文件拷贝到项目中。这样好处在于:防止修改了jni代码,而没有及时更新so库。
注意:gradle版本需要2.2及以上
项目中的gradle配置如下:
defaultConfig {
//省略其他配置.........
ndk {
moduleName "retrofit"
abiFilters "arm64-v8a", "armeabi", "armeabi-v7a","mips","mips64", "x86", "x86_64"
}
externalNativeBuild {
cmake{
cppFlags ""
abiFilters "arm64-v8a", "armeabi", "armeabi-v7a","mips","mips64", "x86", "x86_64"
}
}
}
externalNativeBuild {
ndkBuild {
path file("src/main/jni/Android.mk") //定义的mk文件的路径
}
}
我们再去看生成的build文件夹下:
此时已经不需要再将so文件拷贝到jniLibs的文件夹下面,我们再看下build文件夹下的jniLibs下已经不在生成so文件。为了方便对照与添加so文件的区别,我们也将这种情况下build文件截图下:
jniLibs里面有so文件,此时已经没有ndkBuild的文件夹了。
2、生成的so文件可以直接给第三方使用
如果生成的so文件没有将本地接口类打包到so文件时,那么我们去定义jni的接口类的时候其实并不是自己可以随意定义的,定义的方法名必须与so文件的方法名、包名和类名必须一一对应。
怎么去查看so文件里面的类和函数的定义方式呢?
MacBook-Pro:jniLibs j1$ nm -D mips/libretrofit.so
000004f0 T Java_com_j1_retrofit_UrlBusiness_getBaseUrl
00000524 T Java_com_j1_retrofit_UrlBusiness_getCategoryUrl
00011030 A __bss_end__
00011030 A __bss_start
U __cxa_atexit
U __cxa_finalize
00011030 A __end__
00011030 A _bss_end__
00011030 A _edata
00011030 A _end
00011030 A _fbss
00011000 D _fdata
00000490 T _ftext
gMacBook-Pro:jniLibs j1$
从第一行和第二行中可以明显的看到里面的几个方法,所以在定义接口类时,必须创建相同包名、类名、方法名的接口类。
通常在将so文件提供给第三方的时候,需要将接口类打包成jar,配合so文件一起提供给第三方的。