问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

android 怎么封装jni

发布网友 发布时间:2022-04-23 13:19

我来回答

1个回答

热心网友 时间:2023-05-23 05:15

一、底层实现:

c文件:hardware/libhardware_legacy/power/power.c

以其中set_screen_state(int)函数为例

其Android.mk中添加:
LOCAL_MODULE:= libpower 编译成lib
LOCAL_SRC_FILES += power.c

hardware/libhardware_legacy/power/power.c
1: int
2: set_screen_state(int on)
3: {
4: QEMU_FALLBACK(set_screen_state(on));
5:
6: LOGI("*** set_screen_state %d", on);
7:
8: initialize_fds();
9:
10: //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
11: // systemTime(), strerror(g_error));
12:
13: if (g_error)
14: goto failure;
15:
16: char buf[32];
17: int len;
18: if(on)
19: len = snprintf(buf, sizeof(buf), "%s", on_state);
20: else
21: len = snprintf(buf, sizeof(buf), "%s", off_state);
22:
23: buf[sizeof(buf) - 1] = '\0';
24: len = write(g_fds[REQUEST_STATE], buf, len);
25: if(len < 0) {
26: failure:
27: LOGE("Failed setting last user activity: g_error=%d\n", g_error);
28: }
29: return 0;
30: }

其头文件power.h中:
1: #if__cplusplus
2: extern "C" { //注1
3: #endif
4: enum {
5: PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
6: FULL_WAKE_LOCK = 2 // the screen is also on
7: };
8:
9: // while you have a lock held, the device will stay on at least at the
10: // level you request.
11: int acquire_wake_lock(int lock, const char* id);
12: int release_wake_lock(const char* id);
13:
14: // true if you want the screen on, false if you want it off
15: int set_screen_state(int on);
16:
17: // set how long to stay awake after the last user activity in seconds
18: int set_last_user_activity_timeout(int64_t delay);
19:
20:
21: #if __cplusplus
22: } // extern "C"
23: #endif

注1:

注1:extern表示其他的类已经定义了这段代码里面的内容,这里只是做声明。
"C”表示的一种编译和连接规约,这里为下一步c++调用其做准备.
比如void foo(int,int);该函数被C编译器编译后在库中的名字为_foo,
而C++编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。
由于编译后的名字不同,C++程序不能直接调用C函数。
因此C++提供了一个C连接交换指定符号extern“C”来解决这个问题而不是一种语言。
C表示这段代码可以是符合C语言的编译和连接规约的任何语言,如Fortran、assembler等。

二、cpp构成jni桥梁

一个CPP文件调用之,则需添加其头文件,比如frameworks/base/core/jni/android_os_Power.cpp.
1: #include "JNIHelp.h"
2: #include "jni.h"
3: #include "android_runtime/AndroidRuntime.h"
4: #include <hardware_legacy/power.h>
5: namespace android{
6: ....
7:
8: //定义函数:
9: static int setScreenState(JNIEnv *env, jobject clazz, jboolean on)
10: {
11: return set_screen_state(on);//以此实现cpp到c的调用
12: }
13:
14: static JNINativeMethod method_table[] = {//此处实现java对cpp的调用转化 注2
15: { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock },
16: { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock },
17: { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },
18: { "setScreenState", "(Z)I", (void*)setScreenState },
19: { "shutdown", "()V", (void*)android_os_Power_shutdown },
20: { "rebootNative", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
21: };
22: int register_android_os_Power(JNIEnv *env) //此处注册jni
23: { //向VM(即AndroidRuntime)登记 gMethods[]表格所含的本地函数
24: return AndroidRuntime::registerNativeMethods(
25: env, "android/os/Power",
26: method_table, NELEM(method_table));
27: }
28: };
注2:

typedef struct {
const char* name; //Java中函数的名字
const char* signature; //用字符串是描述了函数的参数和返回值
void* fnPtr; //函数指针,指向C函数
} JNINativeMethod;
其中比较难以理解的是第二个参数,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"
实际上这些字符是与函数的参数类型一一对应的。
"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);
具体的每一个字符的对应关系如下
字符 Java类型 C类型
V void void
Z jboolean boolean
I jint int
J jlong long
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
数组则以"["开始,用两个字符表示
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]
上面的都是基本类型。如果Java函数的参数是class,则以"L"开头,以";"结尾中间是用"/" 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring
Ljava/lang/String; String jstring
Ljava/net/Socket; Socket jobject
如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。
例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

三、java的封装实现

frameworks/base/core/java/android/os/Power.java //此处路径跟cpp中注册jni处的路径是一致的.待细研究是否有关系
1: package android.os;
2: public class Power
3: {
4: ...
5: public static native int setScreenState(boolean on); //被native修饰的表示调用了非java语言的本地方法
6: ...
7: }

四、java中对其调用

frameworks/base/services/java/com/android/server/PowerManagerService.java
import android.os.Power;
public class PowerManagerService extends IPowerManager.Stub
implements LocalPowerManager, Watchdog.Monitor {
...
int err = Power.setScreenState(on);
...
}
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
什么车险可以分期花呗 请问“有几个虫子怕什么"改为陈述句是"有几个虫子不可怕"。为什么要加... 一只狼身边有一只羊为什么狼不吃羊? 路边有一只羊,过来一只狼,却没有吃羊,为什么? ...有没有一个厂叫【福高】厂的,是做电子产品的。。3Q 明道冒险王百度云如何下载 冒险王2cps联系谁? 350分到400分的二本大学 廊坊高考400分能上什么学校 河北2023年高考400分左右能上什么大学 Android2.1 BroadCastReceiver接收不到数据,什么原因 Android中如何解决侧拉栏与主界面的重叠 如何启动一个被home的android应用程序 为什么 SSTL 和 NASA 的一些卫星使用 Android 操作系统 Android有什么好的技术点适合进行技术分享? 怎么理解 android cavans android 看门狗 4.04怎么调用 如何分析Android SystemServer Watchdog重启问题 android watchdog怎么关闭 女的脖子长痣好吗。 微信100m以上的不能传怎么办 脖子长痣好不好 脖子看今生命运吉凶 支付宝登录密码错误次数上限,怎么办 脖子后有痣好吗? 我脖子下面胸口上面有一颗黑痣好不好? 手机支付宝支付密码忘记了怎么办? 脖子下方有个痣,这个对身体有危害麽? 支付宝的支付密码显示错误怎么办 脖子上的痣好不好_对人生有何影响 脖子上长痣好吗,是什么意思? win10系统蓝屏提示代码dpc watchdog violation怎么解决? 查询手机信息代码我是三星手机,要什么命令代码查询,检测手机信息 如何开始的valgrind一个Android应用程序 S3C2440的开发板能移植android系统吗 看门狗联机后可以干嘛 一般行跪拜都是拜三拜,为何祭祀时要拜上四拜? 飞思卡尔的IMX6Q芯片好用吗?有核心板+底板的吗? 隋唐演义中,两人相见都要拜四拜,可现在拜四拜不都是拜死人的吗?谁知道原因? 农村俗语:“拜三不拜四,拜四要出事”,说的是啥意思呢? 拜孔子为什么鞠躬四次 俗语“拜三不拜四,拜四要出事”,是啥意思? 三跪九叩礼节的详解? 四拜的场合 黄金课堂上第三课月是故乡明的分段及段意? 什么是“三跪九叩”,“二跪六叩”“一跪三叩” 悬赏!!谁有2017年黄金课堂单元评估AB卷小学英语六年级上册一起的答案? 水浒传中一感谢别人大恩大义,为什么就要四拜,为什么不是三拜呢 金的熔点是多少?为什么真金不怕火炼? 至今都不解啊,拜孔子为什么鞠躬四次? 英语加盟效果好不好?