目录

一、环境配置

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文件夹下:

android mac studio 没有log mac android studio配置_Android Studio

  

此时已经不需要再将so文件拷贝到jniLibs的文件夹下面,我们再看下build文件夹下的jniLibs下已经不在生成so文件。为了方便对照与添加so文件的区别,我们也将这种情况下build文件截图下:

android mac studio 没有log mac android studio配置_ndk_02

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文件一起提供给第三方的。