android ndk之hello world
前言:Android NDK r7及以上的版本已经集成了Cygwin编译环境,也就是说,我们完全可以抛弃庞大的Cygwin了。
r6及以下版本,也可以抛弃几个G的完整版,使用精简过的Mini-Cygwin来编译,解压后大小仅9M,但短小巧精悍,完全可以满足Android NDK的开发。
下载地址:https://code.google.com/p/mini-cygwin/
Eclipse集成Cygwin编译环境可以参考我的这篇贴:http://blog.csdn.net/codezjx/article/details/8858825
下面进入正题,r7及以上版本,跟着我的这篇帖子,完成环境的升级吧!!!
参考官网:http://tools.android.com/recent/usingthendkplugin
1、首先确认自己的ADT版本,NDK plugin的支持是在ADT 20及以后的版本。
2、安装Android Native Development Tools(该组件集成C/C++开发环境),既在安装ADT工具的时候勾选NDK组件,一路next后重启Eclipse使插件生效。
3、下载NDK工具http://developer.android.com/tools/sdk/ndk/index.html,我使用的是最新的android-ndk-r8e-windows-x86.zip,下载完后解压缩。
4、Eclipse -> Window -> Preferences -> Android -> NDK,设置NDK为刚刚解压缩的工具包路径。
侯注:做到这里时,控制台报出了一个错误:“Unable to launch cygpath. Is Cygwin on the path”,因为我的ndk是之前安装的,并没有专门设置环境变量。按照这个链接中的引导解决:
Head to the project's properties. If you're using Windows, the shortcut is
Alt + Enter; or simply right-click the project name to find its properties.Go to the
C/C++ Buildsection; underBuilder Settingstab inBuild command:text box you're likely to find something similar to that below, if it's empty then type in the similar text - namely:${NDKROOT}/ndk-build.cmdwhereNDKROOT, as its name implies, refers to the path where your NDK root folder exists.
Now you must inform eclipse what
NDKROOTequates to; as in, where is the NDK root path. You can do this by heading to (in your project's properties)C/C++ Build>Environment> pressAdd…Now add your environment variable named NDKROOT (the
Name) with the relevant path (Value). Note that you're to repeat this per NDK project. You would get a window similar to that below.
Press
OKto the New variable input window and thenOKagain to the properties window.
5、NDK环境基本上已经搭建好,新建一个普通Android项目测试NDK支持。项目右键->Android Tools->Add Native Support...,输入.so库名字后点击Finish
(注意:若项目已经是一个Jni项目,例如NDK example里面的HelloJni,这一步中.so库名字不用填)
6、现在已经可以Build我们的Jni项目了,选择项目,Project->Build Project,编译我们的c/c++代码,此时项目结构如下,NDK plugin已经为我们添加好了include,已经为我们生成了相应的Android.mk以及 cpp文件。(注意:这里插件为我们生成的是cpp文件,若你不喜欢可以改回.c,并在mk文件中进行相应更改)
7、这时,Android NDK环境已经完美搭建好,我们可以在cpp文件中流畅地书写我们的c/c++代码。
(而且当你Alt+/时,已经可以使用自动提示,各种爽歪歪有木有。若你不是用NDK plugin来构建JNI项目,而是选择手动方式,Alt+/是不会提示的)
8、关于编译,默认情况下:选择项目,Project->Build Project,来重新编译我们的代码。而且每次run项目的时候,也会自动编译.so库。
一些问题与解决方法:
问题一:Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml (这个是NDK工具的一个BUG,若build Target大于minSdkVersion,则会报这个错误,导致无法运行)
解决方法:
android-ndk-r8e/build/core/add-application.mk第128行把__ndk_warning改为__ndk_info;然后重新build一次项目即可消除错误。
原文:
this problem may be safely fixed by changing this line in add-application.mk from __ndk_warning to __ndk_info
链接:
https://code.google.com/p/android/issues/detail?id=39752
问题二:使用c++来编写本地库,会有一些兼容问题。
(1)直接黏贴HelloJni的stringFromJNI函数过来测试,提示Method 'NewStringUTF' could not be resolved
解决方法:
改为:将(*env)->NewStringUTF(env, "Hello from JNI !")改为return env->NewStringUTF("Hello from JNI !")即可
原因是:
NDK plugin默认为我们生成的是cpp文件,而C与C++调用函数的参数不一致,因此找不到函数,具体参考jni.h中的定义。cpp文件中形如(*env)->Method(env, XXX)改成env->Method(XXX)即可。
(2)运行c++生成的.so库,若报以下错误:(既找不到函数)
No implementation found for native Lcom/dgut/android/MainActivity;.stringFromJNI ()Ljava/lang/String;
java.lang.UnsatisfiedLinkError: stringFromJNI
at com.dgut.android.MainActivity.stringFromJNI(Native Method)
解决方法:
为供Java调用的c++函数前加入extern "C" 修饰,如:(NDK example里面的cpp文件也是这么声明的,参考hello-gl2)
- extern "C" {
- JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz );
- }
- JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz )
- {
- return env->NewStringUTF("Hello from JNI bear c++");
- }
原因是:
被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。
首先看看C++中对类似C的函数是怎样编译的:作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数voidfoo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
同样地,C++中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。
因此,若我们没有使用extern "C"修饰函数,按照C语言方式编译和连接,Jni调用将可能找不到该函数。
首先上面的部分是2014年的时候写的,也比较老了,还在用cywin等。
Android studio的ndk的正确姿势
defaultConfig {
applicationId "com.xzh.ndkdemo"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "NDKDEMO" //生成的so名字
ldLibs "log", "z", "m" //链接时使用到的库
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。目前可有可无
}
}
同时需要修改下gradle.properties的配置,加入如下代码
android.useDeprecatedNdk=true
2,新建MainActivity,新增本地Native方法(为了简单,我们只做一个hello word的调用,复杂情况就不在这里讲解)
public native String getStringFromNative();
android ndk之hello world的更多相关文章
- Android NDK debug 方法
最近又频繁遇到 NDK 的错误,记录一下debug调试的一些经验,以备后续查看 一般来说,在Android Studio中的Monitor中将过滤器的 LOG TAG 设置为 "DEBUG& ...
- Android NDK开发Hello Word!
在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...
- Android NDK开发初识
神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...
- android NDK debug 遇到的问题与解决方法
最近在研究android NDK 的eclipse调试,遇到点问题,总结一下: 1.Unknown Application ABI :在application.mk里面添加APP_PLATFORM ...
- 初识Android NDK
本文介绍Windows环境下搭建Android NDK开发环境,并创建一个简单的使用Native代码的Android Application. 一.环境搭建 二.JNI函数绑定 三.例子 一.环境搭建 ...
- Android SDK Android NDK Android Studio 官方下载地址
2016.12 Android Studio Windows Includes Android SDK https://dl.google.com/dl/android/studio/install/ ...
- Android NDK之JNI陷阱
背景: 最近一个月一直在做移植库的工作,将c代码到share library移植到Android平台.这就涉及到Android NDK(native develop kit)内容.这里只想记录下JNI ...
- Android NDK开发
Android NDK 开发教程(极客学院) 一.Android NDK环境搭建 使用最新ndk,直接抛弃cygwin,以前做Android的项目要用到NDK就必须要下载NDK,下载安装Cygwin( ...
- Eclipse+CDT+GDB调试android NDK程序(转)
Eclipse+CDT+gdb调试android ndk程序 先介绍一下开发环境,在这个环境下,up主保证是没有问题的. ubuntu 11.10 eclipse 3.7(indego) for ja ...
- android NDK入门 windows下安装cygwin
一.Android NDK环境简介 Android NDK 是运行于Android 平台上的Native Development Kit 的缩写. Android 应用开发者可以通过NDK 调用C 或 ...
随机推荐
- 计蒜客NOIP2017提高组模拟赛(五)day1-展览
传送门 发现这题选或不选对状态的优劣程度不会产生影响,如果已经确定了两个数a和b,那么最优的首项和公比也都是唯一确定的, 与对于后面的数x,加进去也好不加进去也好,首项和公比依旧是原来的 于是我们用尺 ...
- linux内核中的链表
1.内核中的链表 linux内核链表与众不同,他不是把将数据结构塞入链表,而是将链表节点塞入数据,在2.1内核中引入了官方链表,从此内核中所有的链表使用都采用此链表,千万不要在重复造车轮子了!链表实现 ...
- 关于快速沃尔什变换(FWT)的一点学习和思考
最近在学FWT,抽点时间出来把这个算法总结一下. 快速沃尔什变换(Fast Walsh-Hadamard Transform),简称FWT.是快速完成集合卷积运算的一种算法. 主要功能是求:,其中为集 ...
- VK-Cup 2017 qualification 1
VK-Cup,cf里面只有切成俄文才能看到,题目也都是俄文的(百度翻译成英文和中文). 两人组队参赛的,赛期1天,乐多赛赛制(和时间基本无关,交上去挂了扣分).这次是第一场资格赛. 这次又和ditol ...
- hdu3966 点权模板-树链部分
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- What's New In MySQL 8.0
由于8.0内有很多C++11特性.需要gcc4.8版本以上.Rhel6系列默认gcc是4.7.在安装gcc6.1之后仍然检查不过. 原因可能是6.1版本不一定高于4.7,暂不讨论.鉴于升级gc ...
- Python中byte与str
原文传送门:请点击 现在计算机中,在内存中采用unicode编码方式. 可以看到上图中,字节型数据t并没有像想象中的一样显示0,1字符串.显示仍然是b,这是因为t是采用utf-8来编码,而utf-8与 ...
- bootstrap插件fileinput.js 显示无法上传失败
哪怕图片已经传到服务器上了 依然显示出错 // 处理完成后,必须返回一个json数据,否则会报错误 JSONObject jsonObject = new JSONObject(); jsonObje ...
- Gradle--初识
1.Eclipse从svn导入Gradle项目 1.检出项目的时候不要选新项目,选"做为工作空间中的项目检出",然后点Finish. 2.将项目转为Gradle项目,右键导入的项目 ...
- Linux 管理软件
公司的openfire先前运行在windows上的,但由于在windows上openfire内存机制问题,最多只能占用2GB内存,且时间稍微长久一些就会自动挂掉,用户无法登陆和连接,因此迁移到了Cen ...