0 写在开头

Android Studio 0.4.2 使用gradle对jni中的代码进行自动编译,很方便,推荐大家使用,下面是我总结的入门教程,包括了模块的配置


1 环境

IDE: Android Studio 0.4.2

SDK:api-19

NDK:android-ndk-r9d(必须是9以上的,我下载的是最新的)

系统:macos


2 新建android项目


那么这一步中ModuleName我没有修改,是默认的app,里面放的是Activity

创建后的项目结构如下图所示


JNIDemo是整个大项目,下面有app模块。

JNIDemo项目有一个根的build.gradle,

app模块内也有一个build.gradle,就是这个模块的编译配置


3 新建个hellojni模块

因为android studio是以模块为概念的,每个模块类似个library

我们新建一个hellojni模块

如下图所示,右击JNIDemo,选择new - Module - Android Library



修改module name为hellojni,勾掉create activity



现在项目有2个模块了



4 创建.h文件

首先在app模块内的MainActivity.java内添加native方法

public class MainActivity extends ActionBarActivity {    public native String hellojni();}

然后在hellojni模块根目录下新建一个autojavah.sh


内容如下,

其中TargetClassName为MainActivity的完整名

SourceFile为app模块java源代码根目录

TargetPath为hellojni模块jni根目录

#!/bin/sh  export ProjectPath=$(cd "../$(dirname "$1")"; pwd)export TargetClassName="com.ashqal.jni.MainActivity"export SourceFile="${ProjectPath}/app/src/main/java"export TargetPath="${ProjectPath}/hellojni/src/main/jni"cd "${SourceFile}"javah -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"echo -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"

右击autojavah.sh,点run,即可运行生成.h文件



当然需要注意得是,你得提前装个Bash Plugin,创建.sh文件时会自动提醒


运行完后,.h文件就自动生成了



5 新建cpp文件

在hellojni模块jni文件夹内新建hellojni.cpp

#include "com_ashqal_jni_MainActivity.h"JNIEXPORT jstring JNICALL Java_com_ashqal_jni_MainActivity_hellojni  (JNIEnv* env, jobject obj){    return env->NewStringUTF( "Hello from JNI !  Compiled with ABI .");}

示例修改自ndk samples hellojni


6 配置ndk环境

在项目JNIDemo内找到local.properties

接着添加

ndk.dir=/programes/android-ndk-r9d



7 编译hellojni模块

编译hellojni模块很简单,就是按command+b,当然右击hellojni模块,选择make module也行

编译后就在hellojni/build/ndk中生成了如下图所示文件,obj/local/内是4个不同的target,已经生成了.so文件了

模块名叫hellojni,是自动生成的Android.mk文件,下面会提到如何修改默认的module name,如何配置编译依赖库



8配置app模块,使之依赖hellojni

选择app模块,右击选择open-module-setting,打开项目结构

一次点击下图所示未知,给app模块添加hellojni模块依赖


添加好后



9 loadlibrary

修改app模块内MainActivity

public class MainActivity extends ActionBarActivity {    public native String hellojni();    static    {        System.loadLibrary("hellojni");    }}

值得注意得时hellojni为之前Android.mk的LOCAL_MODULE名,但是这个Android.mk是自动生成的,跟eclipse中自己写的放在jni下不一样

之前生成的.so文件名为libhellojni.so,那么loadLibrary为hellojni,去掉前面的lib及后面的.so



10 运行测试

在MainActivity的onCreate函数内调用下,写个测试

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        if (savedInstanceState == null) {            getSupportFragmentManager().beginTransaction()                    .add(R.id.container, new PlaceholderFragment())                    .commit();        }        Log.i("MainActivity",hellojni());    }

点击运行,把程序跑起来了



11 配置自动生成的Android.mk

打开hellojni内的build.gradle,在android标签内加入ndk标签

build.gradle

apply plugin: 'android-library'android {    compileSdkVersion 19    buildToolsVersion "19.0.1"    defaultConfig {        minSdkVersion 7        targetSdkVersion 16        versionCode 1        versionName "1.0"    }    release {        runProguard false        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'        ndk {            moduleName "jnimain"            abiFilters "armeabi", "armeabi-v7a"        }    }    debug {        ndk {            moduleName "jnimain"            abiFilters "armeabi", "armeabi-v7a"        }    }}dependencies {    compile 'com.android.support:appcompat-v7:+'}

可以很清楚的看到,

moudleName即为新的模块名,

abiFilters为需要生成的target

还有一些属性是

stl "stlport_shared"ldLibs "log", "z", "m"cFlags "-I/some/include/path"

这些内容来自

http://stackoverflow.com/questions/20674650/how-to-configure-ndk-with-android-gradle-plugin-0-7

里面大神提到的源代码地址我也搜到了,在

https://android.googlesource.com/platform/tools/build/+/c4f572d8dd9664c63a04f48a99b79acfb9513de9/gradle/src/main/groovy/com/android/build/gradle/internal/dsl/NdkConfigDsl.java


我现在修改了moduleName及abiFilters,按command+b,看看新的编译后的结果



可以看到,只生成了2个target,

也让自动生成的Android.mk改变了里面的内容(LOCAL_MODULE为jnimain)


12 结束语

新版的Android Studio还蛮好用的,上面就是我在学习NDK中的步骤总结,希望大家喜欢!





13 Q & A

抽空又看了下回复,给大家集中解决几个问题


1、为什么选择make module之后没有生成ndk文件夹(@_程序人生_)


新版本的android studio似乎在项目中过滤了这些文件的显示,和debug的apk看不到是一个道理

其实已经生成了,如下图所示





2、Error:Execution failed for task ':jnimain:compileReleaseNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
/programes/android-ndk-r9d/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/files/maccode/idea/AndroidJNIDemo/jnimain/build/intermediates/ndk/release/Android.mk APP_PLATFORM=android-20 NDK_OUT=/files/maccode/idea/AndroidJNIDemo/jnimain/build/intermediates/ndk/release/obj NDK_LIBS_OUT=/files/maccode/idea/AndroidJNIDemo/jnimain/build/intermediates/ndk/release/lib APP_ABI=armeabi
Error Code:
2
Output:
In file included from /files/maccode/idea/AndroidJNIDemo/jnimain/src/main/jni/jnimain.cpp:1:0:
/files/maccode/idea/AndroidJNIDemo/jnimain/src/main/jni/com_ashqal_app_MainActivity.h:2:17: fatal error: jni.h: No such file or directory
compilation terminated.
make: *** [/files/maccode/idea/AndroidJNIDemo/jnimain/build/intermediates/ndk/release/obj/local/armeabi/objs/jnimain//files/maccode/idea/AndroidJNIDemo/jnimain/src/main/jni/jnimain.o] Error 1


什么?jni.h找不到?

先看下我写的配置

apply plugin: 'com.android.library'android {    compileSdkVersion 20    buildToolsVersion "20.0.0"    defaultConfig {        minSdkVersion 7        targetSdkVersion 20        versionCode 1        versionName "1.0"    }    buildTypes    {        release {            runProguard false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'            ndk {                moduleName "jnimain"                abiFilters "armeabi" //, "armeabi-v7a"            //  stl "stlport_shared"            //  ldLibs "log", "z", "m"            //  cFlags "-I/some/include/path"            }        }        debug {            ndk {                moduleName "jnimain"                abiFilters "armeabi" //, "armeabi-v7a"            }        }    }}dependencies {    compile 'com.android.support:appcompat-v7:20.0.0'}

因为原先的demo时间比较久了,我首先把targetSdkVersion改成了最新的20

后来发现我后来没更新ndk,ndk目录下根本没有android-20的platforms


所以compileSdkVersion和targetSdkVersion改成19就编译通过了




更多相关文章

  1. NPM 和webpack 的基础使用
  2. 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
  3. 读取android手机流量信息
  4. android 使用html5作布局文件: webview跟javascript交互
  5. Android(安卓)Wifi模块分析(三)
  6. Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
  7. android“设置”里的版本号
  8. Android开发环境搭建
  9. Android(安卓)Resource介绍和使用

随机推荐

  1. APK安装过程及原理详解
  2. android Fragments详解一:概述
  3. Android(安卓)蓝牙4.0详细
  4. android 将RecyclerView当成ViewPager用
  5. Android(安卓)Adapter适配器
  6. android实现emoji输入
  7. Android未来发展 安全是重点
  8. android圆角ImageView的几种实现方式
  9. Android专家/经理——北京招聘
  10. Android root原理