參考资料: 【android ndk】macos环境下Android Studio中利用gradle编译jni模块及配置: http://demo.netfoucs.com/ashqal/article/details/21869151 ANDROID STUDIO, GRADLE AND NDK INTEGRATION: http://ph0b.com/android-studio-gradle-and-ndk-integration/ Gradle Plugin User Guide: http://tools.android.com/tech-docs/new-build-system/user-guide New Build System: http://tools.android.com/tech-docs/new-build-system
实践证明: 0.4.2仅仅有在gradle1.10版本号下创建仅仅包括AndroidLibrary模块的project时才干正常编译,gradle1.9版本号不能够。 0.4.6使用gradle1.10能够。 0.5.0不管是gradle1.10还是gradle1.11版本号都能够生成so库。 0.5.5的不能编译NDK,不管是gradle1.10还是gradle1.11版本号都不能生成so库,屙血尿脓。
下载AndroidStudio: AndroidStudio的历史版本号下载列表: http://tools.android.com/download/studio/canary
下载NDK: 下载链接: http://developer.android.com/tools/sdk/ndk/index.html,注意NDK一定要r9+版本号的,否则编译时会出现例如以下 错误:
Execution failed for task ':hellojni:compileDebugNdk'.> com.android.ide.common.internal.LoggedErrorException: Failed to run command:    D:\ndk\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=F:\androidstudio\test\hellojni\build\ndk\debug\Android.mk APP_PLATFORM=android-19 NDK_OUT=F:\androidstudio\test\hellojni\build\ndk\debug\obj NDK_LIBS_OUT=F:\androidstudio\test\hellojni\build\ndk\debug\lib APP_ABI=armeabi,armeabi-v7aError Code:    2Output:    D:/ndk/build/core/setup-app.mk:63: *** Android NDK: Aborting    .  Stop.

下载gradle: gradle-1.9-all.zip: http://download.csdn.net/detail/xxhongdev/6834859 gradle-1.10-all.zip: http://download.csdn.net/detail/xinghuacheng/7026815 gradle-1.11-all.zip: http://download.csdn.net/detail/d1387968/7097249

通过“AndroidStudio历史版本号下载列表”下载的历史版本号一般是绿色的压缩包,能够直接解压缩使用,可是不包括SDK,须要额外下载SDK,因为之前下载了ADT(版本号:adt20131030),所以后面直接使用ADT文件夹下的SDK。通过 http://developer.android.com/sdk/installing/studio.html首页下载的AndroidStudio为安装版本号,包括了SDK,能够下载后直接安装,首次使用创建项目会比較慢,能够參考“ AndroidStudio创建项目时一直处于building“project name”gradle project info的解决的方法”来解决。
创建项目: 执行AndroidStudio后,创建新项目,新项目会有一个默认的Module,这里项目名称为JNIDemo,Module为app。 然后通过向导完毕项目的创建。
AndroidStudio还是很慢的,长时间处于这样的状态: 经过漫长的等待后最终完毕项目的创建,然后在这个项目下创建一个Module,NewModule->Android Library: 不勾选“Create activity”然后点击“Finish”完毕创建,此时项目结构如图: app和hellojni均为JNIDemo下的两个Module,这里把hellojni作为生成so库的NDK开发层,把app作为调用so库的APK引用开发层。
在hellojni模块的src/main下创建jni文件夹,并在jni文件夹下新建文件main.cpp,代码例如以下:
#include <stdio.h>#include <stdlib.h>#include <jni.h>#include <assert.h>#include <sys/types.h>#include <android/log.h>#define LOG_TAG "Hellojni"#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)//注冊native api的类#define JNIREG_CLASS "com/example/test9/app/MainActivity"extern "C" {    JNIEXPORT void msg(JNIEnv *env, jobject  clazz, jstring str);};//jstring to char* char* jstringTostring(JNIEnv* env, jstring jstr) {     char* rtn = NULL;     jclass clsstring = env->FindClass("java/lang/String");     jstring strencode = env->NewStringUTF("utf-8");     jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");     jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);     jsize alen = env->GetArrayLength(barr);     jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);     if (alen > 0)     {         rtn = (char*)malloc(alen + 1);         memcpy(rtn, ba, alen);         rtn[alen] = 0;     }     env->ReleaseByteArrayElements(barr, ba, 0);     return rtn; }JNIEXPORT void msg(JNIEnv *env, jobject  clazz, jstring str){    char *pszstr = NULL;     pszstr = jstringTostring(env, str);    LOGI("%s", pszstr);    free(pszstr);}/*** Table of methods associated with a single class.*/static JNINativeMethod gMethods[] = {    { "msg", "(Ljava/lang/String;)V", (void*)msg},};/** Register native methods for all classes we know about.*/static int registerNativeMethods(JNIEnv* env){    int nError = 0;    jclass clazz = NULL;    clazz = env->FindClass(JNIREG_CLASS);    if (clazz == NULL) {        LOGE("clazz is null");        return JNI_FALSE;    }    nError = env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0]) );    if ( nError < 0 ) {        LOGE("RegisterNatives error: %d num: %d",nError, sizeof(gMethods) / sizeof(gMethods[0]) );        return JNI_FALSE;    }    return JNI_TRUE;}/** Set some test stuff up.** Returns the JNI version on success, -1 on failure.*/JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved){    JNIEnv* env = NULL;    jint result = -1;    if(vm->GetEnv((void**) &env,JNI_VERSION_1_6) != JNI_OK){        return -1;    }    assert(env != NULL);    if (!registerNativeMethods(env)) {        LOGE("registerNativeMethods failed");        return -1;    }    /* success -- return valid version number */    result = JNI_VERSION_1_6;    return result;}
这里仅仅导出一个msg函数打印传递进来的字符串,仅作測试。再在jni文件夹下新建一个empty.cpp文件,内容为空,这个是为了解决NDK的bug所作的,以防编译出错。
打开local.properties,设置正确的SDK路径和NDK路径:
sdk.dir=D\:/adt20131030/sdkndk.dir=D\:/ndk
打开项目gradle/wrapper文件夹下的gradle-wrapper.properties文件,改动:
#Wed Apr 10 15:27:10 PDT 2013distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=http\://services.gradle.org/distributions/gradle-1.9-all.zip
为:
#Wed Apr 10 15:27:10 PDT 2013distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=http\://services.gradle.org/distributions/gradle-1.10-all.zip
并打开项目根文件夹下的build.gradle文件,改动:
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'com.android.tools.build:gradle:0.7.+'    }}allprojects {    repositories {        mavenCentral()    }}
为(指定使用gradle1.10则改动为0.9.+,指定使用gradle1.11则改动为0.9.2):
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'com.android.tools.build:gradle:0.9.+'    }}allprojects {    repositories {        mavenCentral()    }}
解释:參考 http://tools.android.com/tech-docs/new-build-system知道
0.7.0Requires Gradle 1.9Requires Studio 0.4.0

0.9.0Compatible with Gradle 1.10 and 1.11Using Gradle 1.11 requires Android Studio 0.5.0
假设配置的是0.7.+则默认使用gradle1.9,假设设置为0.9.+则默认使用gradle1.10。
另外还须要注意的是gradle1.9下没有buildTypes标签,须要将debug、release标签直接放在android标签内,在gradle1.10下debug、release须要放在buildTypes标签内,buildTypes在android内。这里hellojni配置的build.gradle文件内容例如以下:
assert gradle.gradleVersion >= "1.10"apply plugin: 'android-library'android {    compileSdkVersion 19    buildToolsVersion "19.0.3"    defaultConfig {        minSdkVersion 8        targetSdkVersion 16        versionCode 1        versionName "1.0"    }    buildTypes {        release {            runProguard false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'            ndk {                moduleName "hellojni"                abiFilters "armeabi", "armeabi-v7a", "x86"            }        }        debug {            ndk {                moduleName "hellojni"                //stl "stlport_shared"                ldLibs "log", "z", "m"                //cFlags "-Wall -Wextra -I " + projectDir + "/src/main/jni/include"                abiFilters "armeabi", "armeabi-v7a", "x86"            }        }    }    productFlavors {        x86 {            versionCode Integer.parseInt("6" + defaultConfig.versionCode)            ndk {                abiFilter "x86"            }        }        mips {            versionCode Integer.parseInt("4" + defaultConfig.versionCode)            ndk {                abiFilter "mips"            }        }        armv7 {            versionCode Integer.parseInt("2" + defaultConfig.versionCode)            ndk {                abiFilter "armeabi-v7a"            }        }        arm {            versionCode Integer.parseInt("1" + defaultConfig.versionCode)            ndk {                abiFilters "armeabi", "armeabi-v7a"            }        }        fat    }}dependencies {    compile 'com.android.support:appcompat-v7:19.+'    compile fileTree(dir: 'libs', include: ['*.jar'])}
然后选择hellojni项目右键“Make Module hellojni”,等待一段时间后会在项目下生成build-ndk文件夹,文件夹下会有一些不同版本号的so库文件生成,如图: 注意这里的Android.mk文件每次编译都会又一次由工具自己主动生成,而非手动编辑的,我认为这一点设计就比較差劲。比如假设想要使用log输出函数__android_log_print,须要加入“LOCAL_LDLIBS :=-llog”,则在build.gradle文件里加入例如以下的配置:
        debug {            ndk {                ldLibs "log"            }        }
由gradle依据配置再去生成Android.mk文件,最后再调用ndk进行编译。

右键project选择Open Module Settings,选择Modules-app,打开Dependencies选项卡点击“+”号,选择Module dependency,在打开的对话框中选择hellojni。 可是測试发现设置依赖没有效果,假设直接编译app,hellojni并没有编译,仍须要手动编译hellojni。

调用native函数:
app项目中,在MainActivity类中声明native函数:
public native void msg(String str);
并加入静态代码载入hellojni库:
    static {        System.loadLibrary("hellojni");    }
在MainActivity::onCreate中调用native函数打印一句log:
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        msg("MainActivity onCreate");    }

还须要将hellojni生成的so库文件打包进apk,仍须要配置build.gradle文件,加入:
task copyNativeLibs(type: Copy) {    from fileTree(dir: '../hellojni/build/ndk/arm/debug/lib', include: 'armeabi/*.so') into 'build/lib'}tasks.withType(Compile) {    compileTask -> compileTask.dependsOn copyNativeLibs}clean.dependsOn 'cleanCopyNativeLibs'tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask ->    pkgTask.jniFolders = [new File(buildDir, 'lib')]}
參考:“Android Studio加入so库” http://blog.csdn.net/caesardadi/article/details/18264399 当中copyNativeLibs任务是从相对app的项目路径'../hellojni/build/ndk/arm/debug/lib'下复制全部armeabi子文件夹的so文件到本项目build文件夹下的lib文件夹中,运行效果: 这样最后打包生成的apk包才会包括有hellojni的so库文件。

測试:
编译执行app,apk安装完成执行时输出log信息:

后面列出了可能出现的gradle错误以及解决方式,以供參考。
错误:
Execution failed for task ':hellojni:compileDebugNdk'.> com.android.ide.common.internal.LoggedErrorException: Failed to run command:    D:\ndk\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=F:\androidstudio\test\hellojni\build\ndk\debug\Android.mk APP_PLATFORM=android-19 NDK_OUT=F:\androidstudio\test\hellojni\build\ndk\debug\obj NDK_LIBS_OUT=F:\androidstudio\test\hellojni\build\ndk\debug\lib APP_ABI=armeabi,armeabi-v7aError Code:    2Output:    make.exe: *** No rule to make target `F:\androidstudio\test\hellojni\build\ndk\debug\obj/local/armeabi/objs/jnimain/F_\androidstudio\test\hellojni\src\main\jni', needed by `F:\androidstudio\test\hellojni\build\ndk\debug\obj/local/armeabi/objs/jnimain/F_\androidstudio\test\hellojni\src\main\jni\hellojni.o'.  Stop.
解决方式: 这是NDK在Windows下一个bug,当仅仅编译一个文件时出现,解决方法就是再加入一个空的文件就可以。 原文见 http://ph0b.com/android-studio-gradle-and-ndk-integration/:
This may come from a current NDK bug on Windows, when there is only one source file to compile. You only need to add one empty source to make it work again.


错误:
Could not determine the dependencies of task ':hellojni:compileArmDebugJava'.> failed to find Build Tools revision 19.0.3
解决方式: 这个Build Tools是指“Android SDK Build-tools”,打开SDK Manager勾选对应版本号(比如这里是19.0.3)安装就可以。


错误:
FAILURE: Build failed with an exception.* What went wrong:Task 'assembleArmDebug' not found in project ':hellojni'. Some candidates are: 'assembleDebug'.* Try:Run gradle tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
解决方式: 在 android { }中加入:
    productFlavors{        arm {        }    }
若有类似错误能够參考增加对应的标签:
    productFlavors {        x86 {            versionCode Integer.parseInt("6" + defaultConfig.versionCode)            ndk {                abiFilter "x86"            }        }        mips {            versionCode Integer.parseInt("4" + defaultConfig.versionCode)            ndk {                abiFilter "mips"            }        }        armv7 {            versionCode Integer.parseInt("2" + defaultConfig.versionCode)            ndk {                abiFilter "armeabi-v7a"            }        }        arm {            versionCode Integer.parseInt("1" + defaultConfig.versionCode)            ndk {                abiFilter "armeabi"                //abiFilters "armeabi", "armeabi-v7a"            }        }        fat    }


错误:
Execution failed for task ':hellojni:compileDebugNdk'.> java.io.IOException: Cannot run program "D:\ndk\ndk-build": CreateProcess error=193, %1 ??????Ч?? Win32 ??ó
解决方式: 在使用gradle1.9版本号时遇到,使用gradle1.10版本号来解决。

错误:
A problem occurred evaluating project ':app'.> Could not create plugin of type 'AppPlugin'.
解决方式: Don’t use latest Gradle (version 1.10), downgrade to 1.9。參考: http://blog.vyvazil.eu/tag/android-studio/ 可是假设我们使用gradle1.9版本号的话又会出现 错误:
Execution failed for task ':hellojni:compileDebugNdk'.> java.io.IOException: Cannot run program "D:\ndk\ndk-build": CreateProcess error=193, %1 ??????Ч?? Win32 ??ó
不管使用哪个版本号都有问题,后来细致查看了下'AppPlugin'这个错误是出如今‘app’模块上的而非‘hellojni’模块上,于是考虑新建project项目而且仅仅在该project下建立一个库模块,不再创建app模块,如图: 这里不勾选“Create custom launcher icon”和“Create activity”,直接finish完毕,其它配置參考前述,最后编译后能够生成so库文件:

错误: 这个错误忘记记录了囧
解决方式: File-Settings-Gradle-Gradle VM options:-Xmx512m

更多相关文章

  1. Android(安卓)Studio 配置快捷方式生成JNI头文件的方法
  2. Android介绍
  3. android 读取DDMS里的文件时打不开,解决方法
  4. Android(安卓)写文件权限
  5. android 使用xml定义自己的View
  6. 修改ProgressBar的进度条颜色
  7. Android上传图片至服务器
  8. android 安装文件例子
  9. android配置文件详解

随机推荐

  1. Android数据库操作的简单封装
  2. Android 开发 调用图库选择图片实现和参
  3. [Android开发实战]Android手势密码(支付宝
  4. android 自定义控件学习之三 控件布局常
  5. android 如何把apk放进系统------unyaffs
  6. Android(安卓)EditText remove focus 只
  7. ANDROID 应用退出
  8. Android中的跨进程通信方法实例及特点分
  9. 定制你自己的Andoird桌面Launcher
  10. android在EditText中插入表情图片