在本篇博客中会涉及以下内容:
Intent 即为意图,可以用来启动一个Activity,可以用来发送一个广播,启动或者绑定一个服务。最典型最常见的用法就是启动一个Activity,可以把Intent看作各个Activity之间的粘合剂。Intent对将来要发生的行为进行了抽象的描述,然后在运行时进行绑定,这种描述和绑定主要依赖于Intent中保存的数据。比如它保存了某个Activity的类名,那么在之后通过startActivity(Intent)就可以在运行时根据Intent中设置的类名找到并启动该Activity,或者他保存了Intent代表的行为,行为的类别,以及要处理的数据和数据的格式,系统也将根据这些内容以及系统内所有应用的清单文件解析出可以处理该Intent的Activity,并将Intent传递给该Activity。
Intent的主要用途在以下三个方面:
Activity 表示应用中的一个页面。通过将 Intent 传递给 startActivity(),您可以启动新的 Activity 实例。Intent 描述了要启动的 Activity,并携带了任何必要的数据。
如果您希望在 Activity 完成后收到结果,请调用 startActivityForResult()。在 Activity 的 onActivityResult() 回调中,您的 Activity 将结果作为单独的 Intent 对象接收。
Service 是一个不使用用户界面而在后台执行操作的组件。通过将 Intent 传递给 startService(),您可以启动服务执行一次性操作(例如,下载文件)。Intent 描述了要启动的服务,并携带了任何必要的数据。
如果服务旨在使用客户端-服务器接口,则通过将 Intent 传递给 bindService(),您可以从其他组件绑定到此服务。
广播是任何应用均可接收的消息。系统将针对系统事件(例如:系统启动或设备开始充电时)传递各种广播。通过将 Intent 传递给 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast(),您可以将广播传递给其他应用。
startActivity(intent);//用于启动一个活动
startService(intent);bindService(intent)//用于开启一个服务,只能使用显示意图
sendBroadcast(intent);//发送一个广播
//startActivity,startService,sendBroadcast指明了要开启一个活动或者是启动服务等
我们可以使用Intent的构造函数创建一个Intent对象,然后根据自己的需求配置合适的参数。
// 这是一个显示Intent,action、category、data不能影响组件的选择,
// 所以这种情况下这些参数一般也不会去设置
// 但是可以设置一些extra参数供下个页面使用。
// 整体上,下面的代码打开一个应用内名为HaveBothActivity.class的页面
Intent intent = new Intent(MainActivity.this,HaveBothActivity.class);
intent.putExtra("userName","francis.fan");
intent.putExtra("userAvatar","http://www.null.com/user/avatar/36271.jpg")
startActivity(intent);
// 下面的这个是隐式的Intent,
// 通过设置Action,告诉系统该Intent想要做什么类型的工作(这里是打开拨号界面)
// 通过设置Data,告诉系统要操作的参数是什么(这里是某个人的手机号)
// 整体上,下面的代码打开了系统的拨号界面,并且打开时已经填入了号码
Intent intent = new Intent();
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:180****8692"));
startActivity(intent);
// 下面的这个是隐式的Intent,
// 通过设置Action,告诉系统该Intent想要做什么类型的工作(这里是要做选择某一种东西的工作)
// 通过设置mimeType,告诉系统要选择的东西的类型(这里是选择皂片)
// 整体上,下面的代码会打开手机内的某一个应用的选择图片的页面(可能有多个这样的,这时候需要用户手动选择一个)
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent,2);
// 用于在手机Web浏览器上检索数据,也设置了搜索的关键字
Intent intent = new Intent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"api player 的博客");
startActivity(intent);
// 用于发送一条数据,数据的接收方会有很多,由用户选择使用哪一种
// 下面的内容设置包含了主题,标题,正文,附件,邮件接收人以及发送内容的mimeType信息在内的多种信息,但是发送的并不一定是邮件,用户也可以选择其他的应用。
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL,new String[]{"[email protected]","[email protected]"});//邮件的收件人
intent.putExtra(Intent.EXTRA_CC,new String[]{"[email protected]"});//邮件的抄送人
intent.putExtra(Intent.EXTRA_TEXT,"这是发送的内容的正文部分");
intent.putExtra(Intent.EXTRA_STREAM,imageUri);//这是发送的内容的附件
intent.putExtra(Intent.EXTRA_TITLE,"这是一个标题");
intent.putExtra(Intent.EXTRA_SUBJECT,"分享的主题");
intent.setType("image/*");//指明发送的数据的类型
startActivity(intent);
intent中参数包含了Action,Category,Data(Uri+mimeType), ComponentName,Flag以及Extras等信息。
ComponentName决定有哪个应用的哪个组件来完成该项工作;
通过setAction告知隐式意图的基本行为;
通过addCategory为意图添加分类;
通过setData,setType或者setDataAndType告诉系统要处理的数据和处理数据的类型;
通过putExtra,将数据存在 Bundl e中,通过Intent传递给处理该意图的组件;
//intent中的变量
private String mAction;//Action
private Uri mData;//Data
private String mType;//Type
private ComponentName mComponent;//classname
private int mFlags;//
private ArraySet mCategories;//Category
private Bundle mExtras;//Bundle
下面针对各个参数做下说明:
意图的一般性行为,通过设置此参数告诉系统我们的隐式Intent想要的操作是大致是做什么的,是查看数据,搜索或者是编辑,选择数据等。如:
还有两个特别的Action值得注意:
// 这是一个选择照片的隐式Intent
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);
intent.setType("image/*");
// 打开一个能和上面的Intent匹配的所有应用的页面的一个列表页
Intent chooseIntent = new Intent();
chooseIntent.setAction(Intent.ACTION_PICK_ACTIVITY);
chooseIntent.putExtra(Intent.EXTRA_INTENT, intent);
startActivityForResult(chooseIntent, 2);
// 返回值是一个ComponentName,在onActivityResult中接受并处理,可直接用于显式启动
ComponentName componentName = data.getComponent();
startActivityForResult(new Intent().setComponent(componentName), 4);
// 打开一个带标题的应用选择器,和上面的类似,区别是这次打开之后用户选择之后就直接打开应用了,
// 如果EXTRA_INTENT需要返回值,需要使用startActivityForResult,否则直接使用startActivity即可
Intent chooseIntent = new Intent();
chooseIntent.setAction(Intent.ACTION_CHOOSER);
chooseIntent.putExtra(Intent.EXTRA_INTENT,intent);
chooseIntent.putExtra(Intent.EXTRA_TITLE,"选择要打开的应用");
startActivityForResult(chooseIntent,8);
data分为两部分:Uri和mimeType.
Uri:scheme://host:port/path(协议名称://主机地址:端口/特定服务的路径),其中path = folder/folder/file。(这几个字段存在线性依赖关系,前面的字段不存在,则后面的字段配置了也会被忽略。)
如常见的content://表示来自系统ContentProvider中的内容;file://表示来自本机文件系统的文件;http://host:port/path 表示要处理的数据来自于基于http协议网络主机上;用户也可以指定适合自己应用格式的特定的Uri格式,如果是自定义的就不具有通用性了。
下面说几个Android应用中常见的几个Scheme和用法:
- ftp / http / https: 你懂得
- content: ContentProvider的资源。content://djsh/whjdhs/shja.jpg
- file: 本机文件。file://dsjj/jajs/hjah.pdf
- tel: 电话功能。tel:180****6680
- smsto: 消息功能。smsto:180****6680
- emailto: 邮件功能。emailto:180****6680
- 自定义: 网页打开应用。
mimeType:Multipurpose Internet Mail Extensions,多目的网络邮件扩展,最初是用来表示邮件的附件的类型的,现在也用来表明附件的类型信息。
一个MIME类型至少包括两个部分:一个类型(type)和一个子类型(subtype)。此外,它还可能包括一个或多个可选参数(optional parameter)。
比如,HTML文件的互联网媒体类型可能是text/html; charset = UTF-8
在这个例子中,文件类型为text,子类型为html,而charset是一个可选参数,其值为UTF-8。
mimeType的常见类型: 这里有对mimeType更加详尽的介绍
- 超文本标记语言文本 .html text/html
- 普通文本 .txt text/plain
- RTF文本 .rtf application/rtf
- GIF图形 .gif image/gif
- JPEG图形 .ipeg,.jpg image/jpeg
- au声音文件 .au audio/basic
- MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
- RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
- MPEG文件 .mpg,.mpeg video/mpeg
- AVI文件 .avi video/x-msvideo
- GZIP文件 .gz application/x-gzip
- TAR文件 .tar application/x-tar
mimeType的类型和子类型也可以用*来表示:image/*、video/*等
类别,声明所属的类别.一个包含应处理 Intent 组件类型的类别信息的字符串。 您可以将任意数量的类别描述放入一个 Intent 中,但大多数 Intent 均不需要类别。
下面是一些标准的Category:(很多我都不知道啊干嘛的)
组件,包含了指定组件的包名和类名,当我们需要显式地指明处理Intent的组件时指定 ComponentName 的值。
所有的service的启动都应该使用显式意图
如果不指定组件,则由系统根据Intent中的其他信息解析出适合的组件,如果满足条件的组件有多个,则由用户指明使用哪一个组件(如果用户之前没有指定过默认打使用的组件)。
Intent所携带的额外的数据,如页面跳转的时候,我们可能经常需要传递一些信息到下一个页面去,或者从当前页面返回数据给上一个页面。系统也提供了一些常用的Extra的Key值,比如:
在 Intent 类中定义的、充当 Intent 元数据的标志。 标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个任务栈),以及启动之后如何处理。
关于常用Flag的解析,看看任玉刚的这篇博客。
注意:如果是从BroadcastReceiver启动一个新的Activity,或者是从Service往一个Activity跳转时,不要忘记添加Intent的Flag为FLAG_ACTIVITY_NEW_TASK。
显式和隐式意图可以根据 Intent 中是否指定了要启动的组件(mComponent 是否指定),指定了特定组件的就是显式意图否则就是隐式意图。
按名称(完全限定类名)指定要启动的组件。 通常,您会在自己的应用中使用显式 Intent 来启动组件,这是因为您知道要启动的 Activity 或服务的类名。例如,启动新 Activity 以响应用户操作,或者启动服务以在后台下载文件。
如果 Intent 中 mComponent 不为空,即开发者使用setComponent或者setClass或者setClassName等显式指定处理意图的组件,此时 Intent 中设置的 action、category、data 等不影响组件的选择。适用条件是开发者准确知道可以处理该意图的对象的确切的位置(包名和类名),如果调用对象在应用内可以直接指定 xxxx.class ,如果调用其他应用则需要指定包名以及类名的确切路径。
//显式意图(通过设置 ComponentName 参数指定完成意图的组件)
//设置Component参数一共有三种方式
intent.setClass(this,MainActivity.class);
intent.setClassName(this,"com.nullpointer.stud.MainActivity.class");
intent.setClassName("com.nullpointer.study","com.nullpointer.study.MainActivity");
//其实质都是通过包名和类名构造了一个ComponentName
//打开当前APP内组件可以不指定包名而通过context指定,但是实质还是使用包名
//打开其他应用的组件需要指定完整包名和全限定类名
不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。 例如,如需在地图上向用户显示位置,则可以使用隐式 Intent,请求另一具有此功能的应用在地图上显示指定的位置。
创建隐式 Intent 时,Android 系统通过将 Intent 的内容与在设备上其他应用的清单文件中声明的 IntentFilter 进行比较,从而找到要启动的相应组件。 如果 Intent 与 IntentFilter 匹配,则系统将启动该组件,并向其传递 Intent 对象。 如果多个 Intent 过滤器兼容,则系统会显示一个对话框,支持用户选取要使用的应用。
隐式意图则是通过设置 Action,Category,Data等之后交给系统( Intent 中的 action 一般都需要指定,Category 可以不设置,如果不设置则默认为只有一个 CATEGORY_DEFAULT ),由系统以及用户选择处理该意图的组件,如果 Activity 希望被隐式意图启动,则必须包含 android.intent.category.DEFAULT。
//通过setAction指定操作的类型,通过setData指定操作的数据,
//通过设置Category限定类别
//通过设置setType指定操作的对象的类型
//Intent.ACTION_DIAL tel:180****6680用于打开拨号界面
//下面的示例就指定了一个打开拨号界面的意图,并且指定了拨号界面的数据是朕的手机号码
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:180****6680"));
//下面的示例就打开了指定的网页
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.google.com"));
//?下面的示例就打开了搜索结果页面
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"Android");
//需要注意的是 setData和setType互斥,如果需要同时设置 请使用setDataAndType();
public @NonNull Intent setData(@Nullable Uri data)
mData = data;
mType = null;
return this;
}
public @NonNull Intent setType(@Nullable String type) {
mData = null;
mType = type;
return this;
}
Android 提供了很多标准Intent的使用范例,也预置了很多标准Action,Category,Extra的字段等,下面列举一下常用的。
Android 提供了很多标准Intent的使用范例,也预置了很多标准Action
谷歌在线文档
一个不错的中文示例
有些东西没必要去死记硬背,需要的时候去翻文档就好了
Intent 过滤器是应用清单文件中的一个表达式,它指定该组件要接收的 Intent 类型。 例如,通过为 Activity 声明 Intent 过滤器,您可以使其他应用能够直接使用某一特定类型的 Intent 启动 Activity。同样,如果您没有为 Activity 声明任何 Intent 过滤器,则 Activity 只能通过显式 Intent 启动。
就像前面讲到的,我们可以通过设置 action、category、data参数来让系统帮我们选择进行此操作的组件,或者应用。 Action 指定了将要操作的行为,是打开一个网页还是去打开一个拨号页面,或者是发短信、发邮件等等等等。 Data 就指定了要操作的数据。
我们使用了系统提供的 Action 可以方便地调用系统的一些服务。如果我们的应用需要被别的应用调用呢?这个时候我们可以设置自己应用 Activity 或者 Service 或者 BrocastReceiver 的 interFilter 来告诉系统我们的组件可以处理哪些数据。相信下面的代码大家一定不会陌生:
<activity android:name=".MainActivity"
android:label="launcher上显示的名字"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
下面介绍一下Action,Data,Category的含义和作用,然后给出几个常用的值。
根据Intent中的配置找到满足条件的IntentFilter,进而找到对应的组件。此处的Intent全部指的是隐式Intent,因为不管显式Intent中action,category,data配置的是什么,Intent都将会传递给显式指定的组件。
Intent的整体匹配规则是:
提前说一下数学中子集的概念:如果集合A的任意一个元素都是集合B的元素,那么集合A称为集合B的子集。空集合是所有集合的子集。
一个IntentFilter可以包含0-n个Action,一个Intent只能包含一个Action。
一个Intent可以设置多个Category,一个IntentFilter也可以包含0-n个Category。
另外,所有的隐式Intent都包含一个CATEGORY_DEFAULT的Category。
一个 IntentFilter 可以配置0-n个data,一个Intent只能包含一个data.
前面已经说过了data分为两部分: Uri 和 mimeType ,因此 data 的匹配也要分成两部分进行匹配。
根据前面所讲到的知道Uri也分为四个部分:scheme、host、port、path。则Uri的匹配规则如下
- path 用来匹配完整的路径,如:”https://developer.android.com/reference/android/content/Intent.html” ,这里将 path 设置为 “/reference/android/content/Intent.html” 才能够进行匹配;
- pathPrefix 用来匹配路径的开头部分,拿上面的 Uri 来说,这里将 pathPrefix 设置为 “/reference” 或者 “/android/content” 就能进行匹配了;
- pathPattern 用表达式来匹配整个路径,本例中可以用 “.*\.html” 匹配所有以.html 结尾的路径(注意字符的反义)。这里需要说下两种匹配符号。
匹配符号:
- “*” 用来匹配0次或更多,如:”a*” 可以匹配”“、”a”、”aa”.
- “.” 用来匹配任意单个字符,如:”.” 可以匹配”a”、”b”,”c”.
因此 “.*” 就是用来匹配任意字符0次或更多,如:”.*.html” 可以匹配 “abc/def/ghi/jkl.html”、”ccbh.tml”;”/reference/.*.html”表示以 “/reference” 开始 以”.html”结尾的路径。(“.html” 表示 html 前面有任意一个字符,”.html” 表示以 .html 结尾)
- Intent的Uri为content或者file类型:IntentFilter可以没有配置Uri(如果IntentFilter配置了mimeType,没有配置Uri,系统假定组件支持content:或者file:类型的Uri),或者也配置了与Intent中Uri匹配的Uri.
- Intent的Uri不为content或者file类型:IntentFilter也配置了与Intent中Uri匹配的Uri.
1、2和4可能还算用的多的,3并不会怎么用。3是不包含Uri但是指定了mimeType,资源都没有,资源的类型也就毫无意义了,所以不是很常用。
其实上面的规则很好理解:IntentFilter是用来处理数据的,所以他要处理的数据的范围必须要大于Intent中设置的数据的范围(范围同时包含Uri类型和mimeType类型)。如果遵守的协议都不一样,肯定没办法处理啊,如果能处理的mimeType也无法匹配,那就自然也处理不了了。
有一个规律就是,Intent中未配置的项默认范围最大,IntentFilter未配置的项默认范围最小。比如:
- 如果Intent中不包含Uri则默认Intent配置的Uri是最大的范围,所以配置了Uri的IntentFilter的Uri范围自然变小,不是包含关系,所以没法处理;mimeType也是同样的。
- 如果IntentFilter中不包含Uri,系统给了content和file的默认值,不包含mimeType时,所有配置了mimeType的Intent均无法与之匹配成功。
根据上面的介绍的匹配规则看一下下面的示例:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:label="启动页面">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
intent-filter>
activity>
<activity android:name=".NoActionActivity"
android:label="NoActionActivity">
<intent-filter>
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY" /
<category android:name="android.intent.category.DEFAULT"/>
intent-filter>
activity>
<activity android:name=".NoCategoryActivity"
android:label="NoCategoryActivity">
<intent-filter>
<action android:name="com.nullpointer.intentdemo.DEMO_ACTION" />
intent-filter>
activity>
<activity android:name=".NoDefaultCategoryActivity"
android:label="NoDefaultCategoryActivity">
<intent-filter>
<action android:name="com.nullpointer.intentdemo.DEMO_ACTION" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY" />
intent-filter>
activity>
<activity android:name=".NoDataActivity"
android:label="NoDataActivity">
<intent-filter>
<action android:name="com.nullpointer.intentdemo.DEMO_ACTION" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY" />
<category android:name="android.intent.category.DEFAULT"/>
intent-filter>
activity>
<activity android:name=".NoMimeTypeActivity"
android:label="NoMimeTypeActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="com.nullpointer.intentdemo.DEMO_ACTION" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="demo" />
intent-filter>
activity>
<activity android:name=".NoUriActivity"
android:label="NoUriActivity">
<intent-filter>
<action android:name="com.nullpointer.intentdemo.DEMO_ACTION" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY1" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY2" />
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY3" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="demo/mime"/>
intent-filter>
activity>
<activity android:name=".HaveBothActivity"
android:label="HaveBothActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="com.nullpointer.intentdemo.DEMO_CATEGORY" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="demo" android:host="test" android:port="1234" android:path="path" android:mimeType="demo/mime"/>
intent-filter>
activity>
application>
这个问题可以说是很大的问题了。简要说一下,详细的就太多内容了。
参考:
欧阳辰的专栏-移动DeepLink的前世今生
google training-Deep Linking and Android App Links
常见的应用大都会为他们的应用提供App和网页两种访问途径,但是显而易见的是APP可以提供更好的用户体验,因此从网页进入我们的App也就成为了一种需求。目前从网页进入App的途径就是通过设置Activity的IntentFilter。
如下面的这个Activity就可以允许网页打开自己。
<activity
android:name=".UserInfoActivity"
android:label="用户信息">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="nullpointer" host="com.nullpointer.demo" path="/userInfo"/>
intent-filter>
activity>
上面这个页面是一个用于展示用户信息的页面,我们配置了一个用于网页打开的过滤器(当然也可以再配置一些用于其他用途的过滤器),我们在这个过滤器中配置了 action,category 以赋予我们的应用可以被网页打开的能力,设置data的值来确保我们的当前只响应我们感兴趣的Uri.
ACTION_VIEW 用于展示数据,总是必须的。
CATEGORY_BROWSABLE 允许我们的应用可以被浏览器打开,因此也是必须的。
CATEGORY_DEFAULT 允许我们的应用允许被隐式意图打开,因而也是必须的。
通过设置Data中scheme、host、path或者path的变种,允许特定的链接才能打开我们的当前页面。
将下面的网页在浏览器中打开,然后点击页面上的“打开我的应用”链接,即可打开我们的App:
<html>
<body>
<h1>Test Schemeh1>
<!—自动加载隐藏页面跳转—>
<!—手动点击跳转—>
<a href="nullpointer://com.nullpointer.demo/userInfo?userId=001">打开我的应用a>
body>
html>
然后我们在App中这样获取应用的参数:
在这里,我们是直达需要的页面,有时候也可以配置一个统一的入口,然后根据参数来确定打开哪个页面。
//因为可以打开我们的这个页面,所以前面的host,path都不要再提了
Intent intent = getIntent();
if (TextUtils.equals("nullpointer",intent.getScheme())){
Uri uri = intent.getData();
String userId = uri.getQueryParameter("userId");
//获取了userId,就爱干啥干啥吧
Toast.makeText(this,"获取的用户Id是"+userId,Toast.LENGTH_SHORT).show();
}
在上面的实例中,我们只是确保了我们的app中的页面可以被浏览器打开,然后通过携带的参数进行相应的展示,这并不符合谷歌对深度链接的定义。
深度链接的一个显著特征是:在用户通过浏览器得到的搜索结果中,当点击某一条来自与当前App配套的网页的结果的时候,浏览器可以直接打开我们的应用(甚至不需要用户选择要打开的App),而不是先进入网页,然后再打开我们的App。
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>example://gizmosloc>
<xhtml:link
rel="alternate"
href="android-app://com.example.android/example/gizmos" />
url>
...
urlset>
<html>
<head>
<link rel="alternate"
href="android-app://com.example.android/example/gizmos" />
...
head>
<body> ... body>
好了,关于Intent的基本知识就先到这里为止了。