2024年最全Android之JNI开发入门(1),面试哪些

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

相信自己,没有做不到的,只有想不到的

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • ⑥编写C函数 如果需要单独编译一下c代码就在c/c++视图中找到小锤子,点一下小锤子就编译了

  • 如果想直接运行到模拟器上 就不用锤子了,直接右键run as,然后就自动编译了

  • ⑦ java代码中不要忘了 System.loadlibrary();

static {

System.loadLibrary(“hello”); //加载动态链接库

}

6. Java向C传递一些基本的类型,处理

======================

将一个jstring转换成一个c语言的char* 类型工具方法

char* _JString2CStr(JNIEnv* env, jstring jstr) {

char* rtn = NULL;

jclass clsstring = (*env)->FindClass(env, “java/lang/String”);

jstring strencode = (*env)->NewStringUTF(env,“GB2312”);

jmethodID mid = (*env)->GetMethodID(env, clsstring, “getBytes”, “(Ljava/lang/String;)[B”);

jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte(“GB2312”);

jsize alen = (*env)->GetArrayLength(env, barr);

jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);

if(alen > 0) {

rtn = (char*)malloc(alen+1); //“\0”

memcpy(rtn, ba, alen);

rtn[alen]=0;

}

(*env)->ReleaseByteArrayElements(env, barr, ba,0);

return rtn;

}

int类型

JNIEXPORT jint JNICALL Java_com_xfhy_javapassdata_JNI_add

(JNIEnv * env, jobject clazz, jint x, jint y){

return x+y; //直接返回x+y

}

String类型

JNIEXPORT jstring JNICALL Java_com_xfhy_javapassdata_JNI_sayHelloInC

(JNIEnv *env, jobject clazz, jstring str){

//将jstring转换成char* 类型

char* cstr = _JString2CStr(env,str);

//调用C语言的strlen测量cstr字符串的长度

int length = strlen(cstr);

int i=0;

for(i=0; i<length; i++){

*(cstr+i) += 1; //将字符串+1

}

return (env)->NewStringUTF(env,cstr); //将char 类型转换成String类型返回

}

int[]类型

JNIEXPORT jintArray JNICALL Java_com_xfhy_javapassdata_JNI_arrElementsIncrease

(JNIEnv *env, jobject clazz, jintArray jArray) {

//jsize (GetArrayLength)(JNIEnv, jarray); 返回数组长度

int length = (*env)->GetArrayLength(env,jArray);

//jint* (GetIntArrayElements)(JNIEnv, jintArray, jboolean*); 最后一个参数表示是否拷贝,可以不用传值

//返回int* 返回该数组的首地址 这样就可以直接通过该指针直接操作该数组了

int* cArray = (*env)->GetIntArrayElements(env,jArray,NULL);

int i;

for(i=0; i<length; i++) {

*(cArray+i) += 10;

}

return jArray; //直接将原数组返回(这时已经是修改过了的)

}

7.C代码中向logcat输出内容

=================

1.Android.mk文件增加以下内容

LOCAL_LDLIBS += -llog

2.C代码中增加以下内容

#include <android/log.h>

#define LOG_TAG “xfhy”

#define LOGD(…) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, VA_ARGS)

#define LOGI(…) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, VA_ARGS)

  • define C的宏定义 起别名 #define LOG_TAG “xfhy” 给”xfhy”起别名LOG_TAG

  • #define LOGI(…) android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS),ANDROID_LOG_DEBUG表示优先级 debug ANDROID_LOG_INFO表示info 这些在log.h中可以看到

  • 给 __android_log_print函数起别名 写死了前两个参数 第一个参数 优先级 第二个参数TAG

  • VA_ARGS:是可变参数的固定写法

  • LOGI(…)在调用的时候 用法跟printf()一样

8. C代码回调java方法

===============

首先需要了解:

Java反射

public class Demo {

public static void main(String[] args) {

//1.获取字节码对象

Class util = Utils.class;

try {

//2.获取Method对象 方法名,参数类型

Method method = util.getMethod(“test”, String.class);

//3.通过字节码对象创建一个Obejct

Object obj = util.newInstance();

//4.通过对象调用方法 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法

method.invoke(obj, “hello”);

} catch (Exception e) {

e.printStackTrace();

}

}

public class Utils {

public void test(String string) {

System.out.println(string);

}

}

}

C代码回调java方法

  • ① 找到字节码对象

  • //jclass (FindClass)(JNIEnv, const char*);

  • //第二个参数 要回调的java方法所在的类的路径 “com/itheima/callbackjava/JNI”

  • ② 通过字节码对象找到方法对象

  • //jmethodID (GetMethodID)(JNIEnv, jclass, const char*, const char*);

  • 第二个参数 字节码对象 第三个参数 要反射调用的java方法名 第四个参数 要反射调用的java方法签名

  • javap -s 要获取方法签名的类的全类名 项目/bin/classes 运行javap

  • ③ 通过字节码创建 java对象(可选) 如果本地方法和要回调的java方法在同一个类里,可以直接用 jni传过来的java对象 调用创建的Method

  • jobject obj =(*env)->AllocObject(env,claz);

  • 当回调的方法跟本地方法不在一个类里 需要通过刚创建的字节码对象手动创建一个java对象

  • 再通过这个对象来回调java的方法

  • 需要注意的是 如果创建的是一个activity对象 回调的方法还包含上下文 这个方法行不通!!!回报空指针异常

  • ④ 反射调用java方法

  • //void (CallVoidMethod)(JNIEnv, jobject, jmethodID, …);

  • 第二个参数 调用java方法的对象 第三个参数 要调用的jmethodID对象 可选的参数 调用方法时接收的参数

/*

  • Class: com_xfhy_callbackjava_JNI java里的类的完整路径

  • Method: callbackvoidmethod java里面的方法名

  • Signature: ()V 方法签名

*/

JNIEXPORT void JNICALL Java_com_xfhy_callbackjava_JNI_callbackvoidmethod

(JNIEnv *env, jobject clazz) {

//1.找到字节码对象

//jclass (FindClass)(JNIEnv, const char*);

//参数: env,需要反射的对象的全路径

jclass claz = (*env)->FindClass(env,“com/xfhy/callbackjava/JNI”);

//2.通过字节码对象找到方法对象

//jmethodID (GetMethodID)(JNIEnv, jclass, const char*, const char*);

//第二个参数 字节码对象 第三个参数 要反射调用的java方法名 第四个参数 要反射调用的java方法签名

//javap -s 要获取方法签名的类的全类名 项目/bin/classes 运行javap

jmethodID methodID = (*env)->GetMethodID(env,claz,“helloFromJava”,“()V”);

//3.通过字节码创建java对象(可选),如果本地方法和要调用的java方法在同一个类里,可以直接用jni传过来的java对象,调用创建的Method

//jobject obj =(*env)->AllocObject(env,claz);

//* 当回调的方法跟本地方法不在一个类里 需要通过刚创建的字节码对象手动创建一个java对象

//* 再通过这个对象来回调java的方法

//* 需要注意的是, 如果创建的是一个activity对象, 回调的方法还包含上下文 ,这个方法行不通!!!回报空指针异常

//4.反射调用java方法

//void (CallVoidMethod)(JNIEnv, jobject, jmethodID, …);

//第二个参数 调用java方法的对象 第三个参数 要调用的jmethodID对象 可选的参数 调用方法时接收的参数

(*env)->CallVoidMethod(env,clazz,methodID);

}

9.c++ 开发JNI

===========

C的预处理命令

  • #开头的就是c/c++的预处理命令

  • 在编译之前 先会走预编译阶段 预编译阶段的作用就是 把 include进来的头文件 copy到源文件中

  • define这些宏定义 用真实的值替换一下

  • #if #else #endif 该删除的删除掉

c++开发jni代码时

  • env不再是结构体Jninativeinterface的二级指针

  • _JNIEnv JNIEnv _JNIEnv 是C++的结构体 C++结构体跟C区别 C++的结构体可以定义函数

  • env 是JNIEnv的一级指针 也就是结构体_JNIEnv的一级指针 env-> 来调用 结构体里的函数

  • _JNIEnv的函数 实际上调用的就是结构体JNINativeInterface的同名函数指针

最后

我这里整理了一份完整的学习思维以及Android开发知识大全PDF。

当然实践出真知,即使有了学习线路也要注重实践,学习过的内容只有结合实操才算是真正的掌握。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

也就是结构体_JNIEnv的一级指针 env-> 来调用 结构体里的函数

  • _JNIEnv的函数 实际上调用的就是结构体JNINativeInterface的同名函数指针

最后

我这里整理了一份完整的学习思维以及Android开发知识大全PDF。

[外链图片转存中…(img-YDZnHgFI-1715849289656)]

当然实践出真知,即使有了学习线路也要注重实践,学习过的内容只有结合实操才算是真正的掌握。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值