android:小问题汇总
1、将eclipse工程导入到android studio后的配置。
Error: Your project contains C++ files but it is not using a supported native build system.
在app模块的build.grade中的BuildTypes中加上sourceSets{ main{jni.src.Dirs=[ ] } }
1.1、工作电脑gradle版本为3.1.2,gradle插件版本为4.4,新建activity什么都没做也会报错,是因为默认配置不对。
需要修改support库和SDK版本。support库和sdk一般还具有相关性,
根据eventlog的信息找到出错的代码段落,把鼠标放到报错标注的部分,as会提示为什么以及怎么改。
2、使用ndk生成.so文件的步骤。
首先需要安装ndk,在AS界面右上角的SDK manager中给NDK打个勾就行了。
然后设置一下jni文件夹下的两个mk文件
在app模块的build.grade中的BuildTypes中加上sourceSets{ main{ jniLibs.srcDirs = ['src/main/jniLibs'] jni.srcDirs=[ ] } }
然后在terminal终端进入到jni所在的文件夹(cd app\src\main\jni )后,输入ndk-build,就可以自动创建了so文件了。
(没有设置环境变量则输入ndk-build所在文件夹:C:\Users\ccaes\AppData\Local\Android\Sdk\ndk-bundle\ndk-build)
sourceSets{ main{ jni.srcDirs=[] jniLibs.srcDirs = ['src/main/jniLibs'] } } /*jni.srcDirs=[] 是告诉ndk,jni源文件所在的目录,填了地址反而报错,还不如不填*/ /* jniLibs.srcDirs 是告诉app,so库所在的位置;那个jniLibs的文件夹名是可以修改的*/
2.1 Android studio JNI中快速生成头文件 https://blog.csdn.net/wwdlss/article/details/80484140
File->Setting->Tools->External Tools->Add External Tools。/**/Program: javah /**/Parameters: -v -jni -d /src/main/jni /**/ Working directory:
3、如何设置定制机的APP签名
3.1下图是如果签名不正确,或者没有签名会报的错误:
Failed to finalize session : INSTALL_PARSE_FAILED_NO_CERTIFICATES: Package /data/app/vmdl540410799.tmp/0_dependencies has mismatched certificates at entry AndroidManifest.xml
3.2解决前提:已有.keystore文件、key store password、key alias、key password
解决步骤:build→generate signed apk→记得勾选两个按钮,点击完成之后会自动编译
→project structure→app→signing中信息填写→buildtypes框框中signing config选上刚设置的签名。
4、关于Activity.finish()、Activity.onDestory()、System.exit(0)
4.1、finish() 功能等价于back按键,结束当前acticity,但是并没有释放activity内存资源;
4.2、onDestory() 结束当前activity且释放内存资源;
4.3、System.exit(0) 结束当前应用程序且释放内存资源;
5、用drawable绘制btn的自定义xml时,右键drawable文件夹,new一个新的drawable resource file时并不会弹出selector的小框,而是弹出大框格New Resource File。
不知道为什么会这样,但是我们可以换种方式来新建一个selector的xml文件。
在res层右键,new一个Andrioid Resource File,然后在弹出框格中将resource type选为drawable,再给file取个名字,就会生成一个seletor的.xml了。
然后下一次绘制btn的自定义xml的时候,又可以直接通过右键new一个新的selecotr或者shape、layer-list了。
6、使用MDK生成bin文件的目录,教程:https://blog.csdn.net/nx505j/article/details/80924902路径复制:
D:\MDK5\SetupFile\ARM\ARMCC\bin\fromelf.exe --bin -o E:\msOS_ZDWX_20190516\Keil\Output\LPC1114_PSAM.bin E:\msOS_ZDWX_20190516\Keil\Output\msOS.axf
7、android studio环境变量的配置:https://www.jianshu.com/p/c3e1fe6f61c4
8 使用TCP协议连接安卓adb;
开启:https://www.cnblogs.com/clovershell/p/10684053.html
more than one device connect : https://blog.csdn.net/yuemingxingxing/article/details/86590989
ps1:这是一篇让你少走弯路的 JNI/NDK 实例教程 https://blog.csdn.net/kisty_yao/article/details/79466396
ps2:Android NDK 视频https://www.youtube.com/watch?v=BWLOas4nojY
ps3:使用Stacktrace处理异常(这里是各种举例) https://blog.csdn.net/u012585964/article/details/51772622
ps4:彻底解决unable to find valid certification path to requested target https://blog.csdn.net/gabriel576282253/article/details/81531746
/*****android:JNI一些相关*******************************************************************************************************************************************************/
1 在JNI层使用log日志
在c文件中加入下列宏定义;
#include "android/log.h" #define TAG " JNI_LOG_TEST " #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 LOGD("\n mode85: %d",mode85); /*调用方式为:LOGD("zhe li shi zi fu %d",10 );*/
在mk文件中加上下列代码,表示需要使用log;
LOCAL_LDLIBS :=-llog
2 JNI层的一些格式
2.1 app层经常需要和jni层交换数据,java中的基本数据类型和JNI中的基本数据类型可能编译器的处理方式是相同的,所以可以直接传递调用;
对于数组对象,编译器的处理方式可能不同,不能直接传递,可以借GetByteArrayElements函数来传递:
/*params: jparray:复制的writeArray的地址, jlen:writeArray的长度;*/ JNIEXPORT jboolean JNICALL Java_XXX_spiWrite (JNIEnv *env, jclass object, jbyteArray writeArray) { jbyte *jparray = (*env)->GetByteArrayElements(env,writeArray, NULL); jint jlen = (*env)->GetArrayLength(writeArray); jbyte jbuf[jlen]; for(jint i=0; i<jlen; i++) /*把数据从writeArray数组搬运到了JNI的数组jbuf[]里;*/ { jbuf[i] = jparray[i]; } (*env)->ReleaseByteArrayElements(env,writeArray, jparray, 0); /*搬完释放线程?? */ jbyteArray jpnewArray = env->NewByteArray(jlen); /*这两行是回调相关函数,用来给jni回显数据到android层,放在这里不适合的*/ env->SetByteArrayRegion(jpnewArray, 0, jlen, jbuf); return ; } /*app层是用户空间,linux是内核空间,那么这些定义在jni的数据是兼而有之吗?*/
2.2 如果是C程序,要用 (*env)-> ;如果是C++要用 env-> ;
在linux下如果.c文件中用 “env->” 编译会找不到此结构,必须用“(*env)->”
3 android端查看手机是否有root权限的代码;
/*查看手机是否有root权限;代码开始:*/ private final static String TAG = "RootUtil"; public static boolean isRoot() { String binPath = "/system/bin/su"; String xBinPath = "/system/xbin/su"; if (new File(binPath).exists() && isExecutable(binPath)) return true; if (new File(xBinPath).exists() && isExecutable(xBinPath)) return true; return false; } private static boolean isExecutable(String filePath) { Process p = null; try { p = Runtime.getRuntime().exec("ls -l " + filePath); // 获取返回内容 BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream())); String str = in.readLine(); Log.i(TAG, str); if (str != null && str.length() >= 4) { char flag = str.charAt(3); if (flag == 's' || flag == 'x') return true; } } catch (IOException e) { e.printStackTrace(); } finally { if (p != null) { p.destroy(); } } return false; } /*查看手机是否有root权限;代码结束;*/
4 在jni层将android端打开的文件映射到内核打开的文件;
大概就是说在android中,打开文件需要使用FileDescriptor类来打开文件;
而在内核中使用open函数来打开文件,返回该文件的唯一性标识符fd;
然后该网页提供的代码参考就是将这两端打开的文件对应起来,用来表示同一个文件;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?