Android Studio jni的开发与ndk的配置

一直想了解一下jni的开发流程是怎么样子的,刚好最近时间比较充裕,就学习了有关这方面的知识并且借鉴了一些优秀的blog。那为啥学写篇文章呢。。。主要是这个不常用,比较容易忘记,方便自己以后查看。当然了,如果能帮助到大家,那就更好了。好的。
接下来分两步走,第一介绍ndk以及ndk配置,第二,介绍jni的开发流程。

ndk的详细介绍

在Android developer上关于ndk的描述:The Native Development Kit (NDK) is a set of tools that allow you to leverage C and C++ code in your Android app. You can use it either to build from your own source code, or to take advantage of existing prebuilt libraries.
其大致意思就是:原生开发套件(NDK)是一套工具,使您能够充分利用C和C++代码在你的Android应用程序。你可以用它来建立你自己的源代码,或者是利用现有的lib库来创建你的应用程序。

ndk的下载,这里提供了两种途径:
1.https://developer.android.com/ndk/downloads/index.html(Android官网)
这里写图片描述
2.http://www.androiddevtools.cn/(Android镜像)
这里写图片描述

在Android Studio上ndk的配置。我用的是Android Studio 2.2 Prerview 6,其ndk可以在线下载,其ndk的配置步骤如下:

  • ndk的下载
    1.进入Default Settings界面设置面板

    2.选中Android SDK一栏

    3.点击右侧的SDK Tools

    4.找到LLDB、NDK这两项,勾选,点击ok,进行下载。下载时间可能有点长,请耐心等待。(这个需要翻墙)

这里写图片描述

这里写图片描述

  • ndk的配置

1.在Android Studio中,进入Default Settings -> Tools -> External Tools.

2.右侧点击“+”按钮,增加编译命令集成(个人叫法,不准勿怪啊)

这里写图片描述

3.增加3项编译命令集成。分别是 javah、ndk-build、ndk-build clean。
这里写图片描述

这里写图片描述

这里写图片描述
4.其详细添加如下(这个参考了别人的blog):

  javah    用于生成头文件
  Program:$JDKPath$/bin/javah
  注意:这个命令我加上了-encoding UTF-8 指定编码,你可以改成你工程的编码。
  Parameters:-encoding UTF-8 -d ../jni -jni $FileClass$
  Working directory:$SourcepathEntry$\..\java

  ndk-build    用于构建 so 包
  注意:MAC/Linux 用 ndk-build,没有.cmd 后缀,这个是你自己的ndk-build路径
  Program:C:\Develop\Android\sdk\ndk-bundle\ndk-build.cmd
  Parameters:什么都不用填
  Working directory:$ModuleFileDir$\src\main

  ndk-build clean    清除 so 包
  注意:MAC/Linux 用 ndk-build,没有.cmd 后缀,这个是你自己的ndk-build路径
  Program:C:\Develop\Android\sdk\ndk-bundle\ndk-build.cmd
  Parameters:clean
  Working directory:$ModuleFileDir$\src\main

好的,到此,ndk的配置就完成了。

jni的开发流程 ##

1.新建一个Android Studio项目TestJniNdkDemo.

2.对TestJniNdkDemo这个项目进行配置。

  • 在local.properties里面加入ndk的路径:
ndk.dir=C\:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk\\ndk-bundle
  • 在gradle.properties里面末尾加入android.useDeprecatedNdk=true这段代码

  • 在build.gradle(module:app)里面进行修改
    原来的代码:

 apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"
    defaultConfig {
        applicationId "com.example.administrator.testjnindkdemo"
        minSdkVersion 21
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.1.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha4'
    testCompile 'junit:junit:4.12'
}

修改后的代码:

//apply plugin: 'com.android.application'
apply plugin: 'com.android.model.application'//修改后的
model{
    android {
        compileSdkVersion 24
        buildToolsVersion "24.0.1"
        defaultConfig {
            applicationId "com.example.administrator.testjnindkdemo"
            minSdkVersion.apiLevel 14 //修改后的
            targetSdkVersion.apiLevel 24 //修改后的
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        //新增
        ndk {
            moduleName   "TestJniDemo"
        }
        buildTypes {
            release {
                minifyEnabled false
//                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                proguardFiles.add(file("proguard-rules.pro"))//修改后的
            }
        }
    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.1.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha4'
    testCompile 'junit:junit:4.12'
}
  • 在build.gradle(Project:TestJniNdkDemo)里面修改。

原来的代码:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-alpha6'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

修改后的代码:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
//        classpath 'com.android.tools.build:gradle:2.2.0-alpha6'
        //修改后的代码,注意最后面的版本,它对应着gradle-wrapper.properties里面的
        //distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip的版本号
        /**对应关系如下所示
         *       Plugin Version |  Gradle Version
         *          0.1.0       |        2.5
         *          0.2.0       |        2.5
         *      0.3.0-alpha3    |        2.6
         *          0.4.0       |        2.8
         *      0.6.0-alpha1    |        2.8
         *      0.6.0-alpha5    |        2.10
         *      0.7.0-alpha1    |        2.10
         *          0.7.0       |        2.10
         *          0.7.3       |        2.14.1
         * */
        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
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

3.项目配置完成后,进行第一次编译。

4.创建一个java文件TestJniDemo,其代码如下:

package com.example.administrator.testjnindkdemo;

/**
 * Created by Administrator on 2016/8/19.
 */

public class TestJniDemo {
    static {
        //加载要使用的 so 文件
        System.loadLibrary("TestJniDemo");
    }
    public static native String helloJni();
}

5.对TestJniDemo这个java类进行编译。

这里写图片描述

6.编译完成后,在cpp(或者是jni)文件夹下会生成一个.h文件。
com_example_administrator_testjnindkdemo_TestJniDemo.h,其内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_administrator_testjnindkdemo_TestJniDemo */

#ifndef _Included_com_example_administrator_testjnindkdemo_TestJniDemo
#define _Included_com_example_administrator_testjnindkdemo_TestJniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_administrator_testjnindkdemo_TestJniDemo
 * Method:    helloJni
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_administrator_testjnindkdemo_TestJniDemo_helloJni
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

7.在cpp文件夹(或者是jni文件夹)下创建一个c语言代码,后缀为.cpp的TestJni的c代码。代码如下:

#include <com_example_administrator_testjnindkdemo_TestJniDemo.h>

JNIEXPORT jstring JNICALL Java_com_example_administrator_testjnindkdemo_TestJniDemo_helloJni
        (JNIEnv *env, jclass type) {//该方法来自.h文件里面的方法

    return env->NewStringUTF("jni ndk sucess!!!");
}

这里写图片描述

8.对项目进行编译

9.在cpp或者是jni文件下,创建两个.mk文件。分别是Android.mk、Application.mk。

Android.mk文件内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := TestJniDemo //这个是build.gradle 里面设的ndk的moduleName
LOCAL_SRC_FILES := TestJni.cpp //这个是c语言代码类
include $(BUILD_SHARED_LIBRARY)

Application.mk文件内容如下:

APP_MODULES := TestJniDemo
APP_ABI := all

这里写图片描述

这里写图片描述

10.对jni或者是cpp文件夹进行ndk-build编译。

这里写图片描述

这里写图片描述

11.在MainActivity里面去调用TestJniDemo这个类。实现相应的功能。
代码如下:

package com.example.administrator.testjnindkdemo;

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);
        tv.setText(TestJniDemo.helloJni());
    }
}

12.在app上运行,得到正确的结果。

这里写图片描述

好了,到此为止,jni的基本开发流程已经走通了。

猜你喜欢

转载自blog.csdn.net/huangf321123/article/details/52243660