NDK的开发流程

作者: 小鱼爱记录 | 来源:发表于2017-04-19 19:05 被阅读387次

    我们这些做Android应用层的,大部分时间都是在使用Java编程,很少使用C/C++编程,对于NDK也了解的比较少,那么,现在就让我们来简单的了解一下NDK的开发流程吧。

    一、下载并配置NDK

    1 . 下载NDK,地址:http://developer.android.com/tools/sdk/ndk/index.html
    2 . 解压,解压得到的文件夹可以移动到其他文件夹,接下来把它的路径加入到环境变量里就行了

    1. 使用ndk-build命令,检查下配置是否成功

    二、在AndroidStudio配置项目的NDK环境

    1. 打开file->project structure,选择你所下载的ndk环境路径


    2. 在项目的gradle.properties文件末尾添加
    android.useDeprecatedNdk=true
    
    1. 在module的build.gradle ->defaultConfig内添加如下代码
    ndk {
        moduleName "NdkJniDemo"          //生成的so名字
        abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库
    }
    

    二、NDK的开发流程

    1.声明一个native方法,编译项目

    package com.soubu.jnidemo;
    
    /**
     * 作者:余天然 on 2017/4/19 下午4:31
     */
    public class JniUtils {
        public static native String getStringFormC();
    }
    

    2.查看是否生成了build/intermediates/classes/debug,有则打开Terminal,切换到此目录下,然后使用javah命令生成h文件

    javah -jni com.wobiancao.ndkjnidemo.ndk.JniUtils
    

    3.在main目录下新建jni目录,将生成的h文件复制到改此目录下,同时新建c文件或cpp文件实现h文件中的方法

    复制的com_soubu_jnidemo_JniUtils.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_soubu_jnidemo_JniUtils */
    
    #ifndef _Included_com_soubu_jnidemo_JniUtils
    #define _Included_com_soubu_jnidemo_JniUtils
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_soubu_jnidemo_JniUtils
     * Method:    getStringFormC
     * Signature: ()Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_com_soubu_jnidemo_JniUtils_getStringFormC
      (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    新建的ndkutils.c,需要自己实现具体的逻辑

    //
    // Created by 余天然 on 2017/4/19.
    //
    
    #include "com_soubu_jnidemo_JniUtils.h"
    
    JNIEXPORT jstring JNICALL Java_com_soubu_jnidemo_JniUtils_getStringFormC(JNIEnv *env, jobject obj) {
        return (*env)->NewStringUTF(env, "这里是来自c的string");
    }
    

    4.编译项目,查看在build/intermediates/ndk目录下是否生成了so文件

    6.在最初声明native类的地方,加载native库

    package com.soubu.jnidemo;
    
    /**
     * 作者:余天然 on 2017/4/19 下午4:31
     */
    public class JniUtils {
        public static native String getStringFormC();
    
        static {
            System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
        }
    
    }
    

    5.现在,我们就可以在Java中调用native方法了

    package com.soubu.jnidemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            TextView tv = (TextView) findViewById(R.id.tv_msg);
            tv.setText(JniUtils.getStringFormC());
        }
    
    }
    

    三、JniLibs的引用流程

    上面呢,我们还是直接引用的c文件,在调试好了c层的逻辑后,我们会将c文件打包成so文件。

    一般情况下呢,我们是将so文件而不是c文件交给第三方使用。

    这里呢,我新建一个jniLibs的module,通过so文件的方式,依赖刚才开发好的c层代码。

    1.在main目录下新建jniLibs目录,将刚才编译时生成的so文件复制到该目录下

    2.加载so文件,需要注意的是,加载so文件的包名、类名、方法名,一定要和之前开发时的保持一致,否则会报错:UnsatisfiedLinkError

    这里,我新建的module的包名其实是jnilibs,而开发时的jnidemo,一定要注意保证依赖时和开发时的路径一致!

    新建jnidemo包,保证路径一致。

    package com.soubu.jnidemo;
    
    /**
     * 作者:余天然 on 2017/4/19 下午4:31
     */
    public class JniUtils {
    
        static {
            System.loadLibrary("NdkJniDemo");//之前在build.gradle里面设置的so名字,必须一致
        }
    
        public static native String getStringFormC();
    
    }
    

    在jniLibs的包中,调用JniUtils的native方法

    package com.soubu.jnilibs;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.TextView;
    
    import com.soubu.jnidemo.JniUtils;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            TextView tv = (TextView) findViewById(R.id.tv_msg);
            tv.setText(JniUtils.getStringFormC());
        }
    }
    

    最后,奉上源码:GitHub-JNIDemo

    其它

    1. 如何配置环境变量?

    1 . 打开terminal(终端)
    2 . 输入 vim ~/.bash_profile,回车
    3 . 按英文键 i 进入编辑模式,在里面添加 export PATH=${PATH}:NDK路径
    4 . 按esc键退出编辑模式,输入:wq(冒号键+英文键w+英文键q),回车。(:wq 表示 保存并退出)
    5 . 输入source ~/.bash_profile,回车,以使前面的更改生效。

    相关文章

      网友评论

        本文标题:NDK的开发流程

        本文链接:https://www.haomeiwen.com/subject/esehzttx.html