我把这个默认启动器起名为NewLauncher,它的功能是能够以列表的形式展现你设备上的可启动应用(可启动应用是指用户点击主屏幕或启动器界面上的图标就能打开的应用),比如微信,微博,QQ等等。
使用PackageManager可获取所有可启动主Activity,可启动主Activity都带有包含MAIN操作(action)和LAUNCHER类别(category)的intent过滤器(intent-filter)。打开任何一个应用项目AndroidManifest.xml文件,可以看到
获取方法如下
private void setupAdapter(){
Intent startupIntent = newIntent(Intent.ACTION_MAIN);
startupIntent.addCategory(Intent.CATEGORY_LAUNCHER);
/**使用了Fragment,所以调用getActivity()获取当前上下文Context**/
final PackageManager packageManager = getActivity().getPackageManager();
/**获取匹配的activity列表**/
List<ResolverInfo> activities = packageManager.queryIntentActivities(startupIntent,0);
}
在PackageManager返回的ResolveInfo对象中,可以获取activity标签和其他一些元数据。首先,对ResolveInfo对象中的activity标签按首字母排序。
Collections.sort(activities, new Comparator() {
@Override
public intcompare(ResolveInfo o1,ResolveInfo o2) {
PackageManager packageManager1 = getActivity().getPackageManager();
return String.CASE_INSENSITIVE_ORDER.compare(
o1.loadLabel(packageManager1).toString(),
o2.loadLabel(packageManager1).toString());
}
});
要创建启动activity的显示intent,需要从ResolveInfo对象中获取activity的包名与类名,这些信息可以从ResolveInfo对象的ActivityInfo中获取。下面创建一个显示intent并启动目标activity
@Override
public void onClick(View v) {
/**mResolveInfo就是之前获取的activities**/
ActivityInfo activityInfo = mResolveInfo.activityInfo;
Intent i = newIntent(Intent.ACTION_MAIN)
.setClassName(activityInfo.applicationInfo.packageName, activityInfo.name)
/**为了在启动新activity时启动新任务,需要为intent添加一个标志
FLAG_ACTIVITY_NEW_TASK标志控制每个activity仅创建一个任务**/
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
作为显示intent的一部分,我们还发送了ACTION_MAIN操作。发送的intent是否包含操作(action),对于大多数应用来说没有什么差别,不过,有些应用的启动行为可能会有所不同。取决与不同的启动要求,同样的activity可能会显示不同的用户界面。开发人员最好能明确启动意图,以便让activity完成它应该完成的任务。
通常的显示intent创建一般使用接受Context和Class对象的Intent构造方法
public Intent(Context packageContext, Class<?> cls)
该构造方法使用传入的参数来获取Intent需要的ComponentName,ComponentName由包名和类名共同组成。该构造方法会通过Activity类自行确定全路径包名。也可以自己通过包名和类名创建ComponentName,然后使用下面的Intent方法创建显示intent
public Intent setComponent(Component component)
不过,setClassName(...)方法能够自动创建ComponentName,需要实现的代码相对较少。
public Intent setClassName(String packageName, String className)
通过添加HOME和DEFAULT类别定义,NewLauncher应用的activity会成为可选的主界面,进入设置-->应用管理-->选择默认应用设置-->桌面-->选择NewLauncher即可。不用担心,之后再通过相同的操作便可修改回来,别忘了,我们可以通过NewLauncher启动设置。
有关Fragment和RecyclerView的使用并没有本文阐述,因为目前为止,这个应用都比较简单,有兴趣的朋友可以在这个链接查看源代码。
该应用还有很多可以扩展的地方,希望有一天可以自己做出一个觉得可以替代系统桌面的应用启动器。