Android 系统开发 - 选择并启动默认 Launcher,高级安卓开发技术
//得到图标 val icon = ri.loadIcon(packageManager)//得到应用名称 val appName = ri.loadLabel(packageManager).toString()
//封装应用信息对象 val appInfo = AppInfo(icon, appName, packageName)//添加到 listlist.add(appInfo)}return list}
使用 PackageManager 提供的 queryIntentActivities 方法就可以获取所有 Launcher 应用,原生设置中也有 Activity 声明了 HOME 属性,在这里就把它屏蔽掉。
默认选择 Launcher3 应用为默认启动
private val DEFAULT_LAUNCHER = "my_default_launcher"defaultLauncher = Settings.Global.getString(contentResolver, DEFAULT_LAUNCHER)if (defaultLauncher.isNullOrEmpty()) {defaultLauncher = "com.android.launcher3"Settings.Global.putString(contentResolver, DEFAULT_LAUNCHER, defaultLauncher)}
当选择另一个应用,就把选择应用的包名设置到 Settings.Global 中。
这样应用选择页面完成,也设置了一个全局的参数提供给系统。
启动
最开始提到了 Launcher 选择弹窗,我们就考虑在这里做点事,把弹窗的逻辑给跳过,就可以实现默认启动。
弹窗源码位于frameworks/base/core/java/com/android/internal/app/ResolverActivity.java
在这里就不具体分析源码了,就看关键部分
public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,List<ResolveInfo> rList, boolean alwaysUseOption) {// The last argument of createAdapter is whether to do special handling// of the last used choice to highlight it in the list. We need to always// turn this off when running under voice interaction, since it results in// a more complicated UI that the current voice interaction flow is not able// to handle.mAdapter = createAdapter(this, payloadIntents, initialIntents, rList,mLaunchedFromUid, alwaysUseOption && !isVoiceInteraction());
final int layoutId;if (mAdapter.hasFilteredItem()) {layoutId = R.layout.resolver_list_with_default;alwaysUseOption = false;} else {layoutId = getLayoutResource();}mAlwaysUseOption = alwaysUseOption;
int count = mAd
《Android 学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
apter.getUnfilteredCount();if (count == 1 && mAdapter.getOtherProfile() == null) {// Only one target, so we're a candidate to auto-launch!final TargetInfo target = mAdapter.targetInfoForPosition(0, false);if (shouldAutoLaunchSingleChoice(target)) {safelyStartActivity(target);mPackageMonitor.unregister();mRegistered = false;finish();return true;}}if (count > 0) {// add by liuwei,if set my_default_launcher,start defaultString defaultlauncher = Settings.Global.getString(this.getContentResolver(), "my_default_launcher");
final TargetInfo defaultTarget = mAdapter.targetInfoForDefault(defaultlauncher);if(defaultTarget != null){safelyStartActivity(defaultTarget);mPackageMonitor.unregister();mRegistered = false;finish();return true;}//endsetContentView(layoutId);mAdapterView = (AbsListView) findViewById(R.id.resolver_list);onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption);} else {setContentView(R.layout.resolver_list);
final TextView empty = (TextView) findViewById(R.id.empty);empty.setVisibility(View.VISIBLE);
mAdapterView = (AbsListView) findViewById(R.id.resolver_list);mAdapterView.setVisibility(View.GONE);}return false;}
在 configureContentView 中判断 launcher 应用个数,如果为 1,则直接启动,finish 当前页面。下面判断 count>0,我们就在这里面增加自己的逻辑,获取配置的 Settings.Global 参数,再去 Adapter 中判断是否有应用包名和参数匹配,如果有就 safelyStartActivity(),关闭弹窗。如果没有匹配包名,就走正常流程,弹窗提示用户。
mAdapter.targetInfoForDefault 函数是在 public class ResolveListAdapter extends BaseAdapter
中增加函数
最后
针对 Android 程序员,我这边给大家整理了一些资料,包括不限于高级 UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter 等全方面的 Android 进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
往期 Android 高级架构资料、源码、笔记、视频。高级 UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的 Android 进阶实践技术,群内还有技术大牛一起讨论交流解决问题。


评论