Android Studio下 NDK配置与Jni开发流程

来源:互联网 发布:淘宝男士机械手表 编辑:程序博客网 时间:2024/06/05 16:55

学习学习在学习,闲来无事找个东西学,一直觉得jni可以Java调用C很神奇,于是来探探玄奇,看了网上的关于AS开发环境下 jni的开发文章,对开发的流程还是有点疑问,于是自己动手琢磨了一下,并编写了简单的demo,理清楚了大致流程,本文着重讲述AS下的jni流程,不涉及代码的编写,记录下自己的积累过程,不正确的地方望指出!!!


概念性的就不讲了,来说说流程,说到底也就是那几步


配置ndk

->创建Java文件,编写本地方法

->根据本地方法,在C/C++文件中编写jni代码

->进行编译生成.so链接库文件

->在创建的Java文件中的静态代码块中加载生成.so文件

->在需要调用的地方调用本地方法

一、环境配置

1、在SDK Tools选项下 选择NDK 下载,将下载到对应sdk目录中的ndk-bundle目录

2、将ndk-bundle绝对路径配置到系统的path变量中


cmd命令行输入ndk-build,将会有看着像错误信息的提示,表示配置成功


3、在以下几个文件中配置相关参数
gradler.properties:
android.useDeprecatedNdk=true

local.properties:(指示ndk的路径)
ndk.dir=E\:\\Android\\sdk\\ndk-bundle
sdk.dir=E\:\\Android\\sdk


也可通过Project Structure指定


二、创建本地方法并编译生成.so文件

1、创建Jni.java 文件,在此文件中添加native修饰的方法
package com.haha.jnidemo;public class Jni {    public native String getString();}


2、Terminal 定位到java目录(也可以是其他目录,定位到哪里,执行后面指令生成的.h文件就在那个目录) 
执行 javah com.haha.jnidemo.Jni(包名+类名) 指令 生成.h文件

刷新下目录,如下所示:
3、复制生成的.h文件到jni目录下,创建hello.c文件,并编写逻辑代码

#include "com_haha_jnidemo_Jni.h"#include "jni.h"JNIEXPORT jstring JNICALL Java_com_haha_jnidemo_Jni_getString  (JNIEnv * env, jobject obj){    return (*env)->NewStringUTF(env, "hello world !");//简单地返回 hello world!字符串  }}

此处也可不使用.h文件,之所以用javah命令,是因为会根据我们所定义的本地方法,自动生成相应函数,避免自己手敲带来的意想不到错误,大牛可直接根据本地方法名写出函数(有命名规律)

代码的逻辑编写请自行百度,本文只讲述流程,不涉及如何编写jni代码

4、配置相关参数

app\build.gradle:(主module下的build.gradle)

android {compileSdkVersion 25buildToolsVersion "25.0.3"defaultConfig {...ndk{moduleName "hello"  //待编译生成的目标.so文件名称abiFilters "armeabi", "armeabi-v7a", "x86" //编译成这些架构的.so文件}}sourceSets{main{jniLibs.srcDirs = ['libs']jni.srcDirs = []}}}




在app\src\main目录下生成jni目录,(或者 右键app->New->Folder->JNI Folder, 默认是在main目录下生成jni目录)


在jni目录下,创建以下两个文件,名字要一样

Android.mk:
LOCAL_PATH := $(call my-dir)  //包含本文件的当前目录include $(CLEAR_VARS)LOCAL_MODULE := hello //生成目标.so文件名称LOCAL_SRC_FILES := hello.c //待编译成.so文件的.c文件include $(BUILD_SHARED_LIBRARY)


此文件指示了将哪个.c文件编译成哪个.so文件,需跟app\build.gradle中配置一致


Application.mk:
APP_ABI := armeabi armeabi-v7a x86  //支持什么架构的.so文件  ALL为支持所有,多个架构用空格隔开APP_PLATFORM := android-14  //min sdk version



5、Terminal 定位到jni目录,执行ndk-build指令对.c文件进行编译,
编译中显示的内容:
执行完ndk-build命令,将会在src\main\java\libs目录下生成几个架构目录,这些目录下有对应的.so文件,前缀为lib

将这些架构目录复制到最外层根目录下libs目录中


至此,.so文件已经编译成功,但是要想链接此文件,需要加载它


6、在Jni.java文件中加入静态代码块,在其中调用System.loadLibrary()方法加载生成的.so文件
package com.haha.jnidemo;public class Jni {    static {        System.loadLibrary("hello");//加载 .so文件    }    public native String getString();}

7、调用Jni中的方法,编译运行app
package com.haha.jnidemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.widget.Toast;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Jni jni = new Jni();        String string = jni.getString();        Toast.makeText(MainActivity.this, "String: " + string,                Toast.LENGTH_LONG).show();    }}

运行起来后,将弹出一个吐司显示hello world!


ps: 如果需要修改native方法的话,在每次修改native方法后,都需要执行ndk-build命令,重新编译生成.so文件,并将其复制到根目录下libs目录中




原创粉丝点击