网站首页 > 技术文章 正文
这几天做独立升级,里面涉及wecomm保活,要验证wecomm在LMK情况下能否重新拉起;
网上找了一大圈,没有比较好用的工具来填充内存,很多是填充终端存储空间ROM,而不是RAM;
写了一个填充RAM的小工具(另外文章介绍,待补充),用到了native jni,对jni用法做一个小结。
生成so的方式可能有多种,这里说一种简单的方式。具体由如下三步
- 下载配置ndk,编写java调用so的native方法;
- 生成.h头文件夹,编写c/c++文件,编写Android.mk文件,Application.mk文件;
- 编译并使用SO文件;
1. 下载配置NDK,编写java方法
下载NDK:
在 file->settings->Android SDK->SDK Tools中检查NDK是否下载,如果没有就需要下载并配置一下,除了需要NDK之外,还需要下载LLDB、CMake这两个编译工具。
配置NDK:
file -> project Structure ->Sdk Location 配置好androidNDK
当前wecomm是在build文件中配置‘ndkVersion ‘16.1.4479499’’
编写Native接口方法:
编写一个java类,并在Java文件中声明native方法。
执行javah命令
进入到android工程的java目录执行(注意这里要带上类文件的包名,不要.java后缀)
命令执行结束之后,会在java目录下生成一个.h文件
有了.h文件,我们就可以进行下一步,开始编写生成so相关的文件了。
2. 编写c/c++代码,配置文件
首先在main目录下新建jni目录,然后把生成的.h文件拷贝到jni目录下面;
然后在jni目录下新建Android.mk文件,Application.mk文件,这两个文件是编译so时用到的脚本文件。
配置选项不多,根据我们的需求进行配置,这里的配置尽量选择少一点,根据下面的注释修改的脚本文件:
//注意,使用的时候需要把这些//注释去掉
//Adroid.mk
LOCAL_PATH :=$(call my-dir)//my-dir 表示当前文件夹,一般不用修改
include $(CLEAR_VARS) //这个配置需要,但是不用做修改
LOCAL_MODULE :=hello //hello就是命名so的名称,如果不是以lib开头,编译后的so文件名会以lib+文件名作为so名称
LOCAL_SRC_FILES :=SayHello.cpp //指定需要编译的c++/c文件
include $(BUILD_SHARED_LIBRARY) //这个不用修改
//APPlication.mk
APP_MODULES := hello //指定需要编译模块名子
APP_ABI := armeabi-v7a //编译so的平台,根据你的需求选择这些'armeabi','x86', 'armeabi-v7a', 'x86_64'
// ndk-build模式 app的build.gradle需要配置这个文件,不然估计会报找不到Android.mk
externalNativeBuild {
ndkBuild {
// Provides a relative path to your ndkBuild script.
path file("jni/Android.mk")
}
}
编写的c++文件
如下,需要引入jni.h以及编译生成的.h文件。
编译c++:
到terminal中切换到jni目录,执行ndk-build,(这里需要配置Ndk环境变量,就是把项目中配置的NDK路径配置到PATH中去。)
ndk-buil命令结束之后,会在libs目录中出生成对应平台的so文件,这里我只配置了armeabi-v7a这一种格式。
现在编译so的过程就完成了,接下来就是使用so了。
3. 使用SO文件
首先需要在gradle里面配置so文件的目录,如果不指定jniLigs.srcDirs, 会报找不到so的错误。
//在Android{}里面配置如下。
sourceSets { main { jniLibs.srcDirs = ['src/main/libs'] }}
接着就是编写我们的使用代码了,代码如下 ,需要注意的是,我们在加载so文件的时候,前缀“lib”不需,直接使用我们命名的文件名就ok了。
public class MainActivity extends AppCompatActivity {
private JNITest jniTest;
static {
System.loadLibrary("hello");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
jniTest = new JNITest();
initView();
}
private void initView(){
findViewById(R.id.btn_jni_test).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,jniTest.sayHello(),Toast.LENGTH_SHORT).show();
}
});
}
}
附件彩蛋:
- 实时显示当前内存工具
- 哆啦A梦,测试小工具
猜你喜欢
- 2024-10-27 NDK开发——FFmpeg视频解码 ffmpeg ndk
- 2024-10-27 Camera基本代码架构 camera calibrator
- 2024-10-27 android 功耗分析方法和优化(1) 功耗app
- 2024-10-27 Cocos Creator v2.3.2 发布了!全新 Launcher 效率飞起!
- 2024-10-27 如何androd动态注册编写计算器 淘宝动态评分计算器在线
- 2024-10-27 高通平台OV8856 Camera的bring up总结
- 2024-10-27 高通平台移植GC2145 Camera驱动 高通驱动安装
- 2024-10-27 《坎公骑冠剑》光炮Android Mk.99技能与背景故事
- 2024-10-27 ubuntu移植libwebp到Android平台 ubuntu移植到arm
- 2024-10-27 高通Android 5.1系统Root方法 高通手机系统
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)