android studio javap,Android Studio下JNI开发的基本步骤

第一步 设置ndk路径 配置相应的开发环境

708ee3e1e657ae00b38aac83269e88de.png

第二步 配置快捷键 Settings -> External tools中配置javah,javap,ndk-build快捷方式,(这一步主要是为了简化命令行输入,使用原生命令行也是可以的)

33ec31681c258637eb92c3155ec68ede.png

d966db6f5574a5699137803dc87ee0dd.png

javah参数配置(直接拷贝):

Program: $JDKPath$\bin\javah.exe

Parameters: -classpath . -jni -o $ModuleFileDir$/src/main/jni/$Prompt$ $FileClass$

Working directory: $ModuleFileDir$\src\main\Java

Parameters的另外一种写法: -classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$

16f68fae00a8fcd670896d7a24a87b8d.png

javap参数配置(直接拷贝):*

Program: $JDKPath$\bin\javap

Parameters: -s -p $FileClass$

Working directory: $ModuleFileDir$\build\intermediates\classes\debug

16f68fae00a8fcd670896d7a24a87b8d.png

ndk-build参数配置(直接拷贝):

Program: D:\Android_NDK\android-ndk-r11b\ndk-build.cmd

Working directory: $ModuleFileDir$\src\main

第三步 创建java类 引用即将创建的链接库,以及创建所需要的本地方法

1

2

3

4

5static {

System.loadLibrary("MyJni");//导入指定的so库文件名称

}

public native String getStringFromNative();//本地方法

public native String getString_From_c();

第四步 使用之前配置的javah快捷键快速生成.h头文件

0e414f9f634f1092296913ba2a09fae5.png

此时 会自动创建jni目录并生成头文件

9f722270627b2a5d337f8d686406aabd.png

第五步 参考头文件 在jni目录下开始编写C/C++代码

a5c59865301162f02a13a20323ceb7b1.png

注:

项目结构切换成 Android状态时,jni文件夹显示成 cpp名字!

当切换成project时就显示成jni文件夹!!

如下图:

b66ee4fe4bf2017cbfe7cf68c5b7efb8.png

bbfbccf8b4a8034eb97c53c6fcc0a7cc.png

添加如下代码:

8ea8d35edf89b9f0ca6f1bea9eac2973.png

第六步 配置gradle

1

2

3

4

5ndk{

moduleName "MyJni"//编译后so库的名字

ldLibs "log"//连接的库,可以有多个

abiFilters "armeabi","armeabi-v7a","x86"//指定so库运行的cpu架构,有armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64这些,常用的是armeabi和armeabi-v7a

}

点击Androidstudio 菜单栏 Build ->ReBuildProject 后自动生成Android.mk文件

e9e48d7982dacdf09fb19295d0b48181.png

把Android.mk文件拷贝到 main/jni文件夹下 然后右键—>External Tools –>ndk-build 生成 .so文件!!

bf1e8e6b7c30bcb84f43f4e98584af68.png

a75e6070a89b304c7c34d66a54001240.png

其次 在项目的gradle.properties 文件中添加

1android.useDeprecatedNdk=true

第七步 运行java代码 调取c库

6d73cb2a55e56886df1f772bef5f0006.png

注意事项加载生成的动态库指定的文件名( System.loadLibrary(“MyJni”);)和生成.so时指定的名字(build.gradle中的ndk{moduleName “MyJni” }),还有Android.mk中LOCAL_MODULE := MyJni三者名称需要保持一致;

异常提示不支持c++

1

2

3

4

5

6

7

8

9

10Error: Flag android.useDeprecatedNdk is no longer supported and will be removed in the next version of Android Studio. Please switch to a supported build system.

Consider using CMake or ndk-build integration. For more information, go to:

https://d.android.com/r/studio-ui/add-native-code.html#ndkCompile

To get started, you can use the sample ndk-build script the Android

plugin generated for you at:

E:\IT\youban\module_c++\build\intermediates\ndk\release\Android.mk

Alternatively, you can use the experimental plugin:

https://developer.android.com/r/tools/experimental-plugin.html

To continue using the deprecated NDK compile for another 60 days, set

android.deprecatedNdkCompileLease=1570504380180 in gradle.properties

解决方案:在build.gradle中添加如下配置即可:

1

2

3

4

5

6

7

8

9

10android{

//增加之后如下信息之后,右键项目的时候Link C++ Project with Gradle选项不再显示;

// externalNativeBuild {

// ndkBuild {

// path file('src/main/jni/Android.mk')

// }

// }

}

附:C调java代码

Java中代码如下:1

2

3

4

5

6

7

8static {

System.loadLibrary("MyJni");//导入指定的so库文件

}

public void show(){

System.out.println("hahaha C++调了我");

}

C中代码如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19//在c代码里面调用java代码里面的方法

//1 . 找到java代码的 class文件

jclass dpclazz = (*env)->FindClass(env, "com/insworks/module_ccc/CCCTestActivity");

if (dpclazz == 0) {

return (*(*env)).NewStringUTF(env, "NDK 没有找到指定的类");

}

//2 寻找class里面的方法

jmethodID method1 = (*env)->GetMethodID(env, dpclazz, "show", "()V");

if (method1 == 0) {

return (*(*env)).NewStringUTF(env, "NDK 没有找到方法");

}

//3.实例化类

jobject jobject1 = (*env)->AllocObject(env, dpclazz);

//4 .调用这个方法

(*env)->CallVoidMethod(env, jobject1, method1);

7afa9b9e748d7d775519ee69ea133821.png

b5ad2c3270ba18ed0b2f457c8b322f74.png

87887f11f2ae33ce376c31e907a48609.png

71468b840313f498292bf4d197d94791.png

注意事项:原生方法在C和C++的调用方式不同,例如:

1

2

3

4/* C */

return (*env)->NewStringUTF(env, "Hello World");

/* C++ */

return env->NewStringUTF("Hello World");

​ 在C语言中,JNIEnv是指向JNINativeInterface结构的指针,使用它必须要解引用。而第一个参数还是env,学过C和C++语言都知道,C语言是面向过程语言,NewStringUTF只是一个函数指针,调用该方法还不清楚调用者,所以要传递env,而C++就不用,因为C++是面向对象语言,这个就不解释咯

2.关于C++调用C函数或者变量

1

2

3

4

5//在C++中引用C语言中的函数和变量,在包含C语言头文件时(假设为cExample.h),需进行以下处理:

//  extern "C"

//  {

//    #include "cExample.h";

//  }

3.关于so文件的名称问题

Android.mk文件中的LOCAL_MODULE 决定了so文件的名称,LOCAL_MODULE 的名称可以手动修改也可以在build.gradle中配置:

1

2

3

4ndk {

// moduleName "native_datahelp"//编译后so库的名称

}

4.关于System.loadLibrary();

为什么loadLibrary中填入的名称不一致,却能依然运行成功不报错?

目前自测发现 build文件中出现很多编译后的so库 有可能是旧so库未及时清除的原因,可以过研究研究build文件夹,里面藏着非常多的秘密

5.ndk-build不执行照样运行成功

C/C++源码文件改动后自动调用ndk-build编译生成新的so库存放在build文件夹中,可以拷贝直接使用,ndk-build生成正式的so库,这跟apk打包是同样的道理 Android.mk文件是必须存在的,否则无法编译生成so库,也无法编译识别源文件

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值