Android studio编写第一个NDK工程的过程详解,以及Demo下载地址
- 1:创建工程和配置NDK
- 2:编写JNI程序
- 1:创建HelloWord.java类在此类中定义native方法,注意该文件中最好不要有中文字符,我这里加了一些批注方便理解
- 2:在Terminal窗口编译HelloWord获取字节码文件`javac HelloWord.java`**注意切换到此文件目录下或者用绝对路径**,(你也可以用cmd,这两种方式你都得配置了JDK、NDK的环境变量)
- 3:切换目录到 \app\src\main文件目录下执行 `javah`生成头文件
- 4:在jni目录下新建.c或.cpp文件实现.h文件中定义的接口方法
- 3:ndk编译生成so文件
- 4:调用生成的so文件
首先附上我的几篇其它文章链接感兴趣的可以看看,如果文章有异议的地方欢迎指出,共同进步,顺便点赞谢谢!!!
Android framework 源码分析之Activity启动流程(android 8.0)
面试必备1:HashMap(JDK1.8)原理以及源码分析
面试必备2:JDK1.8LinkedHashMap实现原理及源码分析
Android事件分发机制原理及源码分析
View事件的滑动冲突以及解决方案
Handler机制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源码
Android三级缓存原理及用LruCache、DiskLruCache实现一个三级缓存的ImageLoader
1:创建工程和配置NDK
1:如果之前没有下载配置ndk则下载
2:给工程配置ndk路径
方法一:在工程的local.properties
文件中添加ndk.dir=D\:\\SoftPath\\Android\\Sdk\\ndk-bundle
如下图
方法二:在studio的Project Structure中选择SDK路径
2:编写JNI程序
第二部分主要是JNI相关操作,因为ndk是基于JNI的
1:创建HelloWord.java类在此类中定义native方法,注意该文件中最好不要有中文字符,我这里加了一些批注方便理解
public class HelloWord {
public static native String getString();//从native方法获取一个字符串
public static native int add(int a,int b);//从native方法做两个数字相加并返回结果
}
2:在Terminal窗口编译HelloWord获取字节码文件javac HelloWord.java
注意切换到此文件目录下或者用绝对路径,(你也可以用cmd,这两种方式你都得配置了JDK、NDK的环境变量)
切换目录执行javac HelloWord.java
执行完javac HelloWord.java
则在当前目录下生成字节码文件
3:切换目录到 \app\src\main文件目录下执行 javah
生成头文件
javah -d jni -classpath D:\WorkSpace\JNIDemo\app\src\main\java myh.com.jnimodel.HelloWord
分析命令:
-d jni:当前目录下创建一个 jni 文件夹
-classpath D:\WorkSpace\JNIDemo\app\src\main\java myh.com.jnimodel.HelloWord 指向字节码文件的路径
javah指令的详细解释如图
执行完后会在 main文件夹下创建jni文件夹并生成.h的头文件 ,给文件中声明了HelloWorld中的native方法
强调一点:生成的myh_com_jnimodel_HelloWord.h文件是为了不懂c或者c++的码农方便编写c或c++的代码,可以没有.h文件
4:在jni目录下新建.c或.cpp文件实现.h文件中定义的接口方法
1:选中jni目录右键–》new—》c/c++ Source File, 名字随意我这叫hello.c
我用的c语言实现的
2:实现.h中的就扣方法
在这里解释一下方法中的两个重要参数
- JNIEnv *env表示指向JNI环境的指针,通过它来访问JNI提供的接口方法
- **jclass **作用相当于Java中的this
hello.c文件的代码
//
// Created by geo on 2019/4/29.
//
#include<jni.h>
#include<stdio.h>
//导入我们创建的头文件
#include "myh_com_jnimodel_HelloWord.h"
JNIEXPORT jstring JNICALL Java_myh_com_jnimodel_HelloWord_getString
(JNIEnv *env, jclass jclass){
//返回一个字符串
return (*env)->NewStringUTF(env,"This is my first NDK Application");
}
JNIEXPORT jint JNICALL Java_myh_com_jnimodel_HelloWord_add
(JNIEnv *env,jclass jclass, jint a, jint b){
return a+b;
}
3:ndk编译生成so文件
1:在jni文件下新建 Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello// 生成的so文件名称
LOCAL_SRC_FILES := hello.c//编译的c或c++文件
include $(BUILD_SHARED_LIBRARY)
2:在jni文件下新建 Application.mk 指定CPU架构 all代表所有
APP_ABI := all
最后jni目录有一下四个文件
3:切换目录到jni目录下执行ndk-build生成对应的so文件
执行完ndk-build会在与jni同级目录下生成libs文件夹,该文件夹存放了对应cpu的so文件如下图
4:调用生成的so文件
1:准备工作:配置Studio加载so文件的路径
第一种方法: 因为Android studio默认加载so的路径是在src\main\jniLibs
,在main下新建jniLibs
文件夹,将libs里的所有内容都复制到jniLibs下(包括so文件的目录结构)
第二种方法:就是修改Android studio 加载so文件的路径,在model的build.gradle
文件中,添加如下代码sourceSets { main { jni.srcDirs = ['libs'] } }
,注意是android{}标签中添加
2:加载so库
System.loadLibrary("hello")
注意hello是上在android.mk中指定的so文件名(即LOCAL_MODULE := hello// 生成的so文件名称
),实际上我们生成的so文件前默认会加上lib即libhello.so
运行点击按钮出现如下结果:返回hello.c文件中方法的数据
到此完毕,最后附上我在编译时遇到的两个问题的解决方案和demo的下载地址
Android NDK 运行错误:java.lang.UnsatisfiedLinkError: Couldn’t load XXX indLibrary returned null
Android studio3.2出现Your project contains C++ files but it is not using a supported native build