本博客是基於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