Android APP完整基础教程(09)载体Intent & IntentFilter

Intent简介

intent理解为通信载体,系统是“大海”,应用为“各个国家”,组件为“国家的岛屿”,通信载体为“小船”。intent可以是启动某个组件的“意图”,也可以是程序组件之间的通信媒介。通过intent可以启动activity、service,还可以发送广播等。

Intent的分类:

  • 显式Intent:通过组件名指定启动的目标组件(就像女孩子相亲,她就要找“梁山伯”)。
  • 隐式Intent:指定Intent的Action、Data、Category,当启动组件时, 会匹配AndroidManifest.xml相关组件的Intent-filter,逐一匹配出满足属性的组件,当不止一个满足时, 会弹出一个让我们选择启动哪个的对话框(就像女孩子相亲,她就要找“高富帅”)。

2.Intent关键属性

Intent关键属性主要有:ComponentName、Action和Category、Data和Type、Extras、Flags。

关于这些属性,我们可以这样简单的类比:

  • ComponentName相当于指定了主语和宾语(此处宾语表明意图确定的组件,显式)。
  • Action相当于指定了谓语动作。Category主要给action增加额外的信息,可以理解为状语。
  • Data和Type相当于宾语(此处宾语表明意图不明确的组件,隐式)。
  • Extra表示在“我要你做什么”的时候,可以给一些资源和支持。传递Bundle数据包。比如:我要发一封邮件给S,那么Extra 等价于 主语把邮件的标题、内容打包成Bundle传递给宾语。
  • FLAG主要针对activity栈。主要描述任务队列启动方式(在“我要做什么”的基础上相再加另一句来补充说明,即我要怎样启动这个新的组件)。

2.1 ComponentName(目的组件)

如果指定了component属性,则直接使用它指定的组件。Intent的其它所有属性都是可选的。一般来说代码使用方式(3种方式均可)如下:

//第1种方式,创建组件,通过组件来响应
Intent intent = new Intent();
ComponentName component = new ComponentName(MainActivity.this, SecondActivity.class);
intent.setComponent(component);                
startActivity(intent);

//第2种方式,指定组件包名
Intent intent = new Intent();
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);

//第3种方式,构造器简化
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);

2.2 Action(动作)和Category(类别)

action和category属性均在<intent-filter>中声明。

2.2.1 Action(动作)

@1 Intent与Action

在Intent中,Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,表示要完成一个抽象动作。在Intent类中,定义了一批量的动作,比如ACTION_VIEW,ACTION_PICK等, 基本涵盖了常用动作。加的动作越多,越精确。设置与获取action代码如下:

Intent intent = new Intent();
//设置action
intent.setAction("com.ags.MY_ACTION1");
//获取action
String action = getIntent.getAction();

注意:一个intent只能包含一个Action属性值。

@2 IntentFilter与Action

一个Intent Filter可以包含多个Action。在AndroidManifest.xml的Activity配置时,可以在其 <intent-filter >节点指定一个action列表用于标识Activity“所能接受的动作”。配置方式如下:

<intent-filter>
  <action android:name="com.ags.MY_ACTION1"></action>
   <action android:name="com.ags.MY_ACTION2"></action>
   <action android:name="com.ags.MY_ACTION3"></action>
</intent-filter>

同时,如果有多个组件匹配成功(比如都有Action "com.ags.MY_ACTION1"),就会以对话框列表的方式让用户进行选择。

2.2.2 Category(类别)

Category属性用于为action属性增加额外的附加类信息,也是作为<intent-filter>子元素来声明的。Action 和category通常是放在一起用,如下所示:

<intent-filter>
  <action android:name="com.ags.MY_ACTION"></action>
  <category android:name="com.ags.intent.MY_CATEGORY"></category> 
  <category android:name="android.intent.category.DEFAULT"></category> 
</intent-filter>

注意:虽然一个intent只能包含一个Action属性,但可以包含很多个category的属性,添加判定的category越多,动作就越具体,意图也就越明确。

为了让唯一组件与上面的intent-filter匹配,该组件要设置Action,同时也要设置category,代码如下所示:

Intent intent = new Intent();
intent.setAction("com.ags.MY_ACTION"); 
//注意,这里默认是有一个category的,就是我们常见的“android.intent.category.DEFAULT"
intent.addCategory("com.ags.MY_CATEGORY");
startActivity(intent);

这样启动时就可以更好地确保唯一性了。

另外指定Action和Category可以用来调用系统的Activity,启动Activity的标准ACTION常量和对应参照文档:

2.3 Data(数据)和Type(MIME类型)

data和type属性均在<intent-filter>中声明。

2.3.1 Data(数据)

Data属性主要用于向Action属性提供操作的数据。Data属性接受一个Uri对象(Uri相关知识可以查看文章:Android APP完整基础教程(08)四大组件之ContentProvider)。关于Data支持的属性有

属性 作用
android:scheme  指定数据协议,http://www.baidu.com
android:host 指定数据主机名,http://www.baidu.com
android:port 指定数据端口,http://www.rowyer:8080/mypath
android:path 指定路径部分,http://www.rowyer:8080/abc/mypath
android:pathPrefix 匹配路径开头部分,http://www.rowyer:8080/abc/mypath
android:pathPattern 正则表达式来匹配整个路径,http://.*/mypath
android:mimeType 指定可以处理的MIME数据类型,即Type属性

在Androidmanifest中定义如下:

<intent-filter>
    <action android:name="com.ags.myapplication"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data
        android:scheme="http"
        android:host="www.baidu.com"
        android:port="8080"
        android:path="/mypath"
        android:mimeType="audio/mp3"/>
</intent-filter>

Intent中设置Data属性的方式为:

//设置Data
Intent intent = new Intent();
Uri data = Uri.parse("file:///storage/sdcard0/test.mp3");
intent.setData(data);

2.3.2 Type(MIME类型)

Type属性用于指定Data属性Uri对象的MIME类型,这种类型可以是自定义MIME类型(MIME相关知识可以查看文章:Android APP完整基础教程(08)四大组件之ContentProvider)。Type在Androidmanifest.xml中的设置同样也在上面Data属性中(如2.3.1所示),是data的mimeType字段。

Intent中设置Type属性的方式为:

//设置Type
Intent intent = new Intent();
intent.setType("audio/mp3");

2.3.3 同时设置Data属性和Type属性

 同时代码中设置Data属性和Type属性的方式为:

//一次性设置Data和Type
Intent intent = new Intent();
Uri data = Uri.parse("file:///storage/sdcard0/test.mp3");
intent.setDataAndType(data, "audio/mp3");

注意:若代码中设置了Data属性再设置Type属性,则Data属性被覆盖;若设置了Type属性再设置Data属性,则Type属性被覆盖。若同时具有Data属性和Type属性,则使用setDataAndType方法。

2.4 Extras(额外)

Extras可以为组件提供扩展信息。可以这样理解比:如果要执行“send email”这个动作,可以将电子email的内容 构建一个Bundle对象 保存在Extras属性中,传给email发送组件。

Extras属性值一个Bundle对象,通过键值对(key:value) 对数据进行存储。使用Bundle来传递数据,Bundle部分在文章Android APP完整基础教程(05)四大组件之Activity 中有更详细的说明。

2.5 Flags(标记) 

为Intent添加一些额外的控制标志,和文章Android APP完整基础教程(05)四大组件之Activity 中提到的4种Activity启动模式中Activity Task栈相关,部分常见Flag使用如下:

FLAG_ACTIVITY_BROUGHT_TO_FRONT:如果该Activity已在栈中,则将该标识的Activity直接拉到前台显示(若activity栈中过有A,以该标志位启动B,B中启动C[0],C[0]启动C[1]...C[N],此时B又被C调出,则直接将B拉到前台,其他保持不变,即由 ABC[1]...[N]->AC[1]...[N]B)。
FLAG_ACTIVITY_CLEAR_TOP:相当于4种启动模式种的singleTask模式。
FLAG_ACTIVITY_NEW_TASK:重新创建一个新Activity并放至栈顶,有可能连着2个activity一样
FLAG_ACTIVITY_NO_ANIMATION:启动Activity时会无过渡动画。
FLAG_ACTIVITY_NO_HISTORY:该标识启动的activity退到后台后不会保留在栈中(若activity栈中有A,B,此时B以该标识启动C,C启动D,此时栈中无C,即由ABC->ABD)。
FLAG_ACTIVITY_REORDER_TO_FRONT:该标识启动的ActivityB会被直接带到栈顶(若activity栈中有A、B、C,此时B被该标识启动,被拉到前台,即由ABC->ACB)。
FLAG_ACTIVITY_SINGLE_TOP:相当于4种启动模式种的singleTop模式。

更多关于FLag的说明可以参照文档:Android Intent Flag说明

3 IntentFilter 匹配/过滤法则解读

该部分主要针对隐式调用,分析IntentFilter中的action,category,data,type的用法。规则解读如下:

@1 整体而言:

  • 一个组件可以声明多个Intent Filter,只需要匹配任意一个Intent Filter即可启动该组件。 
  • 只有一个Intent同时匹配一个Intent Filter的action,category,data,type这几个类别才算完全匹配,只有完全匹配才能启动Activity。

@2 分开来看:

  • Data和Type匹配:如果一个activity在intent-filter标签中配置了data标签中的scheme、host、port、path内容,要想启动该activity,setData传入的字符串就必须与data标签中的所有内容一致,否则不能启动。
  • Action匹配:一个Intent Filter可以声明多个action,Intent中的action与任意一个action在字符串形式上完全相同(注意:字符串区分大小写)action方面就匹配成功。
  • Category的匹配:要求Intent中个如果含有category,那么所有的category都必须和intentFilter规则中的其中一个category相同(比如:Intent中有categoryA和categoryB,intentFilter中必须要有categoryA和categoryB,同时还可以其他的策略categoryC和categoryD等)。

总结:整体而言4个属性均匹配成功才会启动,分开来看中说明了4个属性详细的匹配成功的定义。

4 常见系统Intent使用总结

4.1 打开网页

设置action为ACTION_VIEW,data为Uri.parse("http://www.baidu.com"),代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);

4.2 Telephony相关

4.2.1 打电话

设置action为ACTION_DIAL,data为Uri.parse("tel:95555"),代码如下:

Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:95555"));
startActivity(intent);

4.2.2 发短信

设置action为ACTION_VIEW,type为"vnd.android-dir/mms-sms",Extra为("sms_body", "短信内容"),代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setType("vnd.android-dir/mms-sms");
intent.putExtra("sms_body", "短信内容");
startActivity(intent);

4.3 多媒体

4.3.1 播放音乐

设置action为ACTION_VIEW,data为Uri.parse("file:///storage/sdcard0/XXX.mp3"),type类型为 "audio/mp3",代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file:///storage/sdcard0/XXX.mp3"), "audio/mp3");
startActivity(intent);

4.3.2 打开camera

如果只是打开系统相机,则设置action为MediaStore.ACTION_IMAGE_CAPTURE,如果打开系统相机后还要保存数据,设置Extra为(MediaStore.EXTRA_OUTPUT,照片路径);代码如下:

// 打开拍照程序
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
startActivityForResult(intent, 0);

//打开系统相机,并存储照片
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/tucue",Calendar.getInstance().getTimeInMillis() + ".jpg")));
startActivityForResult(intent, 1);

4.4 发邮件

设置action为ACTION_SENDTO,data为Uri.parse("123@abc.com"),代码如下:

// 给123@abc.com发邮件
Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("123@abc.com"));
startActivity(intent);

4.5 安装/卸载程序

安装应用时,设置action为ACTION_PACKAGE_ADDED,data为Uri.fromParts("package", "com.ags.test", null),代码如下:

//安装应用
Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED);
intent.setData(Uri.fromParts("package", "com.ags.test", null));
startActivity(intent);

卸载应用,action为ACTION_DELETE,data为Uri.parse("package:com.ags.test"),代码如下:

//卸载应用
Intent intent = new Intent(Intent.ACTION_DELETE);
intent.setData(Uri.parse("package:com.ags.test"));
startActivity(intent);

4.6 显示地图

设置action为ACTION_VIEW,data为Uri.parse("geo:30.7,120.4"),代码如下所示:

Intent intent = new Intent(Intent.ACTION_VIEW);
//数据含义为经纬度坐标
intent.setData(Uri.parse("geo:30.7,120.4"));
startActivity(intent);

4.7 打开设置界面

设置action为android.provider.Settings.ACTION_WIRELESS_SETTINGS,代码如下:

Intent intent = new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);  
startActivityForResult(intent, 1);

其他Setting界面启动方式同样可参照如上方式。

5 官方文档索引

Android组件之Intent组件关于Intent更多内容查看文档:Android组件之Intent组件

总结

  • 了解Intent基本概念,显式intent和隐式intent的区别。理解Intent的关键属性(ComponentName、Action和Category、Data和Type、Extras、Flags)和IntentFilter的过滤规则。
  • 练习Intent的关键属性设置和获取方法,常见系统Intent的用法都要练习到熟练为止。
上一篇:C/C++类型转换


下一篇:虚幻引擎(UE4) Visual Logger 可视化调试器