很多人都有用过开源的内存检测工具 LeakCanary,在 demo 应用中接入该库后,安装到手机里,发现手机桌面除了自己的项目外,会神奇地多出一个名叫 Leaks
的“应用”(如下图)。原来,在自有应用中发生如 Acitivty 泄漏时,LeakCanary 会及时生成并分析其泄漏路径保存起来。这个“新应用”相当于一个快捷入口,打开后便会有 demo 应用的历史内存泄漏信息,非常方便。
这种特殊的设计看起来好像是同时安装了两个不同的 app 在手机当中,但我们都知道,这是不可能的。仔细查看新的 Leaks
“应用”的信息,发现它其实就是 demo 应用,只是 demo 应用在桌面同时拥有了两个图标,Leaks
点击后会打开一个新的 Activity,专门用于展示内存泄漏的信息,只是体验起来像是多安装了一个应用而已。这种有趣的交互实现起来其实非常简单,只需要使用 <activity-alias>
标签即可。
<activity-alias>
<activity-alias>
,顾名思义,Activity 的别名,是在应用清单文件 AndroidManifest.xml
中申明,在 <application>
标签之下。
语法大致如下:
<activity-alias android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
android:name="string"
android:permission="string"
android:targetActivity="string" >
. . .
</activity-alias>
<activity-alias>
会包含一个目标 Activity,具有自己的一组 Intent 过滤器,Intent 过滤器可以指定 android.intent.action.MAIN
和 android.intent.category.LAUNCHER
标志,这样就会以一个新的图标入口出现在手机的桌面启动器当中。
示例如下:
<application
. . .>
. . .
<activity
android:name=".SecondActivity"/>
<activity-alias
android:name="com.jason.demo.dynamicshortcut.ShortcutLauncherActivity"
android:enabled="true"
android:icon="@mipmap/ic_launcher_alias"
android:label="ActivityAlias"
android:targetActivity=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
</application>
其中,android:targetActivity
指定所必须的打开的目标 Activity,对应着一个在 AndroidManifest.xml
中申明的 <activity>
。android:name
是别名的唯一名称,不引用实际类。android:icon
以及 android:label
指定一个新的图标和标签给用户。
申明后,便会在手机内看到两个应用图标入口,示例如下:
但体验下来会发现,主图标打开 Main Activity 后,alias 图标点击还是打开 Main Activity,是因为此时 Main Activity 和 Second Activity 有着一样的相似性。
taskAffinity
Activity 会继承为应用设置的相似性(taskAffinity
属性)。应用默认相似性的名称为 <manifest>
元素所设置的包名。具有同一相似性的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)。
因此,需要根据自身的需求,考虑对不同的 Activity 赋予不同的相似性。对于“新应用”的效果,则需要对 Second Activity 设置不同的相似性,示例如下:
<activity
android:name=".SecondActivity"
android:taskAffinity="com.jasonwu.${applicationId}" />
最终,“双应用”入口的效果就这样轻易实现啦:
本次的分享就到这啦,喜欢的话可以点个赞 👍 或关注呗。如有错误的地方欢迎大家在评论里指出。
附
另外,对于这些零碎的 Android 知识点,笔者从自身的经验出发,以文档的形式进行整理放在 Github 上,每周不定时更新,欢迎大家 star。