Android Studio jni的開發與ndk的配置

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/huangf321123/article/details/52243660
一直想了解一下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的基本開發流程已經走通了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章