Android Studio NDKJNI开发

    xiaoxiao2025-01-16  7

    前言

           我们在一步一步学习JNI(一)学习了怎么进行Jni开发,当时说道了怎么编写native函数,怎么进行加载,怎么进行so生成,当时的都是在eclipse下生成的。这里我们就来说说Android Studio下怎么进程开发。

    下载NDK

           在jni开发之前,需要先下载NDK。路径如下:

           下载完成后,NDK是放置在SDK下的,有一个ndk-bundle文件夹。老版本是单独的一个目录,因此以下根据新旧版本来区分讲解。

    开发流程

           第一步当然是创建一个Android工程了。创建完工程后主代码如下:

    public class MainActivity extends Activity { private TextView showSum; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViews(); loadSum(); } private void findViews() { showSum = (TextView) findViewById(R.id.sum); } private void loadSum() { showSum.setText("Result=" + HelloJni.getSum(3, 5)); } }

           这里我们引用了一个HelloJni.getSum函数,主要逻辑在HelloJni里面。创建完工程后,主要有一下一些步骤:

    新版本步骤

    编写native函数配置gradle编译生成class文件实现jni文件运行

    编写native函数

            我们来编写HelloJni类,首先是编写native函数。

    public class HelloJni { static { System.loadLibrary("Hello"); } public static native int getSum(int a, int b); }

           这里代码很简单,跟一步一步学习JNI(一)很类似,主要是跟前面做一个对比,看看最终的效果。这里首先在静态块里面加载了so,之后有一个getSum的native函数。

    配置gradle

           首先将整个工程的gradle下的dependencies节点改成如下,需要gradle2.5版本以上:

    dependencies { //classpath 'com.android.tools.build:gradle:2.1.0' classpath 'com.android.tools.build:gradle-experimental:0.7.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files }

           其次将app下的gradle改成如下,主要apply plugin从com.android.application变成了com.android.model.application,多了一层model节点,其他所有配置项都空格变成了等号。

    apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 23 buildToolsVersion = '23.0.2' defaultConfig { minSdkVersion.apiLevel = 14 targetSdkVersion.apiLevel = 23 } /* * native build settings: taking default for almost everything */ ndk { moduleName = 'Hello' toolchain = 'clang' CFlags.addAll(['-Wall']) } buildTypes { release { minifyEnabled = false proguardFiles.add(file('proguard-rules.txt')) } } productFlavors { // for detailed abiFilter descriptions, refer to "Supported ABIs" @ // https://developer.android.com/ndk/guides/abis.html#sa create("arm") { ndk.abiFilters.add("armeabi") } create("arm7") { ndk.abiFilters.add("armeabi-v7a") } create("arm8") { ndk.abiFilters.add("arm64-v8a") } create("x86") { ndk.abiFilters.add("x86") } create("x86-64") { ndk.abiFilters.add("x86_64") } create("mips") { ndk.abiFilters.add("mips") } create("mips-64") { ndk.abiFilters.add("mips64") } // To include all cpu architectures, leaves abiFilters empty create("all") } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.4.0' }

    编译生成class文件

           编译生成class文件很简单,只需要Build→Make project就好了。

           最终生成的代码在工程/Jni/app/build/intermediates/classes/debug下,会有很多个class文件。

    实现jni

           首先在新创建一个jni目录,默认在java节点下,目录名为jni:

           创建完成后,在jni目录下新建一个.c文件,默认是一个空文件,手动添加#include <jni.h>,之后就可以到之前编写的native函数,这个地方可以用快捷键自动生成映射函数到新创建的.c文件下,生成的函数如下:

    JNIEXPORT jint JNICALL Java_com_net_jni2_Hello_get(JNIEnv *env, jobject instance, jint a, jint b) { // TODO }

    运行

            有时可能需要clean一次,我出现了第一次运行后失败,clean才ok的,之后点击run:

    老版本步骤

    编写native函数编译生成class文件根据class生成头文件实现头文件生成so运行

    编写native函数

           同新版本

    编译生成class文件

           同新版本

    根据class生成头文件

           生成class后就该生成.h文件了。我们可以在Android Studio中用命令行来生成。打开命令行窗口,路径如下View→Tool Window→Terminal:

           在命令行输入生成.h文件的命令,我们将生成后的.h文件放置到app→src→main下,输入命令进入main文件夹下:

    cd app/src/main/

           进入目录后输入生成.h的命令,在前面我们已经学习过怎么生成.h文件了。我们先看看之前的生成方式:

    javah -d jni -classpath /Users/doc/Android/Jni/app/build/intermediates/classes/debug com.net.jni.HelloJni

    -jni为可选参数 -classpath 类查找路径 -d 生成的文件放到-d后指定的目录,如果不存在在生成,这里放到jni目录

           可以看到在main下生成了jni文件夹,并且生成了一个com_net_jni_HelloJni.h的头文件。

           这个地方我们是新建了一个类来实现JNI,但是如果你直接在Activity中使用native函数又该怎么办?输入如下的命令:

    javah -d jni -classpath /Users/doc/Library/Android/sdk/platforms/android-23/android.jar;/Users/doc/Android/Jni/app/build/intermediates/classes/debug com.net.jni.HelloJni

           这里classpath里面多指定了一个路径,指向了sdk中的android.jar,这是因为在Activity中需要继承父类的Activity,需要用到android.jar中的文件。        不过编译命令后可能会出现如下的异常:

    bash: /Users/doc/Android/Jni/app/build/intermediates/classes/debug: is a directory

           这是由于系统的不同classpath后的书写方式不同。将(分号);号改成(冒号):号。

    -classpath /Users/doc/Library/Android/sdk/platforms/android-23/android.jar:/Users/doc/Android/Jni/app/build/intermediates/classes/debug com.net.jni.HelloJni

    实现头文件

           在一步一步学习JNI(一)我们已经学习了怎么实现头文件,在jni文件夹下新建HelloJni.c文件,将头文件中的函数拷贝到HelloJni.c中,并实现。

    #include "com_net_jni_HelloJni.h" #ifdef __cplusplus extern "C" { #endif /* * Class: com_net_jni_HelloJni * Method: getSum * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_net_jni_HelloJni_getSum (JNIEnv *env, jclass cls, jint a, jint b){ return a+b; } #ifdef __cplusplus } #endif

    生成so

           在local.properties下指定NDK路径。

    ndk.dir=/Users/doc/Library/Android/sdk/ndk-bundle

           开始配置build.gradle,gradle改成如下:

    defaultConfig { applicationId "com.net.jni" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "Hello" } }

           还可以配置abiFilters等信息,之后Make project就可以生成so。

    运行

           最终运行效果同新版本。

    总结

           当升级了Android Studio后不能再用老的方式实现,不知道是不是我不知道怎么实现,如果有人知道望告知,升级后编写很简单,可以自动生成对应的jni函数,只需要实现里面的逻辑就好,这是老版本不能实现的。如果不知道怎么更改gradle可以去查看官方的文档,文档路径

    转载请注明原文地址: https://ju.6miu.com/read-1295524.html
    最新回复(0)