Android进阶

NDK的开发流程

2017-04-19  本文已影响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,回车,以使前面的更改生效。

上一篇下一篇

猜你喜欢

热点阅读