记录2022年7月至今,在工作中遇到的问题,希望未来的自己看到能有所感悟。
服务端(php)和客户端(java)间数据如何传输?
答:两端语言不同统一使用JSON字符串来完成数据传递。
如何Android Studio 2.3 版本下的项目迁移到 Android 3.5版本?
场景: 由于代码太过老旧,项目库不稳定,需要进行项目迁移
分析:
1.需要先熟悉项目框架和了解Grade版本;
2.Sync 引入依赖库,并根据提示进行库修改;(不了解版本的需要到相应平台上查看)
3.了解查阅各个问题库的版本 那个适配了AndroidX()
4.修改complie 为 api 或者 implementation;
5.遇到需要全局替换的(例如:黄油刀) 可以使用 replace in path;
引入 import junit.framework.Assert 不存在
implementation 'junit:junit:4.12'
引入 import org.apache.commons.codec.binary.Base64 不存在
原由:具体详情解释
旧:Base64.encodeBase64("foobar".getBytes());
新:Base64.encode("foobar".getBytes(), Base64.NO_WRAP);
butterknife无效的问题解决
moudleA 依赖 moudleB,moudleB 引入 butterknife,moudleA 无法直接引用需要在build.grade中写入
annotationProcessor 'com.jakewharton:butterknife-compiler:版本号'
Android 9.0(P)以上报错 java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/http/util/ByteArrayBuffer
在清单文件 AndroidManifest.xml 的application 标签中添加:
<uses-library android:name="org.apache.http.legacy" android:required="false" />
为什么要在application 标签中配置 android:networkSecurityConfig="@xml/文件名"**
google在android p为了安全起见,已经明确规定禁止http协议额,但是之前很多接口都是http协议
具体详情解释
Android 安装包优化
1.动态库打包配置
在 build.gradle 构建脚本中 , 配置 ndk 编译的动态库 CPU 架构类型,那么为了控制打包后的应用大小, 可以选择性打包一些库
android {
...
ndk{
// 打包生成的 APK 文件指挥包含 ARM 指令集的动态库
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
...
}
x86 手机几乎绝迹 , 另外 “arm64-v8a” 架构的 CPU 可以向下兼容 “armeabi-v7a” 架构的动态库 ;因此 , 这里只提供 “armeabi-v7a” 架构的动态库即可
自定义打包名称
//Android Studio 3.5
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "App_${buildType.name}_v${versionName}_${getNowData()}.apk"
}
}
//Android Studio 2.3
android.applicationVariants.all { v ->
v.outputs.each { outFile ->
def outputFile = outFile.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def outputFileName = "App_${buildType.name}_v${versionName}_${getNowData()}.apk"
outFile.outputFile = new File(outputFile.parent, outputFileName)
}
}
}
android {}
//构建时间
def getNowData() {
return new Date().format("yyyy_MM_dd_HH_mm_ss")
}
错误:that was originally added here
这是由于Dialog没有在Activity销毁时,dismiss掉引起的错误
遇到A页面是竖屏,要进入B页面前,先将手机横屏,然后再进入B页面就出现页面横竖一闪回到A页面,logcat中没有任何错误日志。(如何解决呢???)
方案1:获取系统设置权限,开启方向锁定
方案2:在AndroidManifest.xml中对所有Activity设置android:screenOrientation="portrait"
属性
方案3:在AndroidManifest.xml中对所有Activity设置android:configChanges="keyboardHidden|orientation|screenSize"
在API13 以上需要加上screenSize
否则不需要,不然是走不到onConfigurationChanged
android签名打包v1和v2
二者签名所产生的结果:
v1:在v1中只对未压缩的文件内容进行了验证,所以在APK签名之后可以进行很多修改——文件可以移动,甚至可以重新压缩。即可以对签名后的文件在进行处理
v2:v2签名验证了归档中的所有字节,而不是单独的ZIP条目,如果您在构建过程中有任何定制任务,包括篡改或处理APK文件,请确保禁用它们,否则您可能会使v2签名失效,从而使您的APKs与Android 7.0和以上版本不兼容
Android 12(S 31)新增了singleIntancePerTask模式
有了singleIntance特点,但是又不需要关注taskAffinity
集成 日志显示错误:java.lang.UnsupportedOperationException: Could not find char array in java.lang.String
主要是由于 LeakCanary 版本过低需要升级
重点: Caused by: com.android.builder.internal.aapt.v2.Aapt2InternalException: Failed to start AAPT2 process.
Please check if you installed the Windows Universal C Runtime.
网上大多的解决方案是降低
build.gradle
的版本号,但是都没办法解决我的问题。
如果你也是遇到这个问题,那么请你尝试到微软官网下载KB2999226 补丁文件
,然后重启看看是否能解决你的
问题。
如果你在安装补丁过程中,安装失败“错误代码0x80240037
,那么请依次操作(https://jingyan.baidu.com/article/380abd0adec1af1d90192c1e.html)
- 在D盘中创建 update文件夹,然后把Windows6.1-KB2999226-x64放到update目录下
- 以管理员方式运行cmd
- expand –F:* D:\update\Windows6.1-KB2999226-x64.msu D:\update\
- dism.exe /online /Add-Package /PackagePath:D:\update\Windows6.1-KB2999226-x64.cab
- 输入" y " 重启电脑
引入的三方库所支持版本和项目版本不一致——>导致高低冲突不兼容问题
最佳解决方案:
android{
...
//第三方依赖库统一用一样的support_version
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
//com.android.support
if (requested.group == 'com.android.support:appcompat-v7') {
if (!requested.name.startsWith("multidex")) {
details.useVersion $support_version
}
}
}
}
...
}
给TextView部分文字加粗
方法:
第一种:SpannableString 所需参数:内容、样式、索引start、索引end、区间包含关系
第二种:html标签 注意:了解标签成对出现
操作:
- 第一种:
SpannableString span = new SpannableString("Text") span.setSpan(样式、索引start、索引end、区间包含关系) "例如: spannableString.setSpan(new ForegroundColorSpan(Color.RED), start, end,Spanned.SPAN_INCLUSIVE_EXCLUSIVE) " textView.setText(span)
参数:
- 常用样式
文字加粗:new StyleSpan(Typeface.BOLD)
文字颜色:new ForegroundColorSpan(Color.BLUE)- 区间包含关系
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ---> 不包含两端start和end所在的端点 (a,b)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE ---> 不包含端start,但包含end所在的端点 (a,b]
Spanned.SPAN_INCLUSIVE_EXCLUSIVE ---> 包含两端start,但不包含end所在的端点 [a,b)
Spanned.SPAN_INCLUSIVE_INCLUSIVE ---> 包含两端start和end所在的端点 [a,b]- 使用
动态文字的话,搭配StringBuilder 和 int 来使用例如: var start = 0 var end = 0 val stringBuilder = StringBuffer() stringBuilder.append("Hello Java") start = stringBuilder.length stringBuilder.append(data.name)//data.name 长度未知 end = stringBuilder.length
- 第二种:
使用html标签成对来实现
颜色: <font color= "#fff"> 文字 </font>
粗体: <b><tt> 文字 </tt></b>
android WebView与JS交互功能,打包debug 功能正常 release 功能不正常(AgentWeb)
- 检查混淆文件proguard-rules.pro中,是否将webView与JS交互的class添加混淆中避免混淆
- 检查Gson和实体类是否有加入避免混淆
- clean build 删除缓存
- 项目中无引用的文件移除掉
- 一般情况下,都是混淆文件出的问题,请仔细检查
如何遍历获取实体类元素
Field[] field = model.getClass().getDeclaredFields();
// 获取属性的名字
String name = field[j].getName();
// 将属性的首字符大写,方便构造get,set方法
name = name.substring(0, 1).toUpperCase() + name.substring(1);
// 获取属性的类型
String type = field[j].getGenericType().toString();
Method m = model.getClass().getMethod("get" + name);
// 调用getter方法获取属性值
String value = (String) m.invoke(model);
Android 注册页跳转主页
- 场景
A -> B ->C 然后C -> A
- 操作
将A的launchModel 设置为栈内复用(singTask),然后在A中重写onNewIntent ,OnResume也会被调用。
SwipeRefreshLayout与WebView冲突
smartRefresh.setOnChildScrollUpCallback(new SwipeRefreshLayout.OnChildScrollUpCallback() {
@Override
public boolean canChildScrollUp(@NonNull SwipeRefreshLayout parent, @Nullable View child) {
return webView.getScrollY() > 0;
}
});
刷新方式
使用系统自带 `Swiperefreshlayout`
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
使用github 最多的Star `SmartRefreshLayout`
implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-x'
http 和 https 有什么区别?
打包时,为了方便管理keyStore,我们把密钥文件放进项目中
在src中创建keystore文件夹然后
放进密钥文件
配置“./keystore/密钥文件名.jks”
WebSocket错误
Process: com.lets.oaoffice, PID: 22334
java.lang.IllegalStateException: WebSocketClient objects are not reuseable
at d.b.f.b.h(WebSocketClient.java:354)
at d.b.f.b.i(WebSocketClient.java:366)
at com.lets.oaoffice.utils.im.JWebSocketClientService$b.run(JWebSocketClientService.java:245)
主要导致的是连接的时候没有对websocket进行逻辑判断处理
推荐两款线下可以在手机上查看日志打印器
键盘弹出底部按钮被遮挡
解决方案:在AndroidManifest
中找到对应的类添加一下
android:windowSoftInputMode="stateAlwaysHidden|adjustResize"
JSON字符串方式有哪些?
1.拼接字符
2.JSONObject
3.GSON + bean对象
TextView动态设置Drawable资源
主页跳转到登录页,新建进程跳转 黑屏处理(解决)
1.禁用Preview Window
<item name="android:windowDisablePreview">true</item>
2.设置Preview Window透明属性(需要配套动画设置)
<item name="android:windowIsTranslucent">true</item>
a) 代码动态设置Activity专场动画:
overridePendingTransition(R.anim.anim_right_in,R.anim.anim_left_out);
b) xml静态设置
<style name="Animation.Activity.Translucent.Style" parent="@android:style/Animation.Translucent"> <item name="android:windowEnterAnimation">@anim/base_slide_right_in</item> <item name="android:windowExitAnimation">@anim/base_slide_right_out</item> </style>
Android Studio 代码联想功能不行,报 "Unknown attribute android:padding"
网上很多都是说打开了省电模式,但是我一直都没有打开,是突然出现这样的车祸现场
解决方法:
- 关闭Android Studio
- 移除 C:\Users\MyName.AndroidStudio3.4\system\caches
- 再次打开 Android Studio
数组转换的List,直接操作add 和 remove 报错Caused by: java.lang.UnsupportedOperationException
原因是因为组成的List是Arrays的内部类ArrayList,其中注意的是ArrayList都是继承了AbstractList,所以直接操作数据会报UnsupportedOperationException
解决:
需要将数据类型转换成List,再进行操作
使用 Iterator 迭代器
关于recycleView 如何滚动到最低部 和 两个操作函数的区别
关于androidID、deviceID等设备信息获取的注意点
androidID
- 获取方式:
Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID)
- 正常情况下都能获取到,但是一些红米的设备获取到的是
0000000000000000
- 网上说获取到也有可能是:
9774d56d682e549c
deviceid 、sn设备序列号
- (deviceID)获取方式:
(TelephonyManager) App.getApp().getSystemService(Context.TELEPHONY_SERVICE).getDeviceId()
- (sn设备序列号)获取方式:Build.SERIAL 或 Build.getSerial()
- 当设备SDK大于28(android 9),那么获取到值是空值
网上针对空值或异常值的方案,其实还有一种就是创建一个uuid 再存入 系统数据库中(类似androidID)。这样的方式就是需要申请修改系统设置权限(
Settings.ACTION_MANAGE_WRITE_SETTINGS
)。