我的Android NDK之旅(一),不使用ndk-build命令来创建jni
来源:互联网 发布:java web框架最新技术 编辑:程序博客网 时间:2024/05/13 01:19
转载请注明出处:(http://blog.csdn.net/qq_35071078/article/details/70338637)
最近闲来无事,想摸索下一下ndk,可是ndk不是块好啃的骨头,但作为一名程序员,什么都要了解下,对吧╮( ̄▽ ̄)╭。首先我想吐槽一下,网上有些博客写的很乱,一上来就贴一段代码,也不告诉是要干什么,代码一写完就完事,这让初学者很难理解jni到底是个什么东西。每次按照他们的方法敲,敲着敲着就不知道要干什么了,然后程序也运行不了。不过有些大神确实总结的很好。所以我想通过这几天的摸索,总结一下。
对于jni,ndk到底是什么,我就不多说了,百度讲的很清楚。对于如何创建jni,其实很简单:
- 在.java文件中声明native方法 。
- 编译这个.java文件得到.class文件 。
- 用javah命令作用于这个.class文件生成.h文件。
- 创建一个.c或者.cpp文件,在代码中include刚生成的.h文件,然后再实现里面的方法 ,注意方法的命名是有特定的要求的,后面会讲到。
最后就是生成.so文件了。目前博主知道的三种方法:
- 通过ndk-build(这个需要Android.mk文件和Application.mk文件)生成。
- cmake(需要CMakeLists.txt)方式生成。
- 直接通过android studio编译(这篇文章讲的)来生成。
不使用ndk-build命令,直接通过android studio编译的方式来创建jni
首先在android studio上创建一个项目,
接下来创建一个类 MyJni,这个类用来实现native方法:
接下来编译项目:
编译完成之后,就会在app/build/../com/..下生成相应的classes文件了,接下来就是用 javah 这个指令,将刚才编译好过了的MyJni.class编译成 .h 文件,首先打开终端,点击android studio下方的Terminal,这里默认路径是在当前的项目目录下。
在这里输入 cd app/build/intermediates/classes/debug,进入debug目录,然后在这里输入javah指令来生成.h文件。输入 javah com.chenxin.MyJni ,之后就会在当前目录(../debug)下生成一个com.chenxin.MyJni.h文件。为什么要在debug目录下输入这段指令呢?因为我在其他地方试了,不行啊⊙﹏⊙‖∣° 。javah后面就是要接完整的包名+类名,包名是从com.开始的,所以我们要到com.的父级目录下,进行javah操作。
.h文件里面的代码如下,其他的不用管,只需要知道JNIEXPORT jstring JNICALL Java_com_chenxin_MyJni_getString
(JNIEnv *, jclass);这个就是我们在MyJni.java里面声明的native方法。
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_chenxin_MyJni */#ifndef _Included_com_chenxin_MyJni#define _Included_com_chenxin_MyJni#ifdef __cplusplusextern "C" {#endif/* * Class: com_chenxin_MyJni * Method: getString * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_chenxin_MyJni_getString (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
在app/src/main下创建一个jni文件夹(Directory),因为studio默认的c和c++文件是在这里面,将刚才的那个.h文件剪切到这里面来,然后在jni文件夹里创建一个c/c++ source file,随便叫什么,我这里就叫test,后缀名是都.c或者.cpp都可以,只不过函数的实现上稍微有点差异。在这个.c或者.cpp文件中,首先得导入jni.h,然后导入com_chenxin_MyJni.h,就是刚才用javah生成的.h文件。如果是.cpp的话:
#include "jni.h"#include "com_chenxin_MyJni.h"JNIEXPORT jstring JNICALL Java_com_chenxin_MyJni_getString (JNIEnv *env, jclass jz){ return env->NewStringUTF("this is jni , this is my new life!"); }
如果是.c的话:
#include "jni.h"#include "com_chenxin_MyJni.h"JNIEXPORT jstring JNICALL Java_com_chenxin_MyJni_getString (JNIEnv *env, jclass jz){ return (*env)->NewStringUTF(env,"this is jni , this is my new life!");}
对了,还得在gradle.properties里面添加一行代码,不然会报错,因为这种方法谷歌现在已经不提倡了。
android.useDeprecatedNdk=true
接下来回到MyJni.java文件,添加代码来加载so文件,此时还没有生成,等下编译项目时会自动生成,自动生成的.so的默认名字是app。
public class MyJni { static { System.loadLibrary("app"); } public native static String getString();}
不过如果想自定义生成的so的名字,可以在build.gradle中加入:
ndk{ moduleName "myLib" }
我这里将生成的so的名字改成了myLib,所以将上面的 “app” 改成 “myLib” ,例如:
build.android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { ...... ndk{ moduleName "myLib" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}MyJni.java文件中: static { System.loadLibrary("myLib"); }
也可以设置指定生成什么类型的so文件,这里我就不详细讲解了。想加的话直接在modulueName下面添加:
abiFilters "armeabi", "armeabi-v7a"
然后回到MainActivity,使用Log打印以下,看下是否调用成功了:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e("info","调用jni的结果 :"+TestJni.sayHello()); }}
编译运行
结果:
而且这时在打开app/build/intermediates下就可以看到对应的so文件了
也可以使用 Analyze 来看当前项目的结构:
ok,大功告成。
- 我的Android NDK之旅(一),不使用ndk-build命令来创建jni
- 我的Android NDK之旅(二),使用ndk-build构建Jni
- 我的Android NDK之旅(三),使用cmake来构建Jni
- Android 使用NDK-build生成so文件 C++ JNI NDK
- Android JNI/NDK开发(一)NDK真的很难吗?
- Android NDk-JNi开发(一)NDK环境变量的配置
- 使用Android NDK开发(一):Android NDK介绍(包括JNI的介绍)
- android ndk jni (一)
- Android NDK学习之二. ndk-build使用
- NDK开发之ndk-build命令详解
- Android studio 初步使用JNI(一)配置NDK
- Android Stuido Ndk-Jni 开发(一):创建简单的JniDemo
- Android Jni开发之eclipse中自动化编译ndk-build
- Android NDK之JNI使用例子
- Android NDK开发之从Java与C互调中详解JNI使用(一)
- Android Studio JNI NDK编程(一)
- 使用NDK build android上的busybox.
- android NDK开发之NDK与JNI
- Java 抽象类
- python xgboost算法实践
- 分而治之:Fork/Join框架
- Oracle有哪些服务是必须开启的?
- 各位大牛帮忙看看问题出来哪?自己实现一个数组模板类,编译无法通过
- 我的Android NDK之旅(一),不使用ndk-build命令来创建jni
- 【数据结构】图的遍历--广度优先搜索
- leetcode--66. Plus One
- Hadoop知识点参考
- Cocos Creator各个场景之间传递数据的方法
- nodejs网页请求
- java中抽象类与接口
- ubuntu 16.04 Lancher Bottom
- Mirrored String I Gym