问题背景:
因为目前很多IPTV的厂商+广电的要求,不允许用户自己替换自己的launcher,为了保证利益,强行推广自己的launcher,对播控平台的掌控,于是就必须要求芯片原厂提供turnkey方案时符合其要求。下面用Android 5.1.1来举例说明,理论上AN的版本对此模块改动差异不太多。
Google官方Android原生Launcher设置
Launcher是Android系统的桌面、是android系统的主要组件。android系统允许存在多个Launcher并设置默认主界面。
应用程序作为Home(主界面)需在Activity的intent-filter节点中添加如下内容
|
|
当系统中存在多个Home app且没有设置默认,用户点击Home键会弹出如下图所示的界面(图一):
用户可以选择“只有一次”或者“总是”来启动选择的APP
一般情况下android中只会存在一个Home APP,系统启动后会直接启动此APP为默认,不需要用户选择。但是当系统中存在多个Home APP时,系统第一次启动就会弹出上图所示界面,让用户选择其中一个APP作为主屏幕应用,如果用户通过“始终”确认会设置选择的APP为默认的Home,用户通过“仅此一次”则此次以选择的APP为Home,再次按home键还是会弹出选择窗口.
针对广电总局播控客制化方案
针对上图,思考一下,可以采用两种方案:
- 让google原生态中的选框自动选中并且自动进入,这样就符合我们的需求了
- 直接清除launcher选择的堆栈,让home的堆栈里面永远只保留我们需要的那个,这个是受Android原生code,AMS启动home activity启发
方案一
根据操作流程分析code flow,两者互相糅合,理清问题的关键。
从上面弹出的选择默认主界面的界面入手,通过追踪发现上述界面是一个Activity,Activity代码路径frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
ResolverActivity分析
此Activity会获取系统中所有的Home app,并根据系统的设置情况显示如上界面。此类中有一个内部类ResolveListAdapter该类继承自BaseAdapter,该类是Home app选择界面的数据适配器。
ResolveListAdapter会在ResolverActivity的onCreate方法中被初始化并会传入一个ResolveInfo类型的List,ResolveListAdapter根据会传入的List初始化一个List mList ,用户的点击事件都会在ResolveListAdapter获取数据。
用户点击”ALWAYS”的事件发生在ResolverActivity的onButtonClick 方法中,此方法会获取选中的Item的position、或者获取用户上一次启动的Home app的,mAlwaysUseOption代表用户选中的是否为历史选择(如2图中的Launcher3),并调用startSelected。
|
|
StartSeletced中通过ResolveListAdapter获取选择的item代表的Home app。并且finish此activity
onIntentSelected会根据传入的ResolveInfo设置默认的Home,并根据Intent跳转到相应界面,onIntentSelected的代码在这里就不列出。
|
|
ResolveListAdapter的相关代码
|
|
解决措施
扯了半天了,分析完谷歌的原生流程,现在终于开始进行客制化的修改了。进入正题:
此Activity的onCreate方法中判断是否为第一次启动,如果是则调用startSelected方法设置默认Home app。
默认Home app的从ResolveListAdapter中获取,所以在ResolveListAdapter中添加getDefaultHomePosition(String packageName)
方法,用于获取默认home app在List 中的位置,代码如下:
|
|
在ResolverActivity中添加设置默认app的方法setupDefaultLauncher(),代码如下:
|
|
为了保证mAdapter被初始化 setupDefaultLauncher()的调用添加到ResolverActivity的onCreate函数中,代码如下:
|
|
通过以上方法即可实现设置默认home的功能
方案二【优势,可以通过长按home按键进行切换】
ActivityManagerService.java在每次启动时执行,每次都默认启动设定的launcher,当然,如果设定的launcher存在的话,设置其他的launcher为默认会无效,因为重新启动时setDefaultLauncher()会将当前默认launcher清除。只有在卸载了设定默认启动的launcher后才能设置其他launcher为默认启动.
修改AMS:
|
|
新增客制化的method
|
|
然后在ActivityManagerService类中的
boolean startHomeActivityLocked()
方法第一行调用上面添加的
setDefaultLauncher()
|
|
添加后的方法全部内容如上,重新编译android,烧录,开机就能够自动进入自定义的launcher
可以通过系统设置取消该launcher的默认设置,取消之后按home键会弹出launcher选择提示框
frameworks\base\core\java\com\android\internal\app\ResolverActivity.java
ResolverActivity类就是选择打开方式的弹出框
How to set default app launcher programmatically?
How to reset default launcher/home screen replacement?