当前位置: 首页 > 编程日记 > 正文

androidstudio jni开发_初识NDK开发(一)

 前言:初学逆向 请多多指教 昨天在看雪论坛发了篇文章,被标记了优秀,不由得感叹 这一个月没有白学! 剩下还有11个月 冲了

学习到的内容

1、了解了什么是NDK,以及在android studio中的环境搭建中注意的事项

2、pthread_create函数调用的学习

3、android的进程中的JavaVM与JavaEnv结构体

4、JNIEnv结构体在c/c++中的不同点

什么是NDK

NDK:NDK是一系列工具的集合,它是集成了交叉编译器,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk

为什么需要Android NDK?

1、效率问题

2、 跨平台程序的移植

我们知道在Android上层APP应用都是通过java写出来的.但是当我们设计游戏或视频,音频程序时,肯定需要完成一些复杂的数学运算,这些复杂的操作基本都是放在底层的库中运行的,而且不是通过java语言写出来的,因为java是基于虚拟机的,比C直接面向CPU的执行效率要低很多

环境搭建,Android Studio在SDK Manager中安装如下两个包SDK工具包:

ada6db7b-6620-eb11-8da9-e4434bdf6706.png

创建一个新的Android工程,拖到最下面选择Native c++

afa6db7b-6620-eb11-8da9-e4434bdf6706.png

注意:

1、如果有报错信息为NDK not configured,自己检查下当前工程是否配置了ndk的路径,FILE-Project Structure - SDK Location中ndk的配置路径,然后再去检查是否配置了NDK的环境变量

b2a6db7b-6620-eb11-8da9-e4434bdf6706.png

继续来看CMakeLists.txt中的内容,CMakeLists文本中有规范编译的说明

1、cmake_minimum_required 来表注 cmake的最低版本号的要求

b4a6db7b-6620-eb11-8da9-e4434bdf6706.png

1、设置编译出来的共享连接库文件的名字

2、设置编译的类型

3、设置被编译的源文件的名字

b6a6db7b-6620-eb11-8da9-e4434bdf6706.png

ndkbuild 通过build.gradle的android->defaultConfig中来标注需要生成的对应的处理器类型和位数的共享链接库文件

b8a6db7b-6620-eb11-8da9-e4434bdf6706.png

如果想要让cmake编译的话,可在android->defaultConfig 中添加,标注需要生成的对应的处理器类型和位数的共享链接库文件

bca6db7b-6620-eb11-8da9-e4434bdf6706.png

结果生成的apk的lib目录下就只有对应的arm v7a的共享链接库文件

c0a6db7b-6620-eb11-8da9-e4434bdf6706.png

pthread_create函数的学习

这里就简单实现两个demo,一个是单参数,一个是多参数

需要注意的就是运行的时候,在主线程中需要设置pthread_join让主线程进行堵塞,防止主线程执行完了 子线程还没执行,这个是基础了 大家肯定也知道,自己就做个笔记!

单参数

#include #include #include #include #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MYNATIVE", __VA_ARGS__);void* test(void* args){    for(int i=0;iint*)args;i++){        LOGD("test: %d", i);    }    return 0;}extern "C" JNIEXPORT jstring JNICALLJava_com_example_myndkstudy_MainActivity_stringFromJNI(        JNIEnv* env,        jobject /* this */) {    pthread_t pthread;    int iNum = 10;    void* iValue = NULL;    pthread_create(&pthread, NULL, test, &iNum);    pthread_join(pthread, &iValue);    LOGD("pthread return value: %d", iValue);    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}

c2a6db7b-6620-eb11-8da9-e4434bdf6706.png

所谓的多参数,其实就是传递参数的时候放一个结构体就好了

#include #include #include #include #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "MYNATIVE", __VA_ARGS__);struct People{    int age;    std::string name;};// 子线程void* test(void* args){    People people = *(People*)args;    LOGD("test: %d", people.age);    LOGD("test: %s", people.name.c_str());    pthread_exit(0);}extern "C" JNIEXPORT jstring JNICALLJava_com_example_myndkstudy_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {    /* thread test */    pthread_t pthread;    People people = {20,"我就想睡觉"};    pthread_create(&pthread, NULL, test, &people);    pthread_join(pthread, NULL);    std::string hello = "Hello from C++";    return env->NewStringUTF(hello.c_str());}

c4a6db7b-6620-eb11-8da9-e4434bdf6706.png

进程中的JavaVM和JavaEnv

先知道JNI_OnLoad是什么时候执行顺序的?

array_init -> init_array -> JNI_OnLoad

如何获取JNIEnv 和 JavaVM:

通过JavaVM的attachCurrentThread 子线程中获取JNIEnv

通过JavaVM的GetEnv在主线程中获取JNIEnv

注意:

1、子线程attachCurrentThread获取完JNIEnv,用完之后还需要释放DetachCurrentThread,但是在主线程中通过attachCurrentThread去获取JNIEnv也是可以获取成功的!

2、通过JavaVM的GetEnv,只能在主线程中获取JNIEnv,如果在子线程中获取会获取失败

3、重点,JNI_OnLoad返回值一定要返回对应的JNI版本,一般都是返回JNI_VERSION_1_6,否则程序会报错

最终展示的结果:

1、JavaVM对象在art虚拟机中的进程中是唯一的

2、JNIEnv对象在art虚拟机中的进程中并不是唯一的,而是多个

c5a6db7b-6620-eb11-8da9-e4434bdf6706.png

JavaEnv结构体在c/c++中的不同点

为了更好的学习JavaVM 和 JNIEnv,那么就需要了解的透彻,先从结构体下手

在学习的时候都看到在C中对 JNIEnv对象调用方法的时候,都需要先对env解引用一次,然后再去调用jni的方法,比如ida中就有对应的例子,比如:

caa6db7b-6620-eb11-8da9-e4434bdf6706.png

cda6db7b-6620-eb11-8da9-e4434bdf6706.png

继续跟一层,可以看到如下,其实本质是跟C一样的

cfa6db7b-6620-eb11-8da9-e4434bdf6706.png

所以这里就来学习为什么两种调用方式是不同的,其实这里就是c++会帮助我们来封装函数,追究到底还是得研究jni.h的定义

先跟进JNIEnv,可以发现对于JNIEnv定义 c++和c的定义是不同的,c++会给它起一个别名,而c就直接就是JNINativeInterface结构体指针

d2a6db7b-6620-eb11-8da9-e4434bdf6706.png

继续跟_JNIEnv这个别名

d5a6db7b-6620-eb11-8da9-e4434bdf6706.png

继续跟_JNIEnv,发现原来JNINativeInterface结构体指针也在_JNIEnv中,但是会发现下面的内容是对于c++来定义的

d8a6db7b-6620-eb11-8da9-e4434bdf6706.png

首先看GetVersion这个函数,你会发现它最终还是进去了functions这个JNINativeInterface结构体指针,然后最终调用了JNINativeInterface结构体中的GetVersion

jint GetVersion(){ return functions->GetVersion(this); }

所以很简单,其实就是c++帮助我们封装了一层函数,让我们间接来调用,在调用的时候c++会帮我们传入一个this指针,也就是图中红框的地方

dba6db7b-6620-eb11-8da9-e4434bdf6706.png

但是在C中,当正常的调用GetVersion这个函数指针的时候,它需要一个JNIEnv的指针,但是c++会帮我们传进去,所以c++调用的时候就可以不用参数直接进行调用

文章对你是否有帮助?有的话就点个?吧!!!

dea6db7b-6620-eb11-8da9-e4434bdf6706.png

相关文章:

http编程学习(C#)

《HTTP Programming Recipes for C# Bots》 第一章 选择GET还是POST取决于传送到服务器的数据的多少。GET传送的数据少,POST几乎对传送的数据无限制。 It is important to note that only one physical file is transferred per HTTP request. 每次HTTP请求只传送了…

服务器远程免密登录

1. 生成本地密钥 ssh-keygen2. 将密钥上传到服务器 ssh-copy-id -p port username192.128.128.128 3. 创建登录脚本 ssh -p port username192.128.128.128 转载于:https://www.cnblogs.com/yeran/p/11348045.html

如何触发AspxGridview的PageIndexChanged 客户端事件

?最近在使用AspxGridview控件时,遇到一个问题,就是在触发AspxGridview分页事件之后,需要在执行js事件,找了好久,在官网上找到处理的办法。 就是在cs页面设置变量在触发PageIndexChanged事件后,改…

Mysql 多表使用 Case when then 遇到的坑

前言: 在做一个订单导出时,遇到多表都含有state这个字段,含有多个状态首先想到的是: case colume when condition then result when condition then result when condition then result else result end 当正常试着写代码时会发现…

nginx反向代理原理及配置详解

nginx概述nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;nginx可以作为一个HTTP服务器进行网站的发布处理,另外nginx可以作为反向代理进行负载均衡的实现。 这里主要通过三个方面简…

小鱼易连电脑版_生活多么美好 篇十六:我的桌面改造,有绿植,有小鱼,有大音箱...

原标题:生活多么美好 篇十六:我的桌面改造,有绿植,有小鱼,有大音箱生活多么美好 篇十六:我的桌面改造,有绿植,有小鱼,有大音箱 2020-11-06 22:13:312点赞1收藏1评论想攒一…

菜鸟初涉SQL Server的总结

看完了一遍耿建玲老师的视频,讲的很多,一些细节的东西还是很难去把控。准备总结自己觉得无从下手,觉得很难去把控这个宏观和细节的平衡。但如果不去做这个工作的话,我可能永远都不能学会怎样去做好总结。总之,先这样去…

extjs4.0视频教程下载

发现www.uspcat.com 学习extjs4.0不错的论坛啊 http://www.uspcat.com/portal.php 视频教程下载 http://www.uspcat.com/forum.php?modviewthread&tid197&extra 转载于:https://blog.51cto.com/3450037/687004

开源依旧:再次分享一个进销存系统

开篇 我之前发过一篇博文《两天完成一个小型工程报价系统(三层架构)》,不少朋友向我要源码学习,后来久而久之忘记回复了。今天我再分享一个进销存系统,只为学习,没有复杂的框架和设计模式,有的是我个人的理解&#xff…

kotlin + springboot启用elasticsearch搜索

参考自: http://how2j.cn/k/search-engine/search-engine-springboot/1791.html?p78908 工具版本: elasticsearch 6.2.2、 kibana 6.2.2, 下载地址: elasticsearch、kibana 下载demo 1、kotlin版springboot项目创建 访问https:/…

insert 语句的选择列表包含的项多于插入列表中的项_如何定义和使用Python列表(Lists)

Python中最简单的数据集合是一个列表(list)。列表是方括号内用逗号分隔的任何数据项列表。通常,就像使用变量一样,使用符号为Python列表分配名称。 如果列表中包含数字,则不要在其周围使用引号。 例如,这是测试成绩的列表&#xf…

数据结构之主席树

这里讲静态的主席树,关于静态区间第k小。(有兴趣的朋友还可以去看看我写的整体二分,代码实现略优于主席树我觉得,当然静态主席树是很好写的) 题目描述: 题目描述 如题,给定N个正整数构成的序列&…

k-d tree算法的研究

By RaySaint 2011/10/12 动机 先前写了一篇文章《SIFT算法研究》讲了讲SIFT特征具体是如何检测和描述的,其中也提到了SIFT常见的一个用途就是物体识别,物体识别的过程如下图所示: 如上图(a),我们先对待识别的物体的图像进行SIFT特…

Unicode,UTF-32,UTF-16,UTF-8到底是啥关系?

编码的目的,就是给抽象的字符赋予一个数值,好在计算机里面表示。常见的ASCII使用8bit给字符编码,但是实际只使用了7bit,最高位没有使用,因此,只能表示128个字符;ISO-8859-1(也叫Latin-1&#xf…

HDU 4407 sum 容斥原理

算法: 利用数据1...N的性质&#xff0c;求与P的互质的个数&#xff0c;位运算&#xff0c;容斥定理。。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<vector> #include<string> #include<ma…

uniapp中qrcode生成二维码后传的参数不见了_阿虚教你制作动态二维码,超详细教程!

这篇教程很早之前就答应几个粉丝要写&#xff0c;拖的有点久了。内容比较多&#xff0c;先上个目录阿虚的教程会迟到&#xff0c;但永远不会缺席。hahahahhaha...一、 先说一下今天要教的内容ʕ•̫͡•ོʔ•̫͡•ཻʕ•̫͡•ʔ•͓͡•ʔ 1.不准备教的类似这种二维码&#…

得到最后的自增长列的最后一个值

declare Table_name varchar(60) set Table_name aa; Select so.name Table_name, --表名字 sc.name Iden_Column_name, --自增字段名字 ident_current(so.name) curr_value, --自增字段当前值 ident_incr(so.name) incr_value, --自增字段增长值 ident_seed(so.name) s…

关于C语言中 字符串常量的问题

昨天晚上我编写了一段简短的C语言程序&#xff08;Linux环境下&#xff09;&#xff0c;编译能够通过&#xff0c;但是运行的时候老是报段错误。我当时非常郁闷&#xff0c;因为代码不长。其中主函数中有这样一句话&#xff1a; char *str"epmzm bpmzm qa eqtt bpmzm qa i…

WPF布局(2) 使用的DockPanel面板进行简单的布局

DockPanel 面板是根据外边缘进行控件的拉伸&#xff0c;DockPanel的LastChildFill属性设置为True 时&#xff0c;最后一个添加的控件将占满剩余空间。 <DockPanel LastChildFill"True"><Button DockPanel.Dock"Top">Top Button</Button>…

合并两个有序数组(重新开始)

在看分治算法的时候&#xff0c;想先自己写写合并的代码&#xff0c;还是不熟练啊&#xff01; 为了保持对代码的敏感度&#xff0c;要保持练习。加油&#xff01; public class JustDoIt0803 {/*** 分治算法学习前准备*/public static void main(String[] args) {int[] x new…

miui通知栏要点两下_MIUI免费主题分享,半透明通知栏很好看,另附壁纸!

最近很少分享主题&#xff0c;主要原因是没发现太好的&#xff0c;甚至主题连一处漂亮的点都没有&#xff0c;不过还是有一款状态栏很精致的主题&#xff0c;这里分享大家&#xff0c;可用作混搭使用&#xff01;主题名&#xff1a;Blur首先主题是免费的&#xff0c;也之所以免…

C#中的委托和事件(续)

引言 如果你看过了 C#中的委托和事件 一文&#xff0c;我想你对委托和事件已经有了一个基本的认识。但那些远不是委托和事件的全部内容&#xff0c;还有很多的地方没有涉及。本文将讨论委托和事件一些更为细节的问题&#xff0c;包括一些大家常问到的问题&#xff0c;以及事件访…

优先级队列实现哈夫曼树的编码和译码

//优先级队列实现的哈夫曼树的编码和译码 #include<iostream> #include<queue> #include<string> using namespace std; class Node { public: float weight; Node* left; Node* right; char ch; Node(float…

Git,Github和Gitlab简介和使用方法

什么是Git Git是一个版本控制系统&#xff08;Version Control System&#xff0c;VCS&#xff09;。 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。 多年前&#xff0c;我在法国做第一个实习时&#xff08;2011年&#xff09;&a…

Win10控制桌面图标显示

1、桌面鼠标右键&#xff0c;进入个性化 2、进入主题&#xff1a; 3、 转载于:https://www.cnblogs.com/132818Creator/p/11356237.html

如何查看笔记本电脑配置参数_教你如何查看 MacBook 配置,超简单

相信很多人都会遇到这样的情况&#xff1a;当有人问起你的 MacBook 配置时&#xff0c;你却愣了&#xff0c;因为你自己都没注意或者查看过。实际上&#xff0c;有很多人对自己的电脑配置都不是很清楚&#xff0c;本期Mac毒就来教教你如何快速查看苹果电脑的相关配置。1、首先&…

为什么以太网帧的长度最短64字节,最长1518字节?

1.碰撞槽时间 假设公共总线媒体长度为S&#xff0c;帧在媒体上的传播速度为0.7C&#xff08;光速&#xff09;&#xff0c;网络的传输率为R&#xff08;bps&#xff09;&#xff0c;帧长为L&#xff08;bps&#xff09;&#xff0c;tPHY为某站的物理层时延&#xff1b; 则有&a…

PHP 利用AJAX获取网页并输出(原创自Zjmainstay)

看点&#xff1a; 1、file_get_contents超时控制。 2、页面编码判断。 3、键盘Enter键捕捉响应。 4、键盘event兼容处理。//event event || window.event; 5、XMLHttpRequest 和 jQuery 两种实现方案。 6、页面及源码同时展示。 XMLHttpRequest版本 get_web.php <?phphead…

TCP/IP 协议栈4层结构及3次握手4次挥手

TCP/IP 协议栈是一系列网络协议的总和&#xff0c;是构成网络通信的核心骨架&#xff0c;它定义了电子设备如何连入因特网&#xff0c;以及数据如何在它们之间进行传输。TCP/IP 协议采用4层结构&#xff0c;分别是应用层、传输层、网络层和链路层&#xff0c;每一层都呼叫它的下…

简述BT下载技术及其公司发展现状

一、 BT下载技术是什么&#xff1f;谁发明的&#xff1f; 2003年&#xff0c; 软件工程师Bram Cohen发明了BitTorrent协议&#xff08;俗称“BT下载”&#xff09;&#xff0c;其采用高效的软件分发系统和P2P技术共享大体积文件&#xff08;如一部电影或电视节目&#xf…