标签: Android Studio

注册JNI函数的两种方式

前言
前面介绍过如何实现在Android Studio中制作我们自己的so库,相信大家看过之后基本清楚如何在Android studio创建JNI函数并*终编译成不同cpu架构的so库,但那篇文章介绍注册JNI函数的方法(静态方法)存在一些弊端,本篇将介绍另外一种方法(动态注册)来克服这些弊端。

注册JNI函数的两种方法
静态方法
这种方法我们比较常见,但比较麻烦,大致流程如下:
– 先创建Java类,声明Native方法,编译成.class文件。
– 使用Javah命令生成C/C++的头文件,例如:javah -jni com.devilwwj.jnidemo.TestJNI,则会生成一个以.h为后缀的文件com_devilwwj_jnidemo_TestJNI.h。
– 创建.h对应的源文件,然后实现对应的native方法,如下图所示:

%title插图%num

说一下这种方法的弊端:

需要编译所有声明了native函数的Java类,每个所生成的class文件都得用javah命令生成一个头文件。
javah生成的JNI层函数名特别长,书写起来很不方便
初次调用native函数时要根据函数名字搜索对应的JNI层函数来建立关联关系,这样会影响运行效率
摘自:深入理解Android卷I
既然有这么多弊端,我们自然要考虑一下有没有其他更好的方法下一节就是我要讲的替代方法,Android用的也是这种方法。

动态注册
我们知道Java Native函数和JNI函数时一一对应的,JNI中就有一个叫JNINativeMethod的结构体来保存这个对应关系,实现动态注册方就需要用到这个结构体。举个例子,你就一下子明白了:

声明native方法还是一样的:

public class JavaHello {
public static native String hello();
}

创建jni目录,然后在该目录创建hello.c文件,如下:

//
// Created by DevilWwj on 16/8/28.
//
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>

/**
* 定义native方法
*/
JNIEXPORT jstring JNICALL native_hello(JNIEnv *env, jclass clazz)
{
printf(“hello in c native code./n”);
return (*env)->NewStringUTF(env, “hello world returned.”);
}

// 指定要注册的类
#define JNIREG_CLASS “com/devilwwj/library/JavaHello”

// 定义一个JNINativeMethod数组,其中的成员就是Java代码中对应的native方法
static JNINativeMethod gMethods[] = {
{ “hello”, “()Ljava/lang/String;”, (void*)native_hello},
};

static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods) {
jclass clazz;
clazz = (*env)->FindClass(env, className);
if (clazz == NULL) {
return JNI_FALSE;
}
if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}

/***
* 注册native方法
*/
static int registerNatives(JNIEnv* env) {
if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {
return JNI_FALSE;
}
return JNI_TRUE;
}

/**
* 如果要实现动态注册,这个方法一定要实现
* 动态注册工作在这里进行
*/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;

if ((*vm)-> GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return -1;
}
assert(env != NULL);

if (!registerNatives(env)) { //注册
return -1;
}
result = JNI_VERSION_1_4;

return result;

}

先仔细看一下上面的代码,看起来好像多了一些代码,稍微解释下,如果要实现动态注册就必须实现JNI_OnLoad方法,这个是JNI的一个入口函数,我们在Java层通过System.loadLibrary加载完动态库后,紧接着就会去查找一个叫JNI_OnLoad的方法。如果有,就会调用它,而动态注册的工作就是在这里完成的。在这里我们会去拿到JNI中一个很重要的结构体JNIEnv,env指向的就是这个结构体,通过env指针可以找到指定类名的类,并且调用JNIEnv的RegisterNatives方法来完成注册native方法和JNI函数的对应关系。

我们在上面看到声明了一个JNINativeMethod数组,这个数组就是用来定义我们在Java代码中声明的native方法,我们可以在jni.h文件中查看这个结构体的声明:

typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;

结构体成员变量分别对应的是Java中的native方法的名字,如本文的hello;Java函数的签名信息、JNI层对应函数的函数指针。

以上就是动态注册JNI函数的方法,上面只是一个简单的例子,如果你还想再实现一个native方法,只需要在JNINativeMethod数组中添加一个元素,然后实现对应的JNI层函数即可,下次我们加载动态库时就会动态的将你声明的方法注册到JNI环境中,而不需要你做其他任何操作。

总结
关于JNI技术,在Android中使用是非常多的,我们在实际开发中或多或少可能会使用到第三方或者需要自己开发相应的so库,所以学习和理解JNI中的一些实现原理还是很有必要的,从以前在Eclipse来实现so库开发到现在可以通过Android Studio来开发so库,会发现会方便很多,这个也是技术的发展带来的一些便捷。笔者也计划学习NDK开发的相关技术,后续也会将自己学到的内容总结分享出来。

Android studio运行java程序

在写程序的时候总会遇到测试一个小的功能或者算法,这个时候如果每次都通过运行android程序来测试就太浪费时间了。studio也可以直接运行java程序。下面就直接贴步骤:

1 在已经建立的项目中添加新的module,然后选择JavaLibrary

%title插图%num

%title插图%num

2 填写新的module的信息,然后会生成对应的module和类,这个时候会有新的build.gradle生成

 

%title插图%num

%title插图%num

3这个时候已经完成了创建。但是不能直接点击运行键,这个时候需要设置一下。然后选择application,通过配置Name,mainclass, module名称来实现运行的配置。

%title插图%num %title插图%num

4 配置之后就可以直接运行了。如果想要删除掉的话,直接在项目的settings.gradle文件中删除对应的module就可以。

%title插图%num %title插图%num

在Android Studio重新上传项目时,遇到报错问题

描述:

在GitHub上面上传项目,但是感觉有些问题,就想删除了重新上传。

但是在Android Studio重新上传项目时,遇到了问题,一直提示“project is already on github”

 

解决方案:

1、关闭Android Studio项目;

 

2、进入到本地项目目录,找到隐藏文件夹.git

%title插图%num

 

进入该文件夹下,找到config文件

删除下面这段内容

[remote "origin"]
    url = https://github.com/AnneHan/slidingMenu.git
    fetch = +refs/heads/*:refs/remotes/origin/*

%title插图%num

 

保存config文件

 

3、重新打开Android Studio,进入VCS->Import into Version Control->Share Project on GitHub,再次上传项目即可。

想阅读 Android 源码,请问该往哪个方向努力?

我是一年经验的 Android 开发,在某大厂工作。对 Android 的源码比较有兴趣。

尝试鼓捣过 AOSP,生成 ipr 文件后在 Android Studio 基本不报红。但是看源码抓瞎,不知道从何看起(如:①应用在安装过程中,Android 系统做了什么操作;②又或是状态栏下滑时,当前 TaskRecord 顶部的 Activity 会发生什么变化,等等),请问我该怎么做?

先感谢各位老哥老姐的回复!

12 条回复    2021-02-22 16:13:13 +08:00
MaxLi77
    1

MaxLi77   63 天前

半吊子先回答一下,Activity 相关 AMS,安装包管理 PMS,服务管理 Service Manager,进程通信 Binder 。懂的老哥可以多补充。
calloc
    2

calloc   63 天前 via iPhone

可以从上层 APP 入手,比如要分析安装 apk 时系统做了什么,我们知道系统在安装 apk 的时候 UI 界面是有所体现的,那么可以用`adb shell dumpsys activity top`命令查看当前界面对应的 Activity 。知道它的 Activity 就可以在源码中找到它对应的类,之后就可以用调试大法了。
ZSpirytus
    3

ZSpirytus   63 天前 via Android

@MaxLi77 感谢!我主要想搞懂某一个细节,比如说,点击安装后,系统做了什么之类的,直接看 AMS 和 PMS 的源码容易抓瞎。。
ZSpirytus
    4

ZSpirytus   63 天前 via Android

@calloc 感谢!这个思路巧妙,忘了还有 adb 这个工具,我试试看!
elonmask
    5

elonmask   63 天前 via Android   ❤️ 1

现在的安卓开发卷的厉害,想当年知道四大组件和生命周期就可以去 bat,现在又是 framework 又是 kernel 的,
12 年的时候我记得当时 QQ 安卓 app 的账号和密码都还放明文放 share preference 呢。如果
还年轻可以读个研或者自学换个方向,写界面是没有前途的。
MaxLi77
    6

MaxLi77   63 天前

@ZSpirytus 直接搜索 XXX 功能 + 源码分析,跟着别人的分析思路去看
m30102
    7

m30102   63 天前

@elonmask 以前 20 分的水平能一年一套房,现在 80 分的水平大概率睡桥洞
welkinshadow002
    8

welkinshadow002   62 天前

这里推荐 Gityuan 的相关博客,对整个流程的理解十分有帮助,http://gityuan.com/android/,我自己还买了一些书 android 系统内核设计思想啥的。

不过需要注意的是 android10 、android11 系统源码的改动比较大,自己还是要去跟一下

同样一年经验在学源码,共勉

ZSpirytus
    9

ZSpirytus   62 天前 via Android

@MaxLi77 哈哈,这个确实也是一种思路,我试试
ZSpirytus
    10

ZSpirytus   62 天前 via Android

@welkinshadow002 谢谢,这个我参考一下

ZSpirytus
    11

ZSpirytus   62 天前 via Android

@elonmask 我是纯兴趣的,只是好奇里面是怎么工作的
yolo0014
    12

yolo0014   44 天前

可以从 SystemUI 和 launcher 入手看看

你们的一加 9 ADB 能识别吗?

昨天短暂的识别之后,到现在的 Android Studio 一直不能发现设备,各种重启都试了

PS:通知栏一直常驻开发者选项已开启,存在风险是什么鬼

感觉一加快弃坑了,对 9 很失望,Color OS 垃圾

第 1 条附言  ·  23 小时 5 分钟前

不支持模糊搜索这个很致命,以前 T9 键盘随意点击几下就可以定位到应用,现在汉字名称的应用必须输入汉字才能定位到
第 2 条附言  ·  19 小时 4 分钟前

已解决,选择传输文件,并且在开发者模式里选择 RDMI
第 3 条附言  ·  19 小时 3 分钟前

RNDIS
24 条回复  •  2021-04-01 08:06:16 +08:00
1 F1ReKing   23 小时 38 分钟前 Color OS 一直都是提示开启 adb 风险的 习惯就好
2 john990   23 小时 35 分钟前 @F1ReKing 现在的应用搜索也不能模糊搜索了,找应用及其不方便
3 lmmortal   23 小时 14 分钟前 via Android 连接手机以后有传输文件 充电 照片什么的,各个选项都试一下
4 jmyz0455   23 小时 12 分钟前 听说接上 usb 连分享网络都拿掉了?
5 unkn369   23 小时 12 分钟前 一加 9 pro 怎么刷氧 OS?
6 john990   23 小时 7 分钟前 @unkn369 现在还刷不了,官方还没出
7 Osk   23 小时 6 分钟前 via Android 一加 8 瑟瑟发抖,大氢亡了,是时候崇氧啦
8 john990   23 小时 3 分钟前 @lmmortal 选 RNDIS 可以了,感谢!! 搜索了一下,似乎是 Color OS 的特性
9 noahhhh   23 小时 1 分钟前 via Android https://weibo.com/u/2448674500 据说氧 OS 已经有了
10 ququYamada   22 小时 58 分钟前 手持 1+6,9 系列换成颜色 OS 后感觉自己对一加失去热情了。本来还打算在和哈苏合作的三年内换机。
11 skkk   22 小时 51 分钟前 @noahhhh 对的,有人已经刷完而且砖了。
12 Samuelcc   22 小时 44 分钟前 via Android 我换了一加 9PRO,也是 color os 用得很恶心 不过可以去售后中心刷氧,就是得等几天因为说是现在国际包有点问题。后面应该也会有直接刷氧的方法。 一加再这样乱搞,真的得弃坑了
13 marcong95   22 小时 24 分钟前 还幻想 ColorOS for OnePlus 会把通知栏的开发者模式提醒去掉,果然还是想多了。我的 1+7Pro 瞬间又不卡了
14 en20   22 小时 4 分钟前 一直开着调试确实是有风险的,oppo 主要使用人群又不是开发者,有提示很正常,以前版本开着整个状态栏都变色
15 Moyudawang   20 小时 53 分钟前 USB 连接模式选择传输文件试试
16 x340   20 小时 35 分钟前 via iPhone 以后我的备用机只能选 pixel 了。
17 HongJay   19 小时 44 分钟前 别用 coloros 用痒不好么
18 john990   19 小时 3 分钟前 via Android @HongJay 9 现在还没出氧
19 john990   16 小时 19 分钟前 via Android @en20 一加很多用户是开发者吧
20 nbweb   16 小时 18 分钟前 我所有一加手机,到手后,*件事拆包装,第二件事开机,第三件事刷成氧 os
21 gablic   16 小时 16 分钟前 请问 coloros 和氢比哪里不好用啊
22 demonzoo   15 小时 41 分钟前 还好 8p 一切正常,我就不升级 color os 了
23 john6lq   9 小时 1 分钟前 via iPhone 我当前状态结合国内 APP 现状而言,安卓机也只能当测试机,完全没有使用欲望。
24 john990   1 小时 55 分钟前 via Android @john6lq 那倒不至于,至少我觉得比 iPhone 好用,可能因为我本来就是 Android 开发吧。

Android Studio开发中遇到的问题及解决方法

Android Studio开发中遇到的几个问题及解决方法:

1.创建虚拟机后,运行时出现错误对话框,错误内容如下:
KVM is required to run this AVD.
/dev/kvm is not found.
Enable VT-x in your BIOS security settings, ensure that your Linux distro has working KVM module.

解决方法:
重启电脑,按Enter键,再按F1键进入系统固件设置(BIOS)界面(这是ThinkPad T460p的进入方法,其他机型需查询对应品牌的用户手册),使用左右光标键移动至至“Security”页,用上下光标键移动至“Virtualization”项,按Enter键,再用上下光标键移动至“Intel (R) Virtualization Technology”项,按Enter键,选择“Enabled”选项,按F10键保存退出,重启操作系统,问题解决。

2.Gradle构建出现如下错误信息:
Error:Execution failed for task ‘:app:buildNative’.
> A problem occurred starting process ‘command ‘/home/davidhopper/Android/Sdk/ndk-bundle/ndk-build”
更为详细的错误信息如下:
Executing tasks: [:app:assembleDebug]

Configuration on demand is an incubating feature.
NDK is missing a “platforms” directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory.  It is currently set to /home/davidhopper/Android/Sdk/ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.

Incremental java compilation is an incubating feature.
:app:buildInfoDebugLoader
:app:buildNative FAILED
:app:buildInfoGeneratorDebug

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ‘:app:buildNative’.
> A problem occurred starting process ‘command ‘/home/davidhopper/Android/Sdk/ndk-bundle/ndk-build”

* Try:
Run with –stacktrace option to get the stack trace. Run with –info or –debug option to get more log output.

BUILD FAILED

Total time: 6.369 secs

解决方法:
该错误信息说明在“/home/davidhopper/Android/Sdk/ndk-bundle/”文件夹下找不到“ndk-build”文件,因为Android Studio未自带NDK开发工具,因此会出现此错误。
到“https://developer.android.google.cn/ndk/downloads/index.html”下载Linux 64 位 (x86)版本,我下载的时候,版本号为:android-ndk-r14b-linux-x86_64,下载完毕后将其解压,得到一个“android-ndk-r14b”文件夹,将其内部的所有文件全部移动至“/home/davidhopper/Android/Sdk/ndk-bundle/”文件夹下,重启Android Studio,问题解决。

3.使用Android studio启动模拟器时,状态栏一直停在“waiting for target device to come online”提示界面,无法弹出模拟器界面。

解决方法:
该问题源自SDK自带的库文件版本问题,将本机相关库更新后映射过来即可,具体步骤如下:
a).更新安装库:
$ sudo apt-get install lib64stdc++6:i386
$ sudo apt-get install mesa-utils

b).Android sdk存放目录下的文件夹如:
$ cd ~/Android/Sdk/emulator/lib64

c).备份原有libstdc++目录:
$ mv libstdc++/ libstdc++.bak

d)将本机库链接过来:
$ ln -s /usr/lib64/libstdc++.so.6 libstdc++

e)重启Android Studio,问题解决。

4.模拟器启动后,弹出错误提示对话框,内容如下:
Installation failed with message Failed to finalize session : INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113.
It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing.

WARNING: Uninstalling will remove the application data!

Do you want to uninstall the existing application?

解决方法:
这是由于使用了native libraries,而native libraries不支持当前的cpu的体系结构,可以使用修改配置文件的方法加以解决。
打开工程“app”目录中的“build.gradle”文件,找到如下位置:
android {
compileSdkVersion 23
buildToolsVersion ‘25.0.0’
在下面添加如下语句:
splits {
abi {
enable true
reset()
include ‘x86’, ‘armeabi-v7a’,’x86_64′
universalApk true
}
}
保存,重启模拟器,问题解决。

Android Studio 提示 Failed to initialize editor怎么解决?

一、问题说明
xml 文件提示 Failed to initialize editor,无法看到实时布局的效果。

尝试了重启 AS,clean rebuild 等办法都不行。

二、解决方案
方案 1:
关闭 AS
将项目下的 .idea 文件夹删除
重新打开 AS
这样可以解决只有单个 module 的项目,如果有多个 module 可能只有一个 module 中的文件好使。

方案 2:
File 菜单
Invalidate Caches/Restart

三、问题
Invalidate Caches/Restart 是什么,用来干什么的?
对于首次创建或打开的新项目,IntelliJ IDEA 都会创建项目索引,IntelliJ IDEA 的缓存和索引主要是用来加快文件查询的速度,从而提高各种查找、代码提示等操作的速度,因此索引对 IntelliJ IDEA 的高效性来说,具有至关重要的作用。但是,IntelliJ IDEA 的缓存和索引并不一定总是起到积*的作用,有的时候,反而会因为缓存和索引的损坏,例如项目打不开、个性化设置还原等等。

当我们发现一些文件存在比较奇怪的异常情况时,你可以尝试一下通过该菜单解决。

友情链接: SITEMAP | 旋风加速器官网 | 旋风软件中心 | textarea | 黑洞加速器 | jiaohess | 老王加速器 | 烧饼哥加速器 | 小蓝鸟 | tiktok加速器 | 旋风加速度器 | 旋风加速 | quickq加速器 | 飞驰加速器 | 飞鸟加速器 | 狗急加速器 | hammer加速器 | trafficace | 原子加速器 | 葫芦加速器 | 麦旋风 | 油管加速器 | anycastly | INS加速器 | INS加速器免费版 | 免费vqn加速外网 | 旋风加速器 | 快橙加速器 | 啊哈加速器 | 迷雾通 | 优途加速器 | 海外播 | 坚果加速器 | 海外vqn加速 | 蘑菇加速器 | 毛豆加速器 | 接码平台 | 接码S | 西柚加速器 | 快柠檬加速器 | 黑洞加速 | falemon | 快橙加速器 | anycast加速器 | ibaidu | moneytreeblog | 坚果加速器 | 派币加速器 | 飞鸟加速器 | 毛豆APP | PIKPAK | 安卓vqn免费 | 一元机场加速器 | 一元机场 | 老王加速器 | 黑洞加速器 | 白石山 | 小牛加速器 | 黑洞加速 | 迷雾通官网 | 迷雾通 | 迷雾通加速器 | 十大免费加速神器 | 猎豹加速器 | 蚂蚁加速器 | 坚果加速器 | 黑洞加速 | 银河加速器 | 猎豹加速器 | 海鸥加速器 | 芒果加速器 | 小牛加速器 | 极光加速器 | 黑洞加速 | movabletype中文网 | 猎豹加速器官网 | 烧饼哥加速器官网 | 旋风加速器度器 | 哔咔漫画 | PicACG | 雷霆加速