【android ndk】macos环境下Android(安卓)Studio中利用gradle编译jni模块及配置
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就编译通过了
更多相关文章
- NPM 和webpack 的基础使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
- 读取android手机流量信息
- android 使用html5作布局文件: webview跟javascript交互
- Android(安卓)Wifi模块分析(三)
- Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
- android“设置”里的版本号
- Android开发环境搭建
- Android(安卓)Resource介绍和使用