学习学习在学习,闲来无事找个东西学,一直觉得jni可以Java调用C很神奇,于是来探探玄奇,看了网上的关于AS开发环境下 jni的开发文章,对开发的流程还是有点疑问,于是自己动手琢磨了一下,并编写了简单的demo,理清楚了大致流程,本文着重讲述AS下的jni流程,不涉及代码的编写,记录下自己的积累过程,不正确的地方望指出!!!
概念性的就不讲了,来说说流程,说到底也就是那几步
配置ndk
->创建Java文件,编写本地方法
->根据本地方法,在C/C++文件中编写jni代码
->进行编译生成.so链接库文件
->在创建的Java文件中的静态代码块中加载生成.so文件
->在需要调用的地方调用本地方法
一、环境配置
1、在SDK Tools选项下 选择NDK 下载,将下载到对应sdk目录中的ndk-bundle目录
cmd命令行输入ndk-build,将会有看着像错误信息的提示,表示配置成功
3、在以下几个文件中配置相关参数
gradler.properties:
android.useDeprecatedNdk=true
local.properties:(指示ndk的路径)
ndk.dir=E\:\\Android\\sdk\\ndk-bundle
sdk.dir=E\:\\Android\\sdk
二、创建本地方法并编译生成.so文件
1、创建Jni.java 文件,在此文件中添加native修饰的方法package com.haha.jnidemo;
public class Jni {
public native String getString();
}
2、Terminal 定位到java目录(也可以是其他目录,定位到哪里,执行后面指令生成的.h文件就在那个目录)
执行 javah com.haha.jnidemo.Jni(包名+类名) 指令 生成.h文件
#include "com_haha_jnidemo_Jni.h"
#include "jni.h"
JNIEXPORT jstring JNICALL Java_com_haha_jnidemo_Jni_getString
(JNIEnv * env, jobject obj){
return (*env)->NewStringUTF(env, "hello world !");//简单地返回 hello world!字符串
}
}
app\build.gradle:(主module下的build.gradle)
android {
compileSdkVersion 25
buildToolsVersion "25.0.3"
defaultConfig {
...
ndk{
moduleName "hello" //待编译生成的目标.so文件名称
abiFilters "armeabi", "armeabi-v7a", "x86" //编译成这些架构的.so文件
}
}
sourceSets{
main{
jniLibs.srcDirs = ['libs']
jni.srcDirs = []
}
}
}
在app\src\main目录下生成jni目录,(或者 右键app->New->Folder->JNI Folder, 默认是在main目录下生成jni目录)
在jni目录下,创建以下两个文件,名字要一样:
LOCAL_PATH := $(call my-dir) //包含本文件的当前目录
include $(CLEAR_VARS)
LOCAL_MODULE := hello //生成目标.so文件名称
LOCAL_SRC_FILES := hello.c //待编译成.so文件的.c文件
include $(BUILD_SHARED_LIBRARY)
此文件指示了将哪个.c文件编译成哪个.so文件,需跟app\build.gradle中配置一致
APP_ABI := armeabi armeabi-v7a x86 //支持什么架构的.so文件 ALL为支持所有,多个架构用空格隔开
APP_PLATFORM := android-14 //min sdk version
package com.haha.jnidemo;
public class Jni {
static {
System.loadLibrary("hello");//加载 .so文件
}
public native String getString();
}
7、调用Jni中的方法,编译运行app
package com.haha.jnidemo;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Jni jni = new Jni();
String string = jni.getString();
Toast.makeText(MainActivity.this, "String: " + string,
Toast.LENGTH_LONG).show();
}
}
运行起来后,将弹出一个吐司显示hello world!
ps: 如果需要修改native方法的话,在每次修改native方法后,都需要执行ndk-build命令,重新编译生成.so文件,并将其复制到根目录下libs目录中