Android Studio NDK 學習之接受Java傳入的Int數組

本博客是基於Android Studio 1.3 preview版本,且默認你已經安裝了Android SDK, Android NDK。html

用Android Studio新建一個工程叫AndroidJNI_IntArray,其目錄結構以下:java

├── AndroidJNI_IntArray.imlandroid

├── appapi

│   ├── app.iml數組

│   ├── buildapp

│   ├── build.gradleide

│   ├── libs函數

│   ├── proguard-rules.progradle

│   └── srcui

├── build

│   └── intermediates

├── build.gradle

├── gradle

│   └── wrapper

├── gradle.properties

├── gradlew

├── gradlew.bat

├── local.properties

└── settings.gradle

切換到android視圖,可見以下目錄:

第一步,編寫JNI代碼:

一、新建jni文件夾,在jni文件夾下建立logger.h,用來打印輸出日誌的,其內容以下:

#ifndef ANDROIDJNI_INTARRAY_LOGGER_H
#define ANDROIDJNI_INTARRAY_LOGGER_H

#include <jni.h>
#include <android/log.h>

/**
 * 定義log標籤
 */
#define TAG "jni_logger"

/**
 * 定義info信息
 */
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

/**
 * 定義debug信息
 */
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

/**
 * 定義error信息
 */
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

#endif //ANDROIDJNI_INTARRAY_LOGGER_H

二、接着建立intarray_jni.c主要用來註冊綁定java函數和native函數,以及java函數在c中相應函數的具體實現, 內容以下:

#include "logger.h"

#ifndef NULL
#define NULL ((void *) 0)
#endif

/**
 * 獲取數組大小
 */
#define NELEM(x) ((int)(sizeof(x) / sizeof((x)[0])))

/**
 * 指定要註冊的類,對應完整的java類名
 */
#define JNIREG_CLASS "com/ndk/clarck/MainActivity"

/**
 * 返回數組中元素的和
 */
JNIEXPORT jint JNICALL native_sumArray(JNIEnv *env, jobject obj, jintArray arr) {
    jint *carr;
    jint i, sum = 0;
    carr = (*env)->GetIntArrayElements(env, arr, NULL);
    if (carr == NULL) {
        return 0;
    }

    for (i = 0; i < 10; i++) {
        sum += carr[i];
    }
    (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
    return sum;
}

/**
 * Java和JNI函數綁定
 */
static JNINativeMethod method_table[] = {
        {"sumArray", "([I)I", (void *)native_sumArray},
};

/**
 * 註冊native方法到java中
 */
static int registerNativeMethods(JNIEnv *env, const char* className,
        JNINativeMethod* gMethods, int numMethods) {
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }

    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * 調用註冊方法
 */
int register_ndk_load(JNIEnv *env) {
    return registerNativeMethods(env, JNIREG_CLASS, method_table, NELEM(method_table));
}

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = -1;

    if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }

    register_ndk_load(env);
    return JNI_VERSION_1_4;
}

三、java層調用以下:

package com.ndk.clarck;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int arr[] = new int[10];
        for (int i = 0; i < 10; i++) {
            arr[i] = i;
        }
        int sum = sumArray(arr);
        Log.d("Test", "sum: " + sum);
    }

    public native int sumArray(int[] arr);

    static {
        System.loadLibrary("intarray_jni");
    }
}

 

第二步,配置以下環境,執行編譯命令:

一、在local.properties配置SDK和NDK路徑以下:

 sdk.dir=xxxx

 ndk.dir=xxx

 

二、打開gradle-wrapper.properties,將其配置修改成使用Gradle 2.5來編譯(詳情參考:http://www.cnblogs.com/tanlon/p/4731283.html):

複製代碼
#Mon Aug 17 20:34:50 HKT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip
複製代碼

 

三、配置Project下面的build.gradle,其內容以下:

// 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-experimental:0.2.0'

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

allprojects {
    repositories {
        jcenter()
    }
}

四、配置Module下面的build.gradle,其內容以下:

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 22
        buildToolsVersion = "22.0.1"

        defaultConfig.with {
            applicationId = "com.ndk.clarck"
            minSdkVersion.apiLevel    = 15
            targetSdkVersion.apiLevel = 21
        }
    }

    android.ndk {
        moduleName = "intarray_jni"
        ldLibs    += ["log"]
    }

    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles += file('proguard-rules.pro')
        }
    }

    android.productFlavors {
        create ("arm7") {
            ndk.abiFilters += "armeabi-v7a"
        }
        create ("arm8") {
            ndk.abiFilters += "arm64-v8a"
        }
        create ("x86-32") {
            ndk.abiFilters += "x86"
        }
        // for detailed abiFilter descriptions, refer to "Supported ABIs" @
        // https://developer.android.com/ndk/guides/abis.html#sa

        // build one including all cpu architectures
        create("all")
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
}

五、執行Build->Make Project,獲得以下輸出:

Information:Gradle tasks [:app:assembleAllDebug]
:app:copyArm64-v8aDebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createArm64-v8aDebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileArm64-v8aDebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkArm64-v8aDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsArm64-v8aDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:arm64-v8aDebugAllIntarray_jniSharedLibrary
:app:copyArmeabi-v7aDebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createArmeabi-v7aDebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileArmeabi-v7aDebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkArmeabi-v7aDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsArmeabi-v7aDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:armeabi-v7aDebugAllIntarray_jniSharedLibrary
:app:copyArmeabiDebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createArmeabiDebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileArmeabiDebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkArmeabiDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsArmeabiDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:armeabiDebugAllIntarray_jniSharedLibrary
:app:preBuild UP-TO-DATE
:app:preAllDebugBuild UP-TO-DATE
:app:checkAllDebugManifest
:app:preAllReleaseBuild UP-TO-DATE
:app:preArm7DebugBuild UP-TO-DATE
:app:preArm7ReleaseBuild UP-TO-DATE
:app:preArm8DebugBuild UP-TO-DATE
:app:preArm8ReleaseBuild UP-TO-DATE
:app:preX86-32DebugBuild UP-TO-DATE
:app:preX86-32ReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72220Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42220Library UP-TO-DATE
:app:prepareAllDebugDependencies
:app:compileAllDebugAidl UP-TO-DATE
:app:compileAllDebugRenderscript UP-TO-DATE
:app:generateAllDebugBuildConfig UP-TO-DATE
:app:generateAllDebugAssets UP-TO-DATE
:app:mergeAllDebugAssets UP-TO-DATE
:app:generateAllDebugResValues UP-TO-DATE
:app:generateAllDebugResources UP-TO-DATE
:app:mergeAllDebugResources UP-TO-DATE
:app:processAllDebugManifest UP-TO-DATE
:app:processAllDebugResources UP-TO-DATE
:app:generateAllDebugSources UP-TO-DATE
:app:processAllDebugJavaRes UP-TO-DATE
:app:compileAllDebugJavaWithJavac
:app:copyMips64DebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createMips64DebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileMips64DebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkMips64DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsMips64DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:mips64DebugAllIntarray_jniSharedLibrary
:app:copyMipsDebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createMipsDebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileMipsDebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkMipsDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsMipsDebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:mipsDebugAllIntarray_jniSharedLibrary
:app:copyX86DebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createX86DebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileX86DebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkX86DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsX86DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:x86DebugAllIntarray_jniSharedLibrary
:app:copyX86_64DebugAllIntarray_jniSharedLibraryGdbServer UP-TO-DATE
:app:createX86_64DebugAllIntarray_jniSharedLibraryGdbsetup
:app:compileX86_64DebugAllIntarray_jniSharedLibraryIntarray_jniMainC UP-TO-DATE
:app:linkX86_64DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:stripSymbolsX86_64DebugAllIntarray_jniSharedLibrary UP-TO-DATE
:app:x86_64DebugAllIntarray_jniSharedLibrary
:app:compileAllDebugSources
:app:preDexAllDebug UP-TO-DATE
:app:dexAllDebug
:app:validateDebugSigning
:app:packageAllDebug
:app:zipalignAllDebug
:app:assembleAllDebug
Information:BUILD SUCCESSFUL
Information:Total time: 2.772 secs
Information:0 errors
Information:0 warnings
Information:See complete output in console

六、執行Run,便可運行項目了。

 

經驗:

Error:Cause: com.android.build.gradle.managed.AndroidConfig Impl 緣由:defaultConfig 必須寫成 defaultConfig.with

相關文章
相關標籤/搜索