安卓权威编程指南-笔记(第22章 深入学习intent和任务)
本章,我们会使用隐式intent创建一个替换android默认启动器的应用。名为NerdLauncher。
NerdLauncher应用能列出设备上的其他应用,点选任意列表项会启动相应应用。
1. 解析隐式intent
可启动的主 activity 都有包含 MAIN 操作和 LAUNCHER 类别的 intent 过滤器,一般在 AndroidManifest.xml 中的形式如下:
<activity android:name=".XXXXActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
可以建立一个Intent,然后从PackageManager那里获取匹配它的所有activity。
Intent startupIntent = new Intent(Intent.ACTION_MAIN);
startupIntent.addCategory(Intent.CATEGORY_LAUNCHER); PackageManager pm = getActivity().getPackageManager(); //查询包含Main操作和LAUNCHER类别的activity总数
List<ResolveInfo> activities = pm.queryIntentActivities(startupIntent, 0); Log.i(TAG, "Found " + activities.size() + "activities");
在CriminalIntent应用中,为使用隐式intent发送crime报告,我们先创建隐式intent,再将其封
装在选择器intent中,最后调用 startActivity(Intent) 方法发送给操作系统:
Intent i = new Intent(Intent.ACTION_SEND);
... // Create and put intent extras
i = Intent.createChooser(i, getString(R.string.send_report));
startActivity(i);
这里没有使用类似的处理方式。原因是MAIN/LAUNCHER intent过滤器可能无法与通过 startActivity(...) 方法发送的 MAIN/LAUNCHER 隐式intent相匹配。
startActivity(Intent)意味着启动匹配隐式intent的默认activity。调用 startActivity(Intent) 方法(或 startActivity-ForResult(...) 方法)发送隐式intent时,操作系统会悄悄为目标intent添加 Intent.CATEGORY_DEFAULT 类别。
因此,如果希望intent过滤器匹配 startActivity(...) 方法发送的隐式intent,就必须在对应的intent过滤器中包含 DEFAULT 类别。
然而定义了 MAIN/LAUNCHER intent过滤器的activity是应用的主要入口点。它只负责做好作为应用主要入口点要处理的工作。它通常不关心自己是否为默认的主要入口点,所以可以不包含CATEGORY_DEFAULT 类别。
所以,我们转而使用intent直接向PackageManager 查询带有 MAIN/LAUNCHER intent过滤器的activity。
2. 在运行时创建显示intent
要创建启动activity的显示intent,需要从ResolveInfo对象中获取activity的包名和类名。这些信息可以从ResloveInfo对象的ActivityInfo中获取。
接下来实现用户点击任意列表项,启动对应的activity,我们需要使用显式intent来启动activity。
设置列表项的点击事件
@Override
public void onClick(View v){
ActivityInfo activityInfo = mResloveInfo.activityInfo;
/*
* 发送了ACTION_MAIN操作。发送的intent是否包含操作,对大多数app来说没什么区别。
* 不过,有些应用的启动行为可能会有所不同。取决于不同的启动要求,同样的activity可能会显示不同的用户界面。开发人员最好能明确启动意图,以便让activity完成它应该完成的任务。
*/
Intent i = new Intent(Intent.ACTION_MAIN)
.setClassName(activityInfo.applicationInfo.packageName,activityInfo.name); startActivity(i);
}
在使用包名和类名创建显式intent时,我们使用了以下intent方法:
public Intent setClassName(String packageName, String className);
此方法和Intent构造方法public Intent(Context packageContext, Class<?> cls)结果相同,都是为 Intent 添加了 ComponentName。
也可以自己通过包名和类名创建 ComponentName ,然后使用下面的 Intent 方法创建显式:
public Intent setComponent(ComponentName component)
不过setClassName方法能够自动创建组建名,所以使用该方法需要的实现代码相对较少。
2.任务与后退栈
任务是用户比较关心的activity栈。栈底部的activity通常称为基activity。用户可以看到栈顶的activity。用户点击后退键时,栈顶activity会弹出栈外。如果当前屏幕上显示的是基activity,点击后退键,系统会退回主屏幕。在当前任务中启动activity的好处是,用户可以在任务内而不是在应用层级间导航返回.默认情况下,新 activity 都在当前任务中启动。在 CriminalIntent 应用中,无论何时启动新 activity,它都会被添加到当前任务中。即使要启动的 activity 不属于本应用,它同样也在当前任务中启动。
2.1在任务间切换
在不影响各个任务状态的情况下,overview screen可以让我们在任务间切换。例如,如果进入联系人应用,然后切换到Twitter应用查看信息,这时我们就启动了两个任务。如果再切换回联系人应用,我们在两项任务中所处的状态位置都会被保存下来。
清除任务就是从应用回退栈中清除所有activity。
2.2 启动新任务
我们需要NerdLauncher在新任务中启动activity,这样,点击NerdLauncher启动器中的应用列表项可以让应用拥有自己的任务,用户因此可以在运行的应用间自由切换。
为了在启动新activity时启动新任务,需要为intent添加一个标识。
Intent i = new Intent(Intent.ACTION_MAIN)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.setClassName(activityInfo.applicationInfo.packageName,activityInfo.name);
2.3 使用 NerdLauncher 应用作为设备主屏幕
只需要在项目的配置文件AndroidManifest.xml,对找代码清单向主过滤器添加以下节点
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
通过添加 HOME 和 DEFAULT 类别定义,NerdLauncher应用的activity会成为可选的主界面。
3. 进程与任务
进程是操作系统创建的,供应用对象生存以及应用运行的地方。
每一个activity实例都仅存在于一个进程和一个任务中,这也是进程与任务的唯一相似之处。任务只包含activity,这些activity通常来自于不同的应用。而进程则包含了应用的全部运行代码和对象。
进程与任务很容易让人混淆,主要原因在于它们不仅在概念上有某种重叠,而且通常都是以其所属应用的名称被人提及的。我们以短信应用和联系人应用为例,看看以下具体场景就会明白了(首先清理掉 overview screen 中的所有任务)。
- 打开短信应用:这里我们新建了一个任务,也新建了一个短信的进程
- 点击选择收件人,这会打开联系人应用让我们选择目标联系人: 我们仍然只有一个短信任务,其中包含了两个应用的 activity,也就是说新建了联系人的进程,这样便有了两个进程
- 直接切回主界面(而不是后退回去),打开联系人应用:这样,我们多了一个联系人的任务,并且在联系人进程中新增了一个联系人 activity 的实例。
此外,Android 并没有提供方法用来终止任务,不过,我们可以终止进程。应用商店中那些宣称自己是任务终止器的应用,实际上都是进程终止器。
4. 并发文档
在Lollipop设备上,对以 android.intent.action.SEND 或 action.intent.action.SEND_MULTIPLE 操作启动的activity,隐式intent选择器会创建独立的新任务。(在旧设备上,Gmail的activity是直接添加给CriminalIntent应用任务的。)
这种现象要归因于Lollipop中叫作并发文档(concurrent documents)的新概念。
有了并发文档,我们就可以在应用运行时动态创建任意数目的任务。在Lollipop之前,应用任务只能预先定义好,而且还要在manifest文件中明确指定。
在Lollipop设备上,如果需要应用启动多个任务,可采用两种方式:给intent打上 Intent.FLAG_ACTIVITY_NEW_DOCUMENT 标签,再调用 startActivity(...) 方法;或者在manifest文件中,为activity设置如下 documentLaunchMode :
<activity
android:name=".CrimePagerActivity"
android:label="@string/app_name"
android:parentActivityName=".CrimeListActivity"
android:documentLaunchMode="intoExisting" />
使用上述方法,一份文档只会对应一个任务。(如果发送带有和已存在任务相同数据的intent,系统就不会再创建新任务。)如果无论如何都想创建新任务,那就给intent同时打上Intent.FLAG_ACTIVITY_NEW_DOCUMENT 和 Intent.FLAG_ACTIVITY_MULTIPLE_TASK 标签,或者把manifest文件中的 documentLaunchMode 属性值修改为 always 。
安卓权威编程指南-笔记(第22章 深入学习intent和任务)的更多相关文章
- 安卓权威编程指南 -笔记(19章 使用SoundPool播放音频)
针对BeatBox应用,可以使用SoundPool这个特别定制的实用工具. SoundPool能加载一批声音资源到内存中,并支持同时播放多个音频文件.因此所以,就算用户兴奋起来,狂按按钮播放全部音频, ...
- 安卓权威编程指南 -笔记(18章 处理assets)
resources资源可以存储声音文件,但当处理多个音乐文件时,效率会很低. assets可以被看作随应用打包的微型文件系统,支持任意层次的文件目录结构.类似游戏这样需要加载大量图片和声音资源的应用通 ...
- 安卓权威编程指南-笔记(第21章 XML drawable)
在Andorid的世界里,凡事要在屏幕上绘制的东西都可以叫drawable,比如抽象图形,Drawable的子类,位图图形等,我们之前用来封装图片的BitmapDrawable就是一种drawable ...
- 安卓权威编程指南-笔记(第27章 broadcast intent)
本章需求:首先,让应用轮询新结果并在有所发现时及时通知用户,即使用户重启设备后还没有打开过应用.其次,保证用户在使用应用时不出现新结果通知. 1. 一般intent和broadcast intent ...
- 安卓权威编程指南-笔记(第23章 HTTP与后台任务)
1. 网络连接基本 //通过指定URL获取原始数据,并返回一个字节流数组. public byte[] getUrlBytes(String urlSpec)throws IOException{ / ...
- 安卓权威编程指南-笔记(第24章 Looper Handler 和 HandlerThread)
AsyncTask是执行后台线程的最简单方式,但它不适用于那些重复且长时间运行的任务. 1. Looper Android中,线程拥有一个消息队列(message queue),使用消息队列的线程叫做 ...
- 安卓权威编程指南 挑战练习 25章 深度优化 PhotoGallery 应用
你可能已经注意到了,提交搜索时, RecyclerView 要等好一会才能刷新显示搜索结果.请接受挑战,让搜索过程更流畅一些.用户一提交搜索,就隐藏软键盘,收起 SearchView 视图(回到只显示 ...
- 安卓权威编程指南 - 第五章学习笔记(两个Activity)
学习安卓编程权威指南第五章的时候自己写了个简单的Demo来加深理解两个Activity互相传递数据的问题,然后将自己的学习笔记贴上来,如有错误还请指正. IntentActivityDemo学习笔记 ...
- 安卓权威编程指南 挑战练习(第26章 在 Lollipop 设备上使用 JobService)
26.11 挑战练习:在 Lollipop 设备上使用 JobService 请创建另一个 PollService 实现版本.新的 PollService 应该继承 JobService 并使用 Jo ...
随机推荐
- VS2015提示资源视图加载失败
关闭VS打开的resource,h这个文件,然后重启VS就行了.网上有很多其他的说法,我本地尝试始终不行,暴力解决. 今天发现,其实是不用重启的,直接对rc文件右键保存,就可以正常打开了......
- Sqlite教程(1) SQLiteOpenHelper
首先,创建DbHelper对象,继承SQLiteOpenHelper. Configuration是自行创建的工具类,里面都是App的一些环境设置. public class DbHelper ext ...
- 吴裕雄--天生自然python机器学习:基于支持向量机SVM的手写数字识别
from numpy import * def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i ...
- 染色dp(确定一行就可行)
题:https://codeforces.com/contest/1027/problem/E 题意:给定n*n的方格,可以染黑白,要求相邻俩行”完全“不同或完全相同,对于列也是一样.然后限制不能拥有 ...
- pytorch源码解析-动态接口宏
动态库接口定义: gcc: 定义在动态库的显示属性: 作用对象: 函数.变量.模板以及C++类 default: 表示在动态库内可见 hidden: 表示不可见 #define EXPORT __at ...
- html5页面编码如何确定
页面乱码问题建站学之前曾经多次发教程说明,对于新的html5来说我们的编码要如何做才能解决乱码问题呢?作为一个前端工程师,你是如何指定一个页面的编码的呢?你知道浏览器是怎么识别编码的吗? 首先,一个很 ...
- 复习break、continue、while、do-while的运用
一.复习: 循环.反复执行某段语句一种语法形式. 1.基本语法: for( 初始条件 ; 循环条件 ; 状态的改变 ) { 循环体 } 循环的四要素. 循环的执行过程.初始条件--循环条件--循环体- ...
- Linux下rabitMq的部署(源码安装)
简版yum安装:https://www.jianshu.com/p/46c22834aad5 一.环境安装 1,安装预环境 通过yum安装以下组件,运行命令: [root@rabbitmqserver ...
- Mysql分区,分库和分表
作者说的非常清楚了,感谢.地址为:http://haitian299.github.io/2016/05/26/mysql-partitioning/. 本人项目实践,使用sharding-jdbc进 ...
- stack|session|fuss|anniversary
N-COUNT A stack of things is a pile of them. 摞; 堆 例: There were stacks of books on the bedside table ...