项目背景需求:
1、我们的系统要固定一个HOME应用,并且用户无法通过安装其他Launcher3应用来更改;
2、在生产过程中,通过不同的初始化,进入不同的Launcher应用;
根据以上的需求,我们先来理一理Launcher应用的流程:
1、Android在进行各种服务启动之后运行
((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()
在systemReady后开始开始启动Launcher。
frameworks\base\services\Java\com\android\server\am\ActivityManagerService.java
- 8422 public void systemReady(final Runnable goingCallback) {
- 8423 // In the simulator, startRunning will never have been called, which
- 8424 // normally sets a few crucial variables. Do it here instead.
- .........................
- 8594 resumeTopActivityLocked(null);
- }
- 2576 private final boolean resumeTopActivityLocked(HistoryRecord prev) {
- 2577 // Find the first activity that is not finishing.
- 2578 HistoryRecord next = topRunningActivityLocked(null);
- 2579
- 2580 // Remember how we'll process this pause/resume situation, and ensure
- 2581 // that the state is reset however we wind up proceeding.
- 2582 final boolean userLeaving = mUserLeaving;
- 2583 mUserLeaving = false;
- 2584
- 2585 if (next == null) {
- 2586 // There are no more activities! Let's just start up the
- 2587 // Launcher...
- 2588 return startHomeActivityLocked();
- 2589 }
frameworks\base\services\java\com\android\server\am\ActivityManagerService.java
- 2457 private boolean startHomeActivityLocked() {
- 2458 if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
- 2459 && mTopAction == null) {
- 2460 // We are running in factory test mode, but unable to find
- 2461 // the factory test app, so just sit around displaying the
- 2462 // error message and don't try to start anything.
- 2463 return false;
- 2464 }
- 2465 Intent intent = new Intent(
- 2466 mTopAction,
- 2467 mTopData != null ? Uri.parse(mTopData) : null);
- 2468 intent.setComponent(mTopComponent);
- 2469 if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
- 2470 intent.addCategory(Intent.CATEGORY_HOME);
- 2471 }
frameworks/base/core/java/android/content/Intent.java
- 1881 public static final String CATEGORY_HOME = "android.intent.category.HOME";
根据上面代码可知,在寻找Launcher的时候是根据HOME的filter(在Manifest中定义的<category android:name=”android.intent.category.HOME” />)来过滤。 然后根据filter出来的HOME来启动,如果只有一个HOME,则启动这个HOME,如果用户自己装了HOME,那就会弹出来一个列表供用户选择。
了解了以上流程后,现在我的思路就比较简单:
1、在Intent.java中定义一个获取我们自己的CATEGORY_HOME的接口:
public static final String CATEGORY_MYHOME = "android.intent.category.MYHOME";
private static String mMyCategoryHome=CATEGORY_MYHOME;
void setMyCategoryHome(String str){
mMyCategoryHome = str;
}
String getMyCategoryHome(){
return CATEGORY_MYHOME;
}
2、接下来,搜索系统中所有用到Intent.CATEGORY_HOME的位置,改为使用Intent.getMyCategoryHome()来获取即可;
3、对应将我们自己的Launcher中的
- <category android:name="android.intent.category.HOME" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="android.intent.category.MYHOME" />
- <category android:name="android.intent.category.DEFAULT" />
即可;
4、对于需要多种状态下对应不同的Launcher的情况,可以通过调用setMyCategoryHome()接口灵活的进行切换,匹配不同的定制Launcher应用