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

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

  1.     首先写一个java类,这个方法名有可能报红,不要担心,当我们最后使用.so调用这个方法的就正常了。
  2. 然后用命令行生出来一个jni文件夹,首先我们要配置好jdk和ndk的环境,将当前位置指向我们的项目路径,但是我们需要明白的是:这一步生成.h的头文件是通过命令行编译.class文件形成的,当第一步完成后build->make Project重构代码,让项目中的代码生成java文件对应的class文件,找到这个文件对应的路径,在命令窗口,使用命令行生成对应的.h文件   
  3.  这一步做完之后我们能看到,在项目根目录生成一个jni文件夹,但是这个位置我们是不能用的,那么应该怎么做呢,我们需要在main目录下新建一个jni文件夹,可以这样去生成这个文件夹 当生成jni这个文件夹后,将项目根目录下的jni文件夹中生成的.h文件复制到main目录下的jni文件夹中,这个时候我们只是声明了c或者cpp的方法,接下来继续创建一个.c文件,这一段c代码和上一步生成的.h头文件要绑定联系起来就是#include ".h文件带后缀全部复制过来",然后再JNICALL 调用的后边方法名称要和.h 头文件的方法名完全相同,不然会找不到我们在第一步声明的方法,这个是c的写法,如果我们习惯使用cpp(也就是c++语言),return env->NewsStringUTF((char *)"hello,jni!!")
  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文件夹

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

            

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

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


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文件的名字        }    }

如图所示:

             

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


                                            

# 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文件我们去哪里找呢?如图下这个位置

                              

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

更多相关文章

  1. Android需要大量内存时自己设置堆大小
  2. Android中滑屏初探 ---- scrollTo 以及 scrollBy方法使用说明
  3. 【干货】测试Android应用安全性
  4. Android(安卓)下用 Pull 解析和生成 XML
  5. android UI进阶之style和theme的使用
  6. 使用谷歌提供的支持库(Android)
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. 时隔三年再更新!绝对良心工具,免费好用
  2. 3.17 c语言自定义函数
  3. Bug!Redis 6.0.8紧急发布,请尽快升级!
  4. 超赞!墙裂推荐一个 MySQL 自动化运维工具!
  5. 介绍一个可以离线查询 IP 来源和 ISP 信
  6. 史上首例!阿里程序员写的这三行代码,被国家
  7. 时间同步、双因子安全验证及自动化安装实
  8. 2021年全新永久有效Phpstorm激活码
  9. tp6 多文件上传
  10. 网络发展遭遇瓶颈期,如何推动SDN/NFV解决