Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> AndroidStudio2.0搭建Ndk環境&成功編譯使用

AndroidStudio2.0搭建Ndk環境&成功編譯使用

編輯:關於Android編程

現在使用Ndk開發的場景還蠻多,游戲引擎、音視頻開發等都能涉及到,以前的工程大部分都是Eclipse的工程目錄,但是App開發現在大部分都是在AndroidStudio開發工具中進行的,那就有個問題了?怎麼在As中搭建Ndk的環境呢。這就是本篇文章所要解答的,並且會創建一個小例子,編譯成.so文件,且在項目中使用。Come on….

在沒具體動手之前我們想一想怎麼實現比較好吧,假如我們新建一個As2.0的工程,然後按照他的目錄結構把jni層文件放到指定的目錄下,然後進行開發,固然可行,可行是可行,但是代價就是Sdk開發和Ndk開發就分離了,不在一個工程目錄下,不符合我們的預期,那就換種思路吧。慶幸的是,As的gradle腳本功能比較強大,可以指定源碼文件,操作任務等。如果只是修改一下配置文件,就把事情給做好了,那豈不是皆大歡喜。好吧 開始做了。

首先在工程Module的src目錄下新建一個jni目錄(存放我們的c、c++源碼及mk文件)
\
然後最關鍵的是要在build.gradle配置一下說明jni裡面的代碼是咱們的ndk編譯代碼位置,及做一些編譯任務的處理 下面配置代碼由 成都 小妖<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPiDM4bmpo6zM2LHwuNDQu8v7PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> task buildNative(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = android.ndkDirectory if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } else { commandLine "$ndkDir/ndk-build", '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source '-j', Runtime.runtime.availableProcessors(), 'all', 'NDK_DEBUG=1' } } //在 mac 中 commandLine "$ndkDir/ndk-build", 但是在windows中 commandLine "$ndkDir/ndk-build.cmd",額,坑 // task cleanNative(type: Exec, description: 'Clean JNI object files') { def ndkDir = android.ndkDirectory if (Os.isFamily(Os.FAMILY_WINDOWS)) { commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } else { commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source 'clean' } } // clean.dependsOn 'cleanNative' tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn buildNative }

注意上面的有一個變化的地方就是jni的路徑在哪,src/jni 如果跟我不一樣的,應該寫你的具體位置

然後在我們的代碼中添加一個Native方法,就讓他打印一個helloworld吧

public native void printHelloworld();

然後使用javah命令 生成對應的.h頭文件
\
這樣會在下面目錄生成2個文件,當然下面的那個文件不用管它了

然後把生成的這倆文件放到剛才創建的jni裡面
下面就是編寫cpp文件Android.mk Application.mk文件了

.h文件代碼

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_qbao_ticket_MainActivity */

#ifndef _Included_com_qbao_ticket_MainActivity
#define _Included_com_qbao_ticket_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_qbao_ticket_MainActivity
 * Method:    add
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_qbao_ticket_MainActivity_printHelloworld
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

.cpp文件代碼

#include 
#include 
#include "com_qbao_ticket_MainActivity.h"
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_qbao_ticket_MainActivity_printHelloworld
  (JNIEnv *, jobject){
  LOGI("hello world! come from jni");
}

注意新建寫的時候 一定要加上

#include "com_qbao_ticket_MainActivity.h"

然後寫咱們的mk文件,先來Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := lalala

LOCAL_SRC_FILES := com_qbao_ticket_MainActivity.cpp

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

要改的地方是咱們的module名稱源文件列表 這裡根據自己的代碼設置就好了

接下來Application.mk

APP_ABI := all
APP_PLATFORM := android-8

設置了全平台,當然不設置也可以 默認就行了

點擊這個按鈕 開始編譯
\
編譯成功會在src目錄下生成一個libs和obj.local目錄
然後就生成了咱們命名的liblalala.so文件 格式為lib{模塊名}.so

下面是怎麼在代碼中使用咱們生成的.so文件了

把我們的編譯生成好的.so文件拷貝到代碼的libs中armeabi目錄下

然後是在我們的代碼中使用它

static {
   System.loadLibrary("lalala");
}
public native  void printHelloworld();

注意load的時候寫模塊名 不是文件名 這裡是lalala 然後在MainActivity裡面調用這個printHelloworld方法
打印一下log

好了到這裡在As2.0中搭建Ndk環境並且編譯so文件,並使用so文件的介紹已經講完了,後面會在這個基礎上編譯一些音視頻模塊的代碼,然後封裝使用。期待吧。。。

build.gradle全部配置查看

import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
}

android {
    compileSdkVersion 21
    buildToolsVersion "22.0.1"
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }

        // Move the tests to tests/java, tests/res, etc...
        instrumentTest.setRoot('tests')

        // Move the build types to build-types/
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src//... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }
    buildTypes {
        debug {
            //proguardFile '/Users/xuchuang/Desktop/Stifler/WorkSpace/QBaoTicket_2.0/qbaoticket_2.0/proguard-project.txt'
            //signingConfig signingConfigs.qbaoticket
        }
        release {
            //signingConfig signingConfigs.qbaoticket
            //minifyEnabled true
            //proguardFile '/Users/xuchuang/Desktop/Stifler/WorkSpace/QBaoTicket_2.0/qbaoticket_2.0/proguard-project.txt'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    dexOptions {
        jumboMode true
    }
}

task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
    def ndkDir = android.ndkDirectory

    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine "$ndkDir/ndk-build.cmd",
                '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                '-j', Runtime.runtime.availableProcessors(),
                'all',
                'NDK_DEBUG=1'
    } else {
        commandLine "$ndkDir/ndk-build",
                '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                '-j', Runtime.runtime.availableProcessors(),
                'all',
                'NDK_DEBUG=1'
    }
}
//在 mac 中 commandLine "$ndkDir/ndk-build", 但是在windows中 commandLine "$ndkDir/ndk-build.cmd",額,坑
//
task cleanNative(type: Exec, description: 'Clean JNI object files') {
    def ndkDir = android.ndkDirectory
    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
        commandLine "$ndkDir/ndk-build.cmd",
                '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                'clean'
    } else {
        commandLine "$ndkDir/ndk-build.cmd",
                '-C', file('src/jni').absolutePath, // Change src/main/jni the relative path to your jni source
                'clean'
    }
}
//
clean.dependsOn 'cleanNative'

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn buildNative
}

參考資料

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved