作者: xz-dev
-
dom4j 的 proguard-rules 配置分享
前言
有用户反馈 UpgradeAll 的 F-Droid 配置无法解析,查看日志后发现 dom4j 部分报错。但是直接 debug 无法复现,只有 release 混淆才会出错。
排错
原始错误
2022-09-06 11:35:33 ClientProxyApi E/ClientProxyApi: org.dom4j.InvalidXPathException: Invalid XPath expression: .//application[@id="com.nextcloud.client"] org.jaxen.saxpath.base.XPathReader at org.dom4j.xpath.DefaultXPath.parse(DefaultXPath.java:355) at org.dom4j.xpath.DefaultXPath.<init>(DefaultXPath.java:59) at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:222) at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:202) at org.dom4j.tree.AbstractNode.selectSingleNode(AbstractNode.java:178) at net.xzos.upgradeall.core.websdk.api.client_proxy.hubs.FDroid.getRelease(FDroid.kt:32) at net.xzos.upgradeall.core.websdk.api.client_proxy.ClientProxyApi.getAppReleaseList(ClientProxyApi.kt:55) at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1$1.invoke(ServerApi.kt:57) at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1$1.invoke(ServerApi.kt:57) at net.xzos.upgradeall.core.websdk.api.ServerApiKt.callOrBack(ServerApi.kt:97) at net.xzos.upgradeall.core.websdk.api.ServerApiKt.access$callOrBack(ServerApi.kt:1) at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1.invoke(ServerApi.kt:57) at net.xzos.upgradeall.core.websdk.api.ServerApi$getAppReleaseList$value$1.invoke(ServerApi.kt:56) at net.xzos.upgradeall.core.utils.data_cache.DataCacheManager.get(DataCacheManager.kt:47) at net.xzos.upgradeall.core.utils.data_cache.DataCacheManager.get$default(DataCacheManager.kt:37) at net.xzos.upgradeall.core.websdk.api.ServerApi.getAppReleaseList(ServerApi.kt:56) at net.xzos.upgradeall.core.websdk.api.ServerApiProxy.getAppReleaseList(ServerApiProxy.kt:27) at net.xzos.upgradeall.core.module.Hub.getAppReleaseList$core_debug(Hub.kt:124) at net.xzos.upgradeall.core.module.app.data.DataGetter.renewVersionList(DataGetter.kt:48) at net.xzos.upgradeall.core.module.app.data.DataGetter.doGetVersionList(DataGetter.kt:34) at net.xzos.upgradeall.core.module.app.data.DataGetter.getVersionList(DataGetter.kt:29) at net.xzos.upgradeall.core.module.app.data.DataGetter.doUpdate(DataGetter.kt:41) at net.xzos.upgradeall.core.module.app.data.DataGetter.update(DataGetter.kt:24) at net.xzos.upgradeall.core.module.app.Updater.update(Updater.kt:59) at net.xzos.upgradeall.core.module.app.App.update(App.kt:74) at net.xzos.upgradeall.core.manager.AppManager.renewApp(AppManager.kt:183) at net.xzos.upgradeall.core.manager.AppManager$renewAppList$5$1.invokeSuspend(AppManager.kt:166) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
原始错误分析
看见
org.dom4j.InvalidXPathException: Invalid XPath expression:
的第一反应就是 XPath 写错了,这里的 XPath 是.//application[@id="com.nextcloud.client"]
,所以,按照菜鸟教程,修改为//application[@id="com.nextcloud.client"]
,解决方法无效。直接搜索
org.dom4j.InvalidXPathException: Invalid XPath expression:
关键词,从 Why does dom4j throw InvalidXPathException for a valid XPath only in my test environment? 得知可能是 Dom4j 隐藏了原始错误。尝试取消混淆后 Dom4j 正常运行,所以排除是 release 混淆之外的错误。
编写混淆规则
鉴于对 DOM4J 进行源码修改过于复杂,所以并未选择修改,而是尝试分析 XPath 出错的可能,考虑到混淆后出错,添加 consumer-rules(这里是因为处于模块中)取消对 Dom4j 的混淆。
现存的混淆规则
在 Dom4j 的 Issues 列表中搜索关键词 proguard 发现有相同问题,回答中的
-dontwarn org.dom4j.**
只能忽略 gradle 编译时的警告,自欺欺人行为,忽略。参考 news-reader 的 proguard-rules.txt 添加,测试的错误日志同上,错误并未解决。
-keep class org.dom4j.** { *; } -keep interface org.dom4j.** { *; }
指定 XML 驱动
在网上还有另一种说法 dom4j 问题解决Can‘t create default XMLReader; is system property org.xml.sax.driver set groovy,手动指定 SaxReader 驱动。
System.setProperty("org.xml.sax.driver","org.xmlpull.v1.sax2.Driver");
编译得到的软件时而可用时而报错,后预计为 gradle 编译混淆原因,因此 rebuild 后测试,均失败。
手动排除 Dom4j 依赖
所以考虑到应该只是混淆规则的问题,进行范围排除(这里使用了 Android Studio 补全判断项目有哪些库)
-keep class org.** { *; } -keep class com.** { *; } -keep class java.** { *; } -keep class javax.** { *; } -keep class net.** { *; }
测试发现错误排除。故尝试一个个取消,检查软件运行状态。这里需要注意在修改后 rebuild 整个项目,因为 gradle 可能会偷懒不混淆刚刚取消不混淆的项目。
最终测试出:
-keep class javax.** { *; } -keep class org.** { *; }
proguard-rules 配置
得到上面的 javax 与 org,在 Dom4j 项目库中使用 Github 的代码搜索 import 依赖,最终得到以下规则:
-keep class org.dom4j.** { *; } -keep interface org.dom4j.** { *; } -keep class javax.xml.** { *; } -keep class org.w3c.** { *; } -keep class org.xml.** { *; } -keep class org.xmlpull.** { *; } -keep class org.jaxen.** { *; }
解决。
-
exa 仅显示点文件
exa 是一个 ls 程序的替代品,旨在提供更加友好与多彩的用户界面,其期望与 bat 相似。
背景
在简单尝试 exa 后,我决定 alias 替换 ls 来体验一段时间,然后发现
ls -al --ignore="[^.]*"
命令无法被直接替换,因为 exa 没有 ignore 接口。测试命令
在查找文档后,发现 exa 拥有基于 glob 语法的过滤(文档的 Filtering 节)。
所以仅显示点文件的命令应该是
exa -la --ignore-glob="[!.]*"
其中,
!
意指不包括。添加 alias
最后,我修改后的 rc 文件为(color 只是为了方便之后切换回 ls,exa 默认开启)
alias ls='exa' alias l.='exa -la --ignore-glob="[!.]*"' alias ll='ls --color=auto -l' alias la='ls --color=auto -la'
-
Pipewire 多设备输出
今天想和朋友一起听歌,把ta的蓝牙耳机连到电脑上后发现 KDE 界面只能设置一个音频输出端口。想起来上次 Steam Link 的经验,决定使用 Pipewire 实现这个功能。
参考资料:
https://xzos.net/steam-for-linux-no-sound-when-streaming/
https://bbs.archlinux.org/viewtopic.php?pid=1986792#p1986792- 查找音频设备
$ pw-link -o Midi-Bridge:Midi Through:(capture_0) Midi Through Port-0 v4l2_input.pci-0000_00_14.0-usb-0_6_1.0:out_0 alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FL alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FR alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FL alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FR easyeffects_sink:monitor_FL easyeffects_sink:monitor_FR easyeffects_source:capture_FL $ pw-link -o Midi-Bridge:Midi Through:(capture_0) Midi Through Port-0 v4l2_input.pci-0000_00_14.0-usb-0_6_1.0:out_0 alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FL alsa_output.pci-0000_00_1f.3.analog-stereo:monitor_FR alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FL alsa_input.pci-0000_00_1f.3.analog-stereo:capture_FR easyeffects_sink:monitor_FL easyeffects_sink:monitor_FR easyeffects_source:capture_FL easyeffects_source:capture_FR ee_soe_output_level:output_FL ee_soe_output_level:output_FR ee_soe_spectrum:output_FL ee_soe_spectrum:output_FR ee_soe_equalizer:output_FL ee_soe_equalizer:output_FR ee_soe_convolver:output_FL ee_soe_convolver:output_FR ee_sie_output_level:output_FL ee_sie_output_level:output_FR ee_sie_spectrum:output_FL ee_sie_spectrum:output_FR Audacious:output_FL Audacious:output_FR steam:output_FL steam:output_FR bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FL bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FReasyeffects_source:capture_FR ee_soe_output_level:output_FL ee_soe_output_level:output_FR ee_soe_spectrum:output_FL ee_soe_spectrum:output_FR ee_soe_equalizer:output_FL ee_soe_equalizer:output_FR ee_soe_convolver:output_FL ee_soe_convolver:output_FR ee_sie_output_level:output_FL ee_sie_output_level:output_FR ee_sie_spectrum:output_FL ee_sie_spectrum:output_FR Audacious:output_FL Audacious:output_FR steam:output_FL steam:output_FR bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FL bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:monitor_FR
确认希望使用的音频设备为
alsa_output.pci-0000_00_1f.3.analog-stereo
与bluez_output.84_AB_26_A6_8A_6A.a2dp-sink
2. 连接创建虚拟设备
$ pactl load-module module-null-sink media.class=Audio/Sink sink_name=Simultaneous channel_map=stereo 536870913 # 模块 ID,不用记
3. 连接设备
# 顺序不影响结果 $ pw-link Simultaneous:monitor_FL bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:playback_FL $ pw-link Simultaneous:monitor_FR bluez_output.84_AB_26_A6_8A_6A.a2dp-sink:playback_FR $ pw-link Simultaneous:monitor_FL alsa_output.pci-0000_00_1f.3.analog-stereo:playback_FL $ pw-link Simultaneous:monitor_FR alsa_output.pci-0000_00_1f.3.analog-stereo:playback_FR
4. 去 KDE 设置里选择
KDE 音频设置界面 5. 卸载模块
用完后可以卸载模块
$ pactl unload-module module-null-sink
-
DP-3T 保护隐私的“健康码”
人们总是选择并相信符合直觉的解释与方案,这导致了平庸
DP-3T,一个保护隐私的接触者追踪软件,就好象健康码
健康码,从全知全能的视角出发来“保护”每个人,这几乎可以预测一定会发生老大哥事件。
而另一方面,从最小知识出发,基于随机 ID 与地理位置的 P2P(蓝牙)则避免了这些。
这不符合人类作为个体的直觉,但加密货币的出现证明了这种实现的基础。
更进一步的,参考加密货币的“价值网络”与“行为创造价值”的“权益证明”。我认为,我们可以引入加密货币的代币奖励机制,避免用户重置 ID。同时,用区块记录的方式计时与发放时间积分,保证用户手机尽力在线(除不可抗力导致的断网)与14天的检测期。
-
Steam for Linux no sound when streaming
(更多…)When I use Steam Link to play my game which is running in my ArchLinux PC, I find steam only catch microphone and ignore the sound output of PC. (Fixed on my ArchLinux PC at 2022-09-15)
Github Issue: [Remote Play] No sound when streaming #6606