JNI就是Java-Native-Interface的缩写,它提供了若干API实现了Java和其他语言的通信(在Android中主要是C/C++)

Android调用jni在Android studio2.2版本前后是一个分水岭,之前提供的API在Android studio3.0之后被删除了,我们先回顾一下之前是怎么调用的:

  1.     首先写一个java类,这个方法名有可能报红,不要担心,当我们最后使用.so调用这个方法的就正常了。 Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第1张图片
  2. 然后用命令行生出来一个jni文件夹,首先我们要配置好jdk和ndk的环境,将当前位置指向我们的项目路径,但是我们需要明白的是:这一步生成.h的头文件是通过命令行编译.class文件形成的,当第一步完成后build->make Project重构代码,让项目中的代码生成java文件对应的class文件,找到这个文件对应的路径,在命令窗口,使用命令行生成对应的.h文件    Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第2张图片
  3.  这一步做完之后我们能看到,在项目根目录生成一个jni文件夹,但是这个位置我们是不能用的,那么应该怎么做呢,我们需要在main目录下新建一个jni文件夹,可以这样去生成这个文件夹 Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第3张图片当生成jni这个文件夹后,将项目根目录下的jni文件夹中生成的.h文件复制到main目录下的jni文件夹中,这个时候我们只是声明了c或者cpp的方法,接下来继续创建一个.c文件,这一段c代码和上一步生成的.h头文件要绑定联系起来就是#include ".h文件带后缀全部复制过来",然后再JNICALL 调用的后边方法名称要和.h 头文件的方法名完全相同,不然会找不到我们在第一步声明的方法,这个是c的写法,如果我们习惯使用cpp(也就是c++语言),return env->NewsStringUTF((char *)"hello,jni!!") Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第4张图片
  4. 方法我们现在实现了,那么应该如何调用,首先引入动态库:
    package test.test;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.TextView;public class MainActivity extends AppCompatActivity {    // Used to load the 'native-lib' library on application startup.libName需要和build.gradle ndk节点下面的名字一样    static {        //这个名字需要和build.gradle ndk节点中一致        System.loadLibrary("native-lib");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        // Example of a call to a native method        TextView tv = (TextView) findViewById(R.id.sample_text);        tv.setText(stringFromJNI());    }    /**     * A native method that is implemented by the 'native-lib' native library,     * which is packaged with this application.     */    public native String stringFromJNI();}

    native-lib,就是我们要生成的.so文件名,这样在stringFromJNI()方法中获取到的String类型的数据就是.so文件中对应的函数传输的数据。

5、现在是最重要的一步,应该怎么生成.so文件呢?

  1. 在根目录gradle.properties下面加上:Android.useDeprecatedNdk=true这个意思就是允许使用低版本的NDK
  2. 在model下面的build.gradle中加上ndk节点具体位置如下图:Android{}中,defaultConfig括号下面建立ndk文件夹Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第5张图片

注意:moduleName这里的名字要跟引入动态库的名字一样,按理说有这两步我们就可以了,实际上是不行的,我们先看看log

             Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第6张图片

在这里当时我郁闷了好久,自己写的代码和别人的完全一样,步骤和配置也都是正确的,用有道翻译了半天才发现,这是因为AS在3.0以后推荐我们使用CMake来集成使用JNI-NDK开发,那么完全使用CMake开发模式后续再学习,这里引申出一个问题,假如接手一个老项目,AndroidAPI还手动调高了,系统强制使用CMake的开发方式,那么我们应该怎么办?

1、先通过SDKManager下载:CMake和LLD

Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第7张图片

2、在build.gradle的defaultConfig节点下加入:

android {    compileSdkVersion 26    defaultConfig {        applicationId "test.test"        minSdkVersion 15        targetSdkVersion 26        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        externalNativeBuild {            cmake {                cppFlags ""            }        }    }}
3、在build.gradle的android节点下加入:
// 配置CMakeLists.txt路径    externalNativeBuild {        cmake {            path "CMakeLists.txt"   // 设置所要编写的c源码位置,以及编译后so文件的名字        }    }

如图所示:

              Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第8张图片

4、添加CMakeLists.txt文件到build.gradle文件的统计目录下,具体内容如下:


                                             Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第9张图片

# For more information about using CMake with Android Studio, read the# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.#CMakeLists.txtcmake_minimum_required(VERSION 3.4.1)# Creates and names a library, sets it as either STATIC# or SHARED, and provides the relative paths to its source code.# You can define multiple libraries, and CMake builds them for you.# Gradle automatically packages shared libraries with your APK.add_library( # Sets the name of the library.             # 设置so文件名称.             testJNI             # Sets the library as a shared library.             SHARED             # 设置这个so文件为共享.             # Provides a relative path to your source file(s).             # 配置这个so文件的位置.              src/main/jni/testjni.c) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable.                log-lib                # Specifies the name of the NDK library that                # you want CMake to locate.                log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library.                        # 制定目标库.                        testJNI                        # Links the target library to the log library                        # included in the NDK.                        ${log-lib} )

注意:这里需要更改的就是写了注释的这几句,第一处和第三处都是讲其更改为so文件的名字,第二处代表或者说位置指向了(我们在jni文件夹中声明了一个.c类型的文件用来实现.h声明的c函数)当前这个.c文件的位置。

补一句:突然记起来 这个.so文件是怎么产生的,我们跑一遍程序,运行一下今天写的代码,.so文件就会在下列对应的位置生成出来

到这里我们就配置完所有事项了:.so文件我们去哪里找呢?如图下这个位置

                               Android使用JNI生成.so文件并调用(使用传统生成.h的方法)_第10张图片

可以看到我们已经成功生成so文件。调用的时候可以使用JNIUtils的实例来获取 nativie修饰的方法

更多相关文章

  1. Android本地视频播放器开发--ffmpeg解码视频文件中的音频(1)
  2. android studio运行编译速度慢的解决方法
  3. android之文件上传
  4. Flutter 解决webview_flutter 插件Android端无法上传文件问题
  5. android中共享全局数据的方法
  6. Android的内存优化方法
  7. APPS大乱斗:4大Android文件浏览器横评(一)
  8. 原来Android还可以这样通过反射,获取jar包属性及方法

随机推荐

  1. Android(安卓)XmlSerializer 换行
  2. Ubuntu 10.4下 Android(安卓)ADT的编译
  3. Android(安卓)Suspend
  4. Mms模块ConversationList流程分析
  5. Android(安卓)Please ensure that adb is
  6. java.lang.NoClassDefFoundError: net.yo
  7. sysclktz 0
  8. Android数据存储技术
  9. Android(安卓)获取控件的高度或者宽度的
  10. Android学习七---Hello OpenCV samples