分类: Android平台

软硬件环境

  • ubuntu kylin 14.04
  • 红米note增强版
  • Android studio 0.8.6
  • ndk r10c

前言

本文的目标是在Android studio中进行NDK的开发。示例是在main activity中显示一个字符串,而字符串的内容是来自于一个C函数。归结于一句话:NDK是为了让上层的java应用能够调用底层的c/c++而设计的。马上进入主题。

创建工程

创建一个名为jniDemo的blank activity工程,activity名为MyActivity,在MyActivity类的最后声明一个方法,这个方法会在C函数中去实现,如下图所示,

jni部分

设置ndk路径,打开local.properties,增加

ndk.dir=/home/djstava/Workshop/Android/android-studio/ndk 

点击android studio左下角的Terminal

cd src/main

javah -d jni -classpath ~/Workshop/Android/android-studio/sdk/platforms/android-4.4.2/android.jar:../../build/intermediates/classes/debug/ com.example.djstava.jnidemo.MyActivity 

参数意义:

-d 输出目录,jni是gradle默认的路径
-classpath jar的路径,经常碰到的找不到activity的类的错误一般是由这个引起的
com.example.djstava.jnidemo.MyActivity 包名+activity

这条命令执行完毕后,会在src/main下生成jni目录,并产生头文件com_example_djstava_jnidemo_MyActivity.h,其内容为

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_djstava_jnidemo_MyActivity */ #ifndef _Included_com_example_djstava_jnidemo_MyActivity
#define _Included_com_example_djstava_jnidemo_MyActivity
#ifdef __cplusplus
extern "C" {
#endif
#undef com_example_djstava_jnidemo_MyActivity_MODE_PRIVATE
#define com_example_djstava_jnidemo_MyActivity_MODE_PRIVATE 0L
#undef com_example_djstava_jnidemo_MyActivity_MODE_WORLD_READABLE
#define com_example_djstava_jnidemo_MyActivity_MODE_WORLD_READABLE 1L
#undef com_example_djstava_jnidemo_MyActivity_MODE_WORLD_WRITEABLE
#define com_example_djstava_jnidemo_MyActivity_MODE_WORLD_WRITEABLE 2L
#undef com_example_djstava_jnidemo_MyActivity_MODE_APPEND
#define com_example_djstava_jnidemo_MyActivity_MODE_APPEND 32768L
#undef com_example_djstava_jnidemo_MyActivity_MODE_MULTI_PROCESS
#define com_example_djstava_jnidemo_MyActivity_MODE_MULTI_PROCESS 4L
#undef com_example_djstava_jnidemo_MyActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define com_example_djstava_jnidemo_MyActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef com_example_djstava_jnidemo_MyActivity_BIND_AUTO_CREATE
#define com_example_djstava_jnidemo_MyActivity_BIND_AUTO_CREATE 1L
#undef com_example_djstava_jnidemo_MyActivity_BIND_DEBUG_UNBIND
#define com_example_djstava_jnidemo_MyActivity_BIND_DEBUG_UNBIND 2L
#undef com_example_djstava_jnidemo_MyActivity_BIND_NOT_FOREGROUND
#define com_example_djstava_jnidemo_MyActivity_BIND_NOT_FOREGROUND 4L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ABOVE_CLIENT
#define com_example_djstava_jnidemo_MyActivity_BIND_ABOVE_CLIENT 8L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ALLOW_OOM_MANAGEMENT
#define com_example_djstava_jnidemo_MyActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef com_example_djstava_jnidemo_MyActivity_BIND_WAIVE_PRIORITY
#define com_example_djstava_jnidemo_MyActivity_BIND_WAIVE_PRIORITY 32L
#undef com_example_djstava_jnidemo_MyActivity_BIND_IMPORTANT
#define com_example_djstava_jnidemo_MyActivity_BIND_IMPORTANT 64L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ADJUST_WITH_ACTIVITY
#define com_example_djstava_jnidemo_MyActivity_BIND_ADJUST_WITH_ACTIVITY 128L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_INCLUDE_CODE
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_INCLUDE_CODE 1L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_IGNORE_SECURITY
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_IGNORE_SECURITY 2L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_RESTRICTED
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_RESTRICTED 4L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_CANCELED
#define com_example_djstava_jnidemo_MyActivity_RESULT_CANCELED 0L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_OK
#define com_example_djstava_jnidemo_MyActivity_RESULT_OK -1L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_FIRST_USER
#define com_example_djstava_jnidemo_MyActivity_RESULT_FIRST_USER 1L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DISABLE
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DISABLE 0L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DIALER
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DIALER 1L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SHORTCUT
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SHORTCUT 2L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_LOCAL
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_GLOBAL
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
/*
* Class: com_example_djstava_jnidemo_MyActivity
* Method: getStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_djstava_jnidemo_MyActivity_getStringFromJNI
(JNIEnv *, jobject); #ifdef __cplusplus
}
#endif
#endif

根据产生的头文件,在同级目录创建C源文件,内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_djstava_jnidemo_MyActivity */ /*
* Class: com_example_djstava_jnidemo_MyActivity
* Method: getStringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_djstava_jnidemo_MyActivity_getStringFromJNI
(JNIEnv *env, jobject obj)
{
return (*env)->NewStringUTF(env,"Hello android from jni!");
}

gradle配置

打开build.gradle,在defaultConfig设置项内添加

ndk {
moduleName "jniLib" //这是模块名称,在加载时会被用到
}

在defaultConfig设置项后面添加

flavorGroups "abi"

productFlavors {
x86 {
ndk {
abiFilter "x86"
}
}
arm {
ndk {
abiFilter "armeabi-v7a"
}
}
mips {
ndk {
abiFilter "mips"
}
}
}

在MyActivity中加载jni模块,如下图所示,要去掉前缀lib和后缀.so

修改activity_my.xml

添加textView的id

android:id="@+id/jni_text" 

测试

不出意外的话,你的app的textView上会出现"Hello android from jni!"。生成的库位于app/build/intermediates/ndk/arm/debug/lib/armeabi-v7a/libjniLib.so,Makefile文件位于/home/djstava/AndroidstudioProjects/jniDemo/app/build/intermediates/ndk/arm/debug/Android.mk,apk文件位于/home/djstava/AndroidstudioProjects/jniDemo/app/build/outputs/apk,当然这些文件的生成都是在studio里做的,对用户是透明的。

参考资料

1、https://developer.android.com/tools/sdk/ndk/index.html
2、https://www.youtube.com/watch?v=okLKfxfbz40
3、http://www.shaneenishry.com/blog/2014/08/17/ndk-with-android-studio/
4、https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio
5、https://www.youtube.com/watch?v=e54f6dt9OZo&feature=youtube_gdata

在Android studio中进行NDK开发的更多相关文章

  1. 如何在Android Studio中指定NDK位置?

    如何在Android Studio中指定NDK位置? 问题描述 NDK已经手工下载解包在本地: D:\Portable\android-ndk-r13b 每次创建支持C++项目时,都提示NDK没配置, ...

  2. Android Studio 中关于NDK编译及jni header生成的问题

    之前由于工作原因使用grails这个基于groovy的框架做项目,对groovy感觉很好. 基于groovy的gradle构建系统对我而言自然也是好的没得说. Android Studio 正式版出来 ...

  3. android studio下的NDK开发详解(一)

    源地址:http://www.voidcn.com/blog/chengkaizone/article/p-5761016.html 好记性不如烂笔头,开始坚持写博客,学一点记一点,只为了生活更好. ...

  4. Android Studio 2.2 NDK开发环境搭建

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/52763192 本文出自: [HansChen的博客] Android应用程序使用ND ...

  5. 如何在android studio中cordova的混合开发

    基于Android Studio 中Cordova的开发 cordova简介 Cordova的前身是PhoneGap 官网: (http://cordova.io) Cordova应是运行在客户端本地 ...

  6. 关于Android Studio中使用jni进行opencv配置开发环境的要素秘诀

    使用jni进行opencv开发可以快速地将PC端的opencv代码移植到手机上,但是如何在android studio下进行配置,网上几乎找不到教程,大多都是eclipse下使用mk文件的方法,找不到 ...

  7. .Net程序员之不学Java做安卓开发:Android Studio中的即时调试窗口

    对学.Net的人来说,JAVA开发是一场噩梦. .net中的即时窗口,调试时直接在里面写代码,对程序中的各种方法/属性进行调用,很方便. Android Studio中找了好久,参考如下网址,也有类似 ...

  8. 在android studio中集成javah, ndk-build进行JNI开发

    最近在搞一个android上控制LED灯闪烁的功能,用到了串口编程,搜索了一下,发现Google发布了一个demo,android-serialport-api.有现成的代码和APK,要想自己改JNI ...

  9. cordova开发插件,并在android studio中开发、调试

    之前用过cordova Lib包装H5页面,自己写插件,但做法是野路子,不符合cordova插件的开发思路,这次项目又需要包装H5页面,同时需要自定义插件.所以又折腾了一次cordova自定义插件. ...

随机推荐

  1. List container

    //List容器 //List本质是一个双向链表 //构造函数 list<int>c0; //空链表 list<int>c1(3); //建一个含三个默认值是0的元素链表 li ...

  2. centos 6 安装docker

    安装 Fedora EPEL 1.yum -y install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarc ...

  3. chapter6 深入了解函数

    Lua函数是具有特定词法域的第一类值,与其他传统类型的值(string and number)具有相同的权利. 它可以保存在变量和table中,也可以把它当参数传递,也可以作为返回值. 在Lua中有个 ...

  4. 第三次冲刺spring会议(第五次会议)

    [例会时间]2014/5/24 21:15 [例会地点]9#446 [例会形式]轮流发言 [例会主持]马翔 [例会记录]兰梦 小组成员:兰梦 ,马翔,李金吉,赵天,胡佳奇

  5. Python 之 geturl 学习

    geturl为response对象的方法,由于有时候得到的网站url并不是真正的初始url而是通过重定向获得的,所以可以通过geturl方法获取真实的url.测试代码如下: from urllib2 ...

  6. 如何利用 MembershipUser 更改密码

    如何利用 MembershipUser 更改密码 作者: vkvi 来源:千一网络 (原创) 时间: 2009-3-11   完美集成.增强 KindEditor HTML 编辑器 在 ASP.NET ...

  7. NYOJ-71 独木舟上的旅行 (贪心)

    独木舟上的旅行 时间限制:3000 ms  |  内存限制:65535 KB 难度:2   描述 进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别.一条独木舟最多只能乘坐两个人,且乘客 ...

  8. mongoDB2--mongoDB的下载和安装。

    mongdb安装(1)安装准备我们在Linux环境下来安装mongodb,如果没有Linux操作系统的童鞋,可以使用Vmware虚拟机安装一个Linux虚拟环境来学习.这里就不再赘述.我们到mongo ...

  9. socket编程,简单多线程服务端测试程序

    socket编程,简单多线程服务端测试程序 前些天重温了MSDN关于socket编程的WSAStartup.WSACleanup.socket.closesocket.bind.listen.acce ...

  10. TODO:小程序的使用体验

    TODO:小程序的使用体验 2017.01.09小程序如期而至,话说十年前的今天2007.01.09是第一代iPhone发布日期. 清晨朋友圈发了一张小程序的截图,很多朋友问用什么版本的微信才有小程序 ...