Android一个应用(APK)多个入口的实现方式整理
概要:
某些情况下,需要为apk设置多个执行入口,也就是安装后在应用程序列表中出现多个图标,各个图标是APP不同模块的入口点,并且各个模块运行在不同的进程中。
Android一个应用多个入口有以下三种实现方式;
第一种:使用intent-filter
第二种:使用process属性
第三种:使用别名(activity-alias)
1、方法一:直接在Activity节点中添加intent-filter
给相应的Activity增加如下代码:
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
2、方法二:使用Activity的属性process,不同的Activity是运行在不同的进程中
Activity有一个重要的属性process,这个属性是指定Activity运行时所在的进程。没有指定此属性的话,所有程序组件运行在应用程序默认的进程中,这个进程名跟应用程序的包名一致。在AndroidManifest.xml文件中所有组件元素的process属性能够为该组件设定一个新的默认值。但是任何组件都可以覆盖这个默认值,允许你将你的程序放在多进程中运行。如果这个属性被分配的名字以:开头,当这个activity运行时, 一个新的专属于这个程序的进程将会被创建。所以可以通过给每一个Activity指定标签、图标和进程名来区分不同的入口,具体实现如下:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:process=”:process.main”>
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivityB"
android:label="@string/app_nameB"
android:process=”:process.sub”
android:icon=”@drawable/icon1”
android:launchMode = “singleInstance”>
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
需要注意的是,为Activity指定process属性后,还必须为其指定launchMode为singleInstance,这样才有效。
3、方法三:使用activity-alias
activity-alias是android里为了重复使用Activity而设计的。
当在Activity的onCreate()方法里,执行getIntent().getComponent().getClassName();得到的可能不是这个Activity的名字,有可能是别名的名字
创建两个图标:
<activity
android:name=".MainActivityB"
android:exported="true"
android:label="@string/app_nameB">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity-alias
android:name="ActivityB_copy"
android:icon="@drawable/icon1"
android:screenOrientation="landscape"
android:targetActivity=".MainActivityB">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
创建一个图标:
<activity
android:name=".MainActivityB"
android:exported="true"
android:label="@string/app_nameB">
</activity>
<activity-alias
android:name="ActivityB_copy"
android:icon="@drawable/icon1"
android:screenOrientation="landscape"
android:targetActivity=".MainActivityB">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity-alias>
其中android:exported="true"表示允许别的app调用该activity。
这个应用会在桌面上建两个进入点,即建两个可以进入MainActivityB这个Activity的快捷图标。这时getIntent().getComponent().getClassName()得到的名字就不一样,一个是com.test.MainActivityB,一个是com.test.ActivityB_copy。
总结:上面三种实现方式其实原理都是一样的,都是为第二个Activity添加
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
"intent-filter为程序增加入口图标。
问题
· 因为多个图标共用一个包名,所以只要卸载一个程序,与这个APK包名相同的程序也都会在桌面上消失;
· 从其它应用跳转到该APK时,需要通过ACTION区分跳转到具体哪一个模块(比如从资源管理器选择一个数据时,到底打开哪一个应用,需要通过action加以区分);
· 由于多个图标、splash、标题等需要区分的资源都放在一个APK中,这增加了APK的大小。