Android杂谈:当你尝试安装一个包名长度超过200字符的软件

Android杂谈:当你尝试安装一个包名长度超过200字符的软件

测试这个,源于写程序处理包名缓冲区时的一个灵感

这个问题随便一个搜索引擎你都能搜到很多答案:26?30?50?100?150?
这源于大多数 Apk 分发平台对软件包名长度限制的不同

但是,难道从没有人测试过,Android 系统能够接受安装的最长软件包名是多少吗?
理论上,包名应该能够达到 Linux 限制的 PATH_MAX,即 255 字节左右(这里不计算 Android 在软件安装路径上加的随机字符,但这个是重要的

好像没有,那么,自己动手,丰衣足食

Start:

刚开始我找来一个无加固软件开始改包名,50?100?150?

很快,所有图形 Apk 修改工具能够修改的最长包名已经达到了,超不过 180 字节

这当然不是终点,既然修改不行,那就从源头编译!
一番测试编译…

当最后一次将包名长度增至 246 时,终于报错了((

1
2
3
* What went wrong:
Execution failed for task ':app:dataBindingGenBaseClassesDebug'.
> java.io.FileNotFoundException: MyBasicActivity/app/build/intermediates/data_binding_base_class_log_artifact/debug/dataBindingGenBaseClassesDebug/out/com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.app-binding_classes.json (File name too long)

这个报错很明显,构建工具在尝试以Apk包名作为基础名称创建一个 json 文件,但明显超过了 Linux 限制的长度 255
解决方法:build.gradle 改一下:

1
2
3
4
buildFeatures {
dataBinding false
viewBinding false
}

继续…
但还是抛出了异常

1
2
3
4
5
* What went wrong:
Execution failed for task ':app:processDebugResources'.
> A failure occurred while executing com.android.build.gradle.internal.res.LinkApplicationAndroidResourcesTask$TaskAction
> Android resource linking failed
ERROR: MyBasicActivity/app/build/intermediates/packaged_manifests/debug/processDebugManifestForPackage/AndroidManifest.xml:2: AAPT: error: attribute 'package' in <manifest> tag is not a valid Android package name: 'com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.app'.

~ 构建工具 aapt 抛出的异常

这应该是构建工具能达到的最长包名了(?

既然编译也走不通了,常见改包名方法也就剩下 apktool、16 进制编辑器了

先试试 apktool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@localhost ~/kotlin# apktool d app-debug.apk -o app_dir
I: Using Apktool 2.7.0-dirty on app-debug.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/.local/share/apktool/framework/1.apk
I: Renamed manifest package found! Replacing com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.app with com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestt
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Baksmaling classes2.dex...
I: Baksmaling classes3.dex...
I: Baksmaling classes4.dex...
I: Baksmaling classes5.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...
I: Copying META-INF/services directory
root@localhost ~/kotlin#

解压后修改相关 xml、文件内包名
重新打包又炸了:

1
brut.androlib.AndrolibException: brut.common.BrutException: could not exec (exit code = 1): [aapt, p, --min-sdk-version, 21, --target-sdk-version, 34, --rename-manifest-package, com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.ap

由于解包Apk时连带解包了资源文件,apktool 又调用构建工具中的 aapt 打包资源,并把修改的超长包名以参数形式传给了 aapt,aapt 再次拒绝了这个超长包名参数,并返回 exit code 1,导致打包终止

既然 aapt 拒绝这个包名,总不能…改 aapt 吧((
只能想法让 apktool 不要调用 aapt 打包资源

查了一下,可以用 -r 参数解压避免解压资源文件

1
2
3
apktool d -r app-debug.apk -o app_dir

apktool b app_dir -o app-debug_1.apk

成功打包,签名 Apk

这样我们就成功拿到一个包名长度为 246 字符的软件()

接下来就是测试环节了

测试在虚拟机: 两仪 Android 8.1.0 进行

之所以选择虚拟机是因为这种测试还没人做过,一旦出 bug 很可能在系统引起奇怪的问题或残留(
为什么选择两仪:两仪提供了一个近乎完全原生的 Android 8.1 系统环境,是经典的系统版本之一,保证测试质量

刚开始我尝试使用 pm install 来安装,但 pm 似乎卡住了((既安装不上也无任何反应

命令行不通?那还是图形吧。

打开 “文件” ~ 右上角三点 ~ 打开显示内部储存,左上角菜单,点内部储存,进入内部储存找到 Apk 点击…

正常进入软件包安装程序,点击安装…

一切正常…吗?

软件安装卡在最后的部分…90% 的位置不动了,但没有弹出无响应,系统也没有卡死

很明显:出 bug 了

既然是 bug,当然要去抓 logcat

就在我输完 logcat >>/sdcard/debug.log 之后返回来时发现:前台在桌面!

这里怎么判断发生了什么呢?一般来说只有前台界面崩溃或系统重启才会在桌面

有个技巧,Android 8.1 可以在设置-系统-关于设备-状态信息里看到已开机时间
但这里千万别去看,因为某些原因,两仪系统里显示的是主系统的总开机时间((

这里看不了,还记得刚刚抓的 log 吗?

1
2
12-06 17:57:52.150 24465 24625 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=file:///data/user_de/0/com.android.packageinstaller/no_backup/package2365387567240456731.apk flg=0x10000 cmp=com.android.packageinstaller/.PackageInstallerActivity (has extras)} from uid 10009
12-06 17:57:52.344 24977 24977 I PackageInstaller: No source found for package com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.app

这段 log 显示了系统永远不会显示在前台的东西:

17:57:52.150:ActivityManager 显示启动了 com.android.packageinstaller 安装 /data/user_de/0/com.android.packageinstaller/no_backup/package2365387567240456731.apk,安装开始

17:57:52.344:PackageInstaller 爆出了一个错误:No source found for package com.imtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest.app

没错,PackageInstaller“不识别”这个包,准确来说是安装过程已经出现了问题

但这里没完,PackageInstaller 貌似陷入了一种卡死循环状态

为什么这么说?看这段log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
12-06 18:00:40.537 24465 24670 W Watchdog: Failed to write to /proc/sysrq-trigger
12-06 18:00:40.537 24465 24670 W Watchdog: java.io.FileNotFoundException: /proc/sysrq-trigger (Permission denied)
12-06 18:00:40.537 24465 24670 W Watchdog: at java.io.FileOutputStream.open0(Native Method)
12-06 18:00:40.537 24465 24670 W Watchdog: at java.io.FileOutputStream.open(FileOutputStream.java:287)
12-06 18:00:40.537 24465 24670 W Watchdog: at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
12-06 18:00:40.537 24465 24670 W Watchdog: at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
12-06 18:00:40.537 24465 24670 W Watchdog: at java.io.FileWriter.<init>(FileWriter.java:63)
12-06 18:00:40.537 24465 24670 W Watchdog: at com.android.server.Watchdog.doSysRq(Watchdog.java:586)
12-06 18:00:40.537 24465 24670 W Watchdog: at com.android.server.Watchdog.run(Watchdog.java:518)
12-06 18:00:40.538 24465 24670 W Watchdog: Failed to write to /proc/sysrq-trigger
12-06 18:00:40.538 24465 24670 W Watchdog: java.io.FileNotFoundException: /proc/sysrq-trigger (Permission denied)
12-06 18:00:40.538 24465 24670 W Watchdog: at java.io.FileOutputStream.open0(Native Method)
12-06 18:00:40.538 24465 24670 W Watchdog: at java.io.FileOutputStream.open(FileOutputStream.java:287)
12-06 18:00:40.538 24465 24670 W Watchdog: at java.io.FileOutputStream.<init>(FileOutputStream.java:223)
12-06 18:00:40.538 24465 24670 W Watchdog: at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
12-06 18:00:40.538 24465 24670 W Watchdog: at java.io.FileWriter.<init>(FileWriter.java:63)
12-06 18:00:40.538 24465 24670 W Watchdog: at com.android.server.Watchdog.doSysRq(Watchdog.java:586)
12-06 18:00:40.538 24465 24670 W Watchdog: at com.android.server.Watchdog.run(Watchdog.java:519)
12-06 18:00:40.581 24465 24670 W Watchdog: *** WATCHDOG KILLING SYSTEM PROCESS: Blocked in handler on PackageManager (PackageManager)
12-06 18:00:40.581 24465 24670 W Watchdog: PackageManager stack trace:
12-06 18:00:40.582 24465 24670 W Watchdog: at java.io.UnixFileSystem.checkAccess0(Native Method)
12-06 18:00:40.582 24465 24670 W Watchdog: at java.io.UnixFileSystem.checkAccess(UnixFileSystem.java:252)
12-06 18:00:40.582 24465 24670 W Watchdog: at java.io.File.exists(File.java:807)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService.getNextCodePath(PackageManagerService.java:17613)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService.-wrap19(Unknown Source:0)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService$FileInstallArgs.doRename(PackageManagerService.java:17029)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService.installPackageLI(PackageManagerService.java:18927)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService.installPackageTracedLI(PackageManagerService.java:18528)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService.-wrap33(Unknown Source:0)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.pm.PackageManagerService$8.run(PackageManagerService.java:15989)
12-06 18:00:40.582 24465 24670 W Watchdog: at android.os.Handler.handleCallback(Handler.java:790)
12-06 18:00:40.582 24465 24670 W Watchdog: at android.os.Handler.dispatchMessage(Handler.java:99)
12-06 18:00:40.582 24465 24670 W Watchdog: at android.os.Looper.loop(Looper.java:164)
12-06 18:00:40.582 24465 24670 W Watchdog: at android.os.HandlerThread.run(HandlerThread.java:65)
12-06 18:00:40.582 24465 24670 W Watchdog: at com.android.server.ServiceThread.run(ServiceThread.java:46)
12-06 18:00:40.582 24465 24670 W Watchdog: *** GOODBYE!
12-06 18:00:40.583 24465 24670 I Process : Sending signal. PID: 24465 SIG: 9

三分钟后(即18:00:40),系统底层的 Watchdog (看门狗)触发并抛出了完整堆栈,关键日志:

1
12-06 18:00:40.537 24465 24670 W Watchdog: Failed to write to /proc/sysrq-trigger

Watchdog:多久没喂狗了😠😠

随即,Watchdog kill 了某关键进程

1
2
12-06 18:00:40.582 24465 24670 W Watchdog: *** GOODBYE!
12-06 18:00:40.583 24465 24670 I Process : Sending signal. PID: 24465 SIG: 9

这里解释了为什么系统软重启

测试结果很明显了:成功触发了 Android PackageManagerService 一个可能的未知 bug,并且阻塞了 system_server
当然,这需要广泛的系统版本测试验证

回到开始前的那个问题:Android 系统能够接受安装的最长软件包名是多少?

好了,篇幅很长了,感谢你能看到这里👍👍

“GOODBYE!”


Android杂谈:当你尝试安装一个包名长度超过200字符的软件
http://example.com/2025/12/06/Android杂谈:当你尝试安装一个包名长度超过200字符的软件/
作者
FlyCome
发布于
2025年12月6日
许可协议