再探Android应用双开
前言
之前折腾原生系统多用户的时候,当时的需求是能多开就行,所以在网上草草搜了搜,找到一个方法就直接用了。虽然确实凑合能用,但是那个多开一下就把系统自带App全部同时多开了一份,看着确实不舒心。而且在体验了一段时间原生后,我觉得原生其实并不太适合作为主力使用,其原因主要有三大,一是过于简洁很多实用功能它没有,二是糟糕的后台管理,而这三就是更新维护实在不行,一个好的ROM真的很难找,有时连一些官方原生ROM都存在bug(点名批评PixelOS,Redme Note 12 Turbo 的ROM屏幕无法自动调光,只有亮屏那一次是自动的,后续不会根据环境光线变化)。于是乎,我换了一台澳版三星s22u。
三星的好真的一言难尽(我以后大概再也不会用其他牌子作我的主力机了),但我们还是把主题放回应用双开上。三星自带的所谓的“应用双开”,只有社交应用,毕竟人家就叫“Dual Messenger”。虽然看起来只能开指定应用有些鸡肋,但实际上我却要感谢他给我打开了一个突破口。
分析三星多开原理
用户类型
我们之前已经知道多开应用就是利用了Android自带的多用户功能,而原生系统上工作用户的多开表现和三星自带多开功能的表现却大不相同。工作用户的“多开”,实际上就是给不同用户各安装了一个相同包名的App罢了,它们并没有共用同一个Apk包,也就是说,这两个包是分开独立的。从而也就出现了主用户卸载了某一个App,而在工作用户上的多开版本并没有被同时卸载,以及主用户的某一App更新了,多开的App还是旧版本。这与我们的预期是大不相同的。正常来说,多开应用应该共用一个包,主App卸载或者更新,多开App也能被同步卸载或更新。这里,我们本能的会去想多开应用用户的区别,也就是用户类型。
通过查阅官方文档Android支持多用户-用户类型可知,Android用户类型有以下几种。
- android.os.usertype.full.SYSTEM
- android.os.usertype.full.SECONDARY
- android.os.usertype.full.GUEST
- android.os.usertype.full.DEMO
- android.os.usertype.full.RESTRICTED
- android.os.usertype.profile.MANAGED
- android.os.usertype.system.HEADLESS
- android.os.usertype.profile.CLONE
再去看之前的指令,不难发现,我们之前创建的“工作用户”应该为android.os.usertype.profile.MANAGED
类型用户
在这里需要注意一下,CLONE
和MANAGED
这两个类型前面都有一个profile
,之后有用。
我们可以使用adb的下述指令,查看手机上目前运行的用户及其类型。
1 | adb shell dumpsys user |
在我的三星手机上得到了以下输出
1 | Users: |
可以发现三星自带的多开功能使用了android.os.usertype.profile.CLONE
类型用户。
共用Apk包
实际上adb shell pm
里是有一个叫install-existing
的指令,字面意思理解就好喽,这就是共用包的原理了。具体用法在后面。
总结多开流程
创建CLONE用户
首先在这里给出adb shell pm create-user
的用法。
1 | adb shell pm create-user [--profileOf USER_ID] [--managed] [--restricted] [--ephemeral] [--guest] [--pre-create-only][--user-type USER_TYPE] USER_NAME |
这里就要用到之前提到的,CLONE
和MANAGED
这两个类型前面都有一个profile
。还记得之前创建“工作用户”的时候有一个--profileOf 0
的参数吗?这就是依赖于用户0,也就是我们的SYSTEM主用户,来创建一个多开用户。
这里也要提一嘴SECONDARY
用户,这个用户就是我们可以在手机系统里操作的创建多用户的用户类型,它就是一个普通用户,没有admin权限(或者说SYSTEM权限?)。貌似是因为这个原因,上面说的--profileOf 0
参数似乎也只能依赖于用户0,即SYSTEM
用户,而不能依赖一个SECONDARY
用户。也就是说,现阶段不能给SECONDARY
用户创建CLONE
或MANAGED
用户,SECONDARY
用户无法多开应用。
CLONE
用户创建命令如下,其中,最后的CloneUser
为用户名称,可自行更改。
1 | adb shell pm create-user --profileOf 0 --user-type android.os.usertype.profile.CLONE CloneUser |
创建以后会返回此用户id,一般为10。可以用adb shell pm list users
查看所有用户id。然后启动此用户。
1 | adb shell am start-user 10 |
完成后你就成功的创建了一个CLONE
用户了。在原生系统上,你依然会看到多出来一个“工作账户”,不过这个“工作账户”不会像之前一样把所有系统自带App都给你复制一份,在我这里只有3个系统自带App被复制了,在可以接受的范围内,并且此时你尝试“暂停工作应用”的时候会发现这个“工作账户”是无法关闭的。
如果你想删除多开用户,使用以下指令。
1 | adb shell pm remove-user 10 |
共用Apk包多开应用
使用adb shell pm list packages
列出所有包名,找到你想多开的App的包名,替换以下指令的包名就行了。如果你的用户id不是10,记得也要改成相应的。
1 | adb shell pm install-existing --user 10 com.android.vending |
这个时候你就可以去试试删掉主App了,手机会提示此App的Clone版本也会被删除,这就符合我们的预期了。
结语
应用多开到这里基本上以及满足个人使用需求了,但是还有一些问题是值得再探索的。例如三星的“安全文件夹”,它可以让应用再多开一份。以及如何创建另一个SYSTEM
用户或者一个具有admin权限的用户,来实现多个实体用户多开应用。目前知道的是无法使用adb完成这些任务,可能需要使用UserManager相关的Android API了,这个我还不会用,有时间再折腾吧。
另外就是,细心的可能会发现,在我使用adb shell dumpsys user
查看到的三星多开用户里有一个Flags: 536875024 (DUALAPP_PROFILE|INITIALIZED|PROFILE)
的标志位,如果你用这个指令去看用我上面内容开出来的多开用户会发现它的标志位是Flags: 4112 (INITIALIZED|PROFILE)
,没有DUALAPP_PROFILE
这个flags,这个可能也是要通过系统设置API或设备管理API来实现的,等我后面慢慢研究吧。
参考文章
Android 多用户介绍(multiple users)
Android 11多用户功能之理论篇(一)
How to find out currently running user name/ID from ADB
ChatGPT生成内容1
ChatGPT生成内容2