zoukankan      html  css  js  c++  java
  • Android Studio NDK 学习之接受Java传入的Int数组

    本博客是基于Android Studio 1.3 preview版本,且默认你已经安装了Android SDK, Android NDK。

    用Android Studio新建一个工程叫AndroidJNI_IntArray,其目录结构如下:

    ├── AndroidJNI_IntArray.iml

    ├── app

    │   ├── app.iml

    │   ├── build

    │   ├── build.gradle

    │   ├── libs

    │   ├── proguard-rules.pro

    │   └── src

    ├── build

    │   └── intermediates

    ├── build.gradle

    ├── gradle

    │   └── wrapper

    ├── gradle.properties

    ├── gradlew

    ├── gradlew.bat

    ├── local.properties

    └── settings.gradle

    切换到android视图,可见如下目录:

    第一步,编写JNI代码:

    1、新建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

    2、接着创建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;
    }

    3、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");
        }
    }

    第二步,配置如下环境,执行编译命令:

    1、在local.properties配置SDK和NDK路径如下:

     sdk.dir=xxxx

     ndk.dir=xxx

    2、打开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
    复制代码

    3、配置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()
        }
    }

    4、配置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'
    }

    5、执行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

    6、执行Run,即可运行项目了。

    经验:

    Error:Cause: com.android.build.gradle.managed.AndroidConfig Impl 原因:
    defaultConfig 必须写成 defaultConfig.with

  • 相关阅读:
    C++ 栈和队列
    epoll 实际使用
    js数组的操作
    nodejs 基本类型和语法
    epoll 简单介绍及例子
    epoll 应用
    linux 查看系统状态方法
    struct stat结构体的详解和用法
    Asp.Net_获取IP地址
    Asp.Net_的传值跟存储值操作
  • 原文地址:https://www.cnblogs.com/tanlon/p/4757971.html
Copyright © 2011-2022 走看看