一个Android程序由多个组件组成,各个组件之间使用Intent进行通信。Intent对象中包含组件名称、动作、数据等内容。根据Intent中的内容,Android系统可以启动需要的组件。
实际上,Activity、Service和Broadcast Receiver这3三种核心组件都需要使用Intent来进行激活。Intent用于相同或者不同应用程序组件间的后期运行时绑定。
一、Intent对象
对于不同的组件,Android系统提供了不同的Intent发送机制进行激活。
①Intent对象可以船体给Context.startActivity()或Activity.startActivityForResult()方法来启动Activity或者让已经存在的Activity去做其他任务。Intent对象也可以作为Activity.setResult()方法的参数,将信息返回给调用startActivityForResult()方法的Activity。
②Intent对象可以传递给Context.startService()方法来初始化Service或者发送新指令到正在运行的Service。类似的,Intent对象可以传递Context.bindService()方法来建立调用组件和目标Service之间的链接。它可以有选择地初始化没有运行的服务。
③Intent对象可以传递给Context.sendBraodcast()、Context.sendOrderedBroadcast()或Context.sendStickyBroadcast()等广播方法,使其被发送给所有感兴趣的Broadcast Receiver。
原则上讲,Intent包含组件名称、动作、数据、种类、额外和标记等内容:
①组件名称(Component Name)
组件名称是指Intent目标组件的名称。它是一个ComponentName对象。组件名称可以使用setComponent()、setClass()或setClassName()方法设置,使用getComponent()方法读取。
②动作(Action)
Action是要给字符串,用来表示将要执行的动作。在广播Intent中,Action用来表示已经发生即将报告的动作。在Intent类中,定义了一些列动作常量,其目标组件包括Activity和Broadcast两类。
1)标准Activity动作 2)标准广播动作
除了预定义的动作,开发人员还可以自定义动作字符串来启动应用程序中的组件。这些字符串应该包含一个应用程序包名作为前缀,如com.dyzhou.SHOW_COLOR。Intent对象中的动作使用setAction()方法设置,使用getAction()方法读取。
③数据(Data)
Data表示操作数据的URI和MIME类型。不同动作与不同类型的数据规范匹配。例如,如果动作是ACTION_EDIT, 数据应该是包含用来编辑的文档的URI;如果动作是ACTION_CALL,数据应该是包含呼叫号码的tel:URI。类似的,如果动作是ACTION_VIEW而且数据是http:URI,接收的Activity用来下载和显示URI指向的数据。
在将Intent与处理它的数据的组件匹配时,除了数据的URI,也有必要了解其MIME类型。例如,能够显示图片数据的组件不应该用来播放音频文件。
在多种情况下,数据类型可以从URI中推断,尤其时content:URI。它表示数据存在于设备上并由ContentProvider控制。但是,类型信息也可以显式地设置到Intent对象中。setData()方法仅能指定数据的URI,setType()方法仅能指定数据的MIME类型,setDataAndType()方法可以同时设置URI和MIME类型。使用getData()方法可以读取URI,使用getType()方法可以读取类型。
④种类(Category)
Category是一个字符串,其中包含了应该处理当前Intent的组件类型的附加信息。在Intent对象中可以增加任意多个种类描述。 与动作类似,在Intent类中也预定义了一些种类常量。
addCategory()方法将种类增加到Intent对象中,removeCategory()方法删除上次增加的种类,getCategories()方法获得当前对象中包含的全部种类。
⑤额外(Extras)
Extras是一组键值时,其中包含了应该传递给处理Intent的组件的额外信息。
Intent对象中包含了多个putXXX()方法(如putExtra()方法)用来插入不同类型的额外数据,也包含了多个getXXX()方法(如getDoubleExtra()方法)来读取数据。这些方法与Bundle对象有些类似。实际上,额外可以通过putExtras()和getExtras()方法来作为Bundle设置和读取。
⑥标记(Flags)
Flags表示不同来源的标记。多数用于指示Android系统如何启动Activity(如activity属于哪个Task)以及启动后如何对待(如它是否属于近期的activity列表)。所有标记都定义在Intent类中。
注意:所有标记都是整数类型。
二、Intent使用
Intent可以分成显式和隐式两类。
①显式Intent通过组件名称来指定目标组件。由于其他应用程序的组件名称对于开发人员通常式位置的,显式Intent通常用于应用程序内部消息,例如Activity启动子Service或其他Activity。
②隐式Intent不指定组件名称,通常用于激活其他应用程序中的组件。
在使用Intent过滤器测试Intent对象时,对象中仅有3个方面与其相关:
动作
数据(包括URI和数据类型)
种类
额外和标记在决定哪个组件可以接收Intent时并无作用。
Intent过滤器
Activity、Service和BroadcastReceiver能定义多个Intent过滤器来通知系统它们可以处理哪些隐式Intent。每个过滤器描述组件的一种能力以及该组件可以接收的一组Intent。实际上,过滤器接收需要类型的Intent、拒绝不需要类型的Intent仅限于隐式Intent。对于显式Intent,无论内容如何,总可以发送给其目标,过滤器并不干预。
对于能够完成的工作及显示给用户的界面,组件都有独立的过滤器。
Intent过滤器时IntentFilter类的实例。然而,由于Android系统在启动组件前必须了解组件的能力,Intent过滤器通常不在Java代码中进行设置,而是使用<intent-filter>标签写在应用程序的配置文件中(唯一的例外是调用Context.registerReceiver()方法动态注册BroadcastReceiver的过滤器,它们通常直接创建为IntentFilter对象)。
过滤器中包含的域与Intent对象中动作、数据和分类域相对应。过滤器对于隐式Intent在这3个方面分别进行测试。仅有通过全部测试时,Intent对象才能发送给拥有过滤器的组件。由于组件可以包含多个过滤器,Intent对象在一个过滤器上失败并不代表不能通过其他测试。
1.动作测试
2.种类测试
3.数据测试
Android在一个APP中通过包名或类名启动另一个APP(以下三篇文章仅供参考)
一、
有时候需要从一个APP中启动另外一个APP,比如Twitter/微信等。
如果你不知道那个APP的Activity,但是知道包名(package name),那么可以使用如下的方法:
- Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
- startActivity(LaunchIntent);
Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
startActivity(LaunchIntent);
如果APP之间有合作关系,可以获得合作APP的清单文件(manifest),那么可以从该文件中获知package/activity,
可使用如下的方法来启动该APP特定活动界面:
- Intent intent = new
- intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
- startActivity(intent);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);
如果要在启动APP时传递参数,可以在意图(Intent)中设置:
- intent.putExtra("firstKeyName","FirstKeyValue");
- intent.putExtra("secondKeyName","SecondKeyValue");
二、
1、最简单的情况:只有包名
PackageManager packageManager = context.getPackageManager();
Intent it= packageManager.getLaunchIntentForPackage(pk_name);
2、启动第三方指定页面。(这个方法有限制,第三方页面 Activity的属性Export=“true”)
启动页貌似是默认是true,其他页面默认是false
pk_name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
ComponentName comp = new ComponentName("com.android.settings","com.android.settings.Settings");
intent.setComponent(comp);
startActivity(intent);
3、隐式启动第三方应用
Intent intent = new Intent();
intent.setAction(action);
intent.addCategory(category);
intent.setDataAndType("abc://www.baidu.com","image/gif");
startActivity(intent);
条件1:IntentFilter 至少有一个action 至少有一个Category 可以没有Data和Type
条件2:如果有Data,参数中Data必须符合Data规则
Category 默认:android.intent.category.DEFAULT)
三、
开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用。一般我们知道了另一个应用的包名和MainActivity的名字之后便可以直接通过如下代码来启动:
- Intent intent = new
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- ComponentName cn = new
- intent.setComponent(cn);
- startActivity(intent);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
startActivity(intent);
但是更多的时候,我们一般都不知道目标应用程序的启动Activity的类名,而只知道包名,接下来就需要这么做了,我封装成了一个方法,如下所示:
1. private void
2.
3. // 通过包名获取此APP详细信息,包括Activities、services、versioncode、name等等
4. null;
5. try
6. 0);
7. catch
8. e.printStackTrace();
9. }
10. if (packageinfo == null) {
11. return;
12. }
13.
14. // 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
15. new Intent(Intent.ACTION_MAIN, null);
16. resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
17. resolveIntent.setPackage(packageinfo.packageName);
18.
19. // 通过getPackageManager()的queryIntentActivities方法遍历
20. List<ResolveInfo> resolveinfoList = getPackageManager()
21. 0);
22.
23. ResolveInfo resolveinfo = resolveinfoList.iterator().next();
24. if (resolveinfo != null) {
25. // packagename = 参数packname
26. String packageName = resolveinfo.activityInfo.packageName;
27. // 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式:packagename.mainActivityname]
28. String className = resolveinfo.activityInfo.name;
29. // LAUNCHER Intent
30. new
31. intent.addCategory(Intent.CATEGORY_LAUNCHER);
32.
33. // 设置ComponentName参数1:packagename参数2:MainActivity路径
34. new
35.
36. intent.setComponent(cn);
37. startActivity(intent);
38. }
39. }