第 23 章 深入学习 intent 和任务 (选讲)
本章将使用隐式intent,创建一个启动器应用来替换Android默认的启动器应用。
23.1 创建 NerdLauncher 项目
使用与创建CriminalIntent应用相同的设置,创建一个新项目,如图23-1所示。项目名称处填入NerdLauncher,包名处填入com.jet.nerdlauncher。
图23-1 创建NerdLauncher项目
单击Next按钮,选择EmptyActivity,创建一个名为NerdLauncherActivity的全新activity,最后单击Finish按钮完成项目的创建。
NerdLauncherActivity将会继承SingleFragmentActivity类,因此,首先需要将它添加到当前项目中。
另外我们还需要activity_fragment.xml布局。因此,再将CriminalIntent项目中的res/layout/activity_fragment.xml文件复制到NerdLauncher项目的res/layout目录中。
NerdLauncher将以列表的形式显示设备上的应用。用户点击任意列表项将启动相应的应用。以下是该应用涉及的对象。
NerdLauncherFragment是ListFragment的子类,它的视图默认为ListFragment自带的ListView视图。
以android.support.v4.app.ListFragment为父类,创建一个名为NerdLauncherFragment的新类。暂时先不理会新建的空类。
打开NerdLauncherActivity.java文件,修改NerdLauncherActivity的超类为SingleFragmentActivity类。然后删除默认的模板代码,并覆盖createFragment()方法返回一个NerdLauncherFragment,如代码清单23-1所示。
代码清单23-1 另一个SingleFragmentActivity(NerdLauncherActivity.java)
23.2 解析隐式 intent
NerdLaucher应用会以列表的形式向用户展示设备上的应用。要实现该功能,它将发送一个所有应用的主activity都会响应的隐式intent。
在NerdLauncherFragment.java中,覆盖onCreate(Bundle)方法创建一个隐式intent。然后,从PackageManager中获取匹配intent的activity列表。当前,先以日志记录下PackageManager返回的activity数,如代码清单23-2所示。
代码清单23-2 向PackageManager查询activity数(NerdLauncherFragment.java)
运行NerdLauncher应用,在LogCat日志窗口查看PackageManager返回的activity数目。
接下来,我们需要将查询到的activity标签显示在NerdLauncherFragment的ListView视图中。activity的标签即用户可以识别的显示名称。既然查询到的activity都是启动activity,标签名通常也就是应用名。
在PackageManager返回的ResolveInfo对象中,可以获取activity的标签和其他一些元数据。
首先,添加如下代码对PackageManager返回的ResolveInfo对象按标签(使用ResolveInfo.loadLabel(...)方法)的字母顺序进行排序,如代码清单23-3所示。
代码清单23-3 按字母顺序对activity进行排序(NerdLauncherFragment.java)
然后,为创建显示activity标签名的简单列表项视图,还需创建一个ArrayAdapter并设置给ListView,如代码清单23-4所示。
代码清单23-4 创建一个适配器(NerdLauncherFragment.java)
运行NerdLauncher应用。我们将看到一个显示了activity标签的ListView视图,如图23-2所示。
图23-2 设备上的全部activity
23.3 在运行时创建显式 intent
接下来就是实现用户点击任一列表项时,启动该列表项的activity。我们将使用显式intent来启动activity。
要创建显式intent,还需从ResolveInfo对象中获取更多数据信息。特别是需要知道activity的包名与类名。这些信息可以从ResolveInfo对象的ActivityInfo中获取。(从ResolveInfo类中还可以获取其他哪些信息,具体请查阅该类的参考文档。)
在NerdLauncherFragment.java中,覆盖onListItemClick(...)方法,取得列表项的ActivityInfo对象。然后,使用ActivityInfo对象中的数据信息,创建一个显式intent并启动目标activity,如代码清单23-5所示。
代码清单23-5 实现onListItemClick(...)方法(NerdLauncherFragment.java)
从以上代码可以看到,作为显式intent的一部分,我们还发送了ACTION_MAIN操作。发送的intent是否包含操作,对于大多数应用来说没有什么差别。不过,有些应用的启动行为可能会有所不同。取决于不同的启动要求,同样的activity可能会显示不同的用户界面。开发人员最好能明确启动意图,以便让activity完成它应该完成的任务。
运行NerdLauncher应用并尝试启动一些应用。