Android——Intent
1.什么是Intent
Android中提供了Intent机制来协助应用间的交互与通讯,或者采用更准确的说法是,Intent不仅可用于应用程序之间,也可用于应用程序内部的activity,service和broadcast receiver之间的交互。Intent这个英语单词的本意是“目的、意向、意图"。
Intent是一种运行时绑定 (runtime binding)机制,它能在程序运行的过程中连接两个不同的组件。通过Intent, 你的程序可以向Android表达某种请求或者意愿.。Android会 根据意愿的内容选择适当的组件来响应。
对于向这三种组件发送Intent有不同的机制:
使用Context.startActivity() 或 Activity.startActivityForResult(),传入一个Intent来启动一个activity。
使用Асtіvіtу.ѕеtRеѕult(),传入一个Intent来从асtіvіtу中返回结果。
将Intent对象传给Context.startService()来启动一个 Service或者传消息给一个运行的Service。
将Intent对象传给Context.bindService()来绑定Service。
将Intent对象传给Context.sendBroadcast(), Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则他们给传给broadcast receiver。
2.Intent的相关属性
Intent由以下组成部分:
- component(组件):目的组件
- Action(动作):用来表现意图的行动
- category(类别):用来表现动作的类别(给动作加限制范围)
- data(数据):表示与动作要操纵的数据
- type(数据类型):对于data范例的描写(限制数据)
- extras(扩展信息):扩展信息
- Flags(标志位):期望这个意图的运行模式
Intent分为直接Intent和间接Intent
Activity中IntentFilter匹配过程
IntentFilter翻译成中文就是“意图过滤器”,主要用来过滤隐式意图。当用户进行一项操作的时候,Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件,服务。
component(组件):目的组件
直接法:
//直接查找法(通过组件名称)
public void componentClick(View v){
//全写
// Intent intent=new Intent();
// ComponentName componentName=new ComponentName(this,Main2Activity.class);
// intent.setComponent(componentName);
//简写
Intent intent=new Intent(this,Main2Activity.class);
startActivity(intent);
}
Action(动作):用来表现意图的行动
当日常生活中,描述一个意愿或愿望的时候,总是有一个动词在其中。比如:我想"做"三个俯卧撑;我要"看"一部电影等等。在Intent中, Action就是描述看、 做、写等动作的,当你指明了一个Action,执行者就会依照这个动作的指示,接受相关输入,表现对应行为,产生符合的输出。在Intent类中,定义了一批量的动作,比如ACTION_VIEW,ACTION_PICK等,基本涵盖了常用动作。
Action是一个用户定义的字符串,用于描述一个Android应用程序组件,一个Intent Filter可以包含多个Action。在 AndroidManifest.xml的Activity定义时可以在其节点指定一个Action列表用于标识Activity所能接受的“动作”。
//间接法(通过Action属性)
public void actionClick(View v){
Intent intent=new Intent();
intent.setAction("com.action.MY_ACTION");//匹配方,Action只能有一个
startActivity(intent);
}
简写
Intent intent=new Intent("com.action.MY_ACTION");
在清单文件中给Main3设置inten-filter
<activity
android:name=".Main3Activity"
android:label="@string/title_activity_main3">
<intent-filter>
<action android:name="com.action.MY_ACTION"></action>
<category android:name="android.intent.category.DEFAULT"></category>//默认的类别,必须添加
</intent-filter>
</activity>
给Main2也加上intent-filter
<activity
android:name=".Main2Activity"
android:label="@string/title_activity_main2" >
<intent-filter>
<action android:name="com.action.MY_ACTION"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
则找到两个符合要求的,按优先级排序,优先级相同由用户进行选择。
设置优先级,给不想显示的activity的优先级设置为负数
<activity
android:name=".Main3Activity"
android:label="@string/title_activity_main3">
<intent-filter android:priority="-1">
<action android:name="com.action.MY_ACTION"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
<activity
android:name=".Main2Activity"
android:label="@string/title_activity_main2" >
<intent-filter android:priority="2">
<action android:name="com.action.MY_ACTION"></action>
<category android:name="android.intent.category.DEFAULT"></category>
</intent-filter>
</activity>
ps:在被匹配方中可加多个action,只要找到对应的匹配项就可以。
category(类别):用来表现动作的类别(给动作加限制范围)
Category属性也是作为子元素来声明的。
<category android:name="com.category.MY_CATEGORY"></category>
/*
* 间接法(通过Action属性和category属性)
* 在Activity的清单文件配置中,必须使用默认的类别
* android.intent.category.DEFAULT
* */
public void actionClick(View v){
// Intent intent=new Intent("com.action.MY_ACTION");
Intent intent=new Intent();
intent.setAction("com.action.MY_ACTION");//Action最多只能有一个
intent.addCategory("com.category.MY_CATEGORY");//类别可以添加多个
startActivity(intent);
}
data(数据):表示与动作要操纵的数据
Data属性是Android要访问的数据,和action和category声明方式相同,也是在中声明。
/*
* data属性,一般与Action配合使用(此组合是最常见的使用方法)
* */
public void dataClick(View v){
Intent intent=new Intent();
// intent.setAction("com.action.MY_ACTION");
intent.setAction(Intent.ACTION_VIEW);
Uri data=Uri.parse("http://www.baidu.com");
intent.setData(data);
startActivity(intent);
}
协议:android:scheme=""
路径:android:path=""
主机:android:host=""
端口:android:port=""
数据类型:android:mimeType=""
<intent-filter>
<action android:name="com.action.MY_ACTION"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<data android:scheme="http" android:host="www.baidu.com"></data>
</intent-filter>
type(数据类型):对于data范例的描写(限制数据)
如果Intent对象中既包含Uri又包含Type,那么,在中也必须二者都包含才能通过测试。
Type属性则用于明确指定Data属性的数据类型或MIME类型(字符串,如.jpg/.png),但是通常来说,当Intent不指定Data属性时,Type属性才会起作用,否则Android系统会根据Data属性值来分析数据的类型,所以无需指定Type属性。
/*
* data属性,一般与Action配合使用(此组合是最常见的使用方法)
* Type属性,用来表示数据的类型
* */
public void dataClick(View v){
Intent intent=new Intent();
// intent.setAction("com.action.MY_ACTION");
intent.setAction(Intent.ACTION_VIEW);
Uri data=Uri.parse("http://www.baidu.com");
// intent.setData(data);//会把Type属性设置为空
// intent.setType();//会把Data属性设置为空
//要同时使用Data和Type,必须使用以下方法,匹配时必须两者同时匹配才能通过
intent.setDataAndType(data,"text/html");
startActivity(intent);
}
<data android:scheme="http" android:host="www.baidu.com" android:mimeType="text/html"></data>
通常情况下只设置一个的比较常用
extras(扩展信息):扩展信息
是其他所有附加信息的集合,使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。
Flags(标志位):期望这个意图的运行模式
一个程序启动后系统会为这个程序分配- -个task供其使用, 另外同一个task 里面可以拥有不同应用程序的activity。那么,同 一个程序能不能拥有多个task?这就涉及到加载activity的四种模式: standard、singleTop、 singleTask、 singlelnstance。可以在AndroidManifest.xml中activity标签的属性launchMode中设置该activity的加载模式。
加载模式:android:launchMode=""
简述下这四种模式的区别:
- android:launchMode=“standard”:默认的模式,以这种模式加载每次启动会重新创建一个activity对象放到膜表task中的activity栈顶。
- android:launchMode=“singleTop”:这种模式与standard模式类似,区别在于加载activity会多个判断步骤。判断需要加载的新activity与当前task栈顶的activity是不是同一个,相同的话不在构造新的activity,并调用这个activity的newInstance()方法,不相同就还是会构造新的activity放到栈顶。
- android:launchMode=“singleTask”:在当前任务栈中,判断栈里是否存在Activity,如果不存在,创建一个新Activity入栈,如果存在,会把该Activity之上的所有Activity清除出栈,显示当前的Activity。
- android:launchMode=“singlelnstance”:这种模式下,会创建一个新的task,并且这个task中只能存在一个需要加载的这个Activity实例,即除了这个activity之外,不允许其他activity。如果已存在,那么会切换到该任务栈。
以下测试代码,可自行测试
新建两个文件,分为A,B
A:
B:
按钮事件:
public void startA(View v){
Intent intent=new Intent(this,MainActivitya.class);
startActivity(intent);
}
public void startB(View v){
Intent intent=new Intent(this,MainActivityb.class);
startActivity(intent);
}
清单文件
<activity
android:name=".MainActivityb"
android:label="@string/title_activity_main_activityb"
android:launchMode="standard"//在此修改加载模式>
</activity>
<activity
android:name=".MainActivitya"
android:label="@string/title_activity_main_activitya">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
用代码设置Activity的启动模式
public void flagClick(View v){
Intent intent=new Intent(this,Main5Activity.class);
//设置Activity的启动模式
//Intent.FLAG_ACTIVITY_NEW_TASK 在新的任务栈中启动Activity,如果有,那么就在本任务中启动
//
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
常用的三个属性:
FLAG_ACTIVITY_NEW_TASK 在新的任务栈中启动Activity
FLAG_ACTIVITY_CLEAR_TASK==singleTask
FLAG_ACTIVITY_CLEAR_TOP==singleTop
3.Intent应用
显示网页:
Uri data=Uri.parse("http://www.baidu.com");
Intent intent=new Intent(Intent.ACTION_VIEW,data);
startActivity(intent);
拨打电话:调用拨号程序(拨号面板,并不直接拨打)
Uri data=Uri.parse("tel:xxxxxx");
Intent intent=new Intent(Intent.ACTION_DIAL,data);
startActivity(intent);
拨打电话:(直接拨打)
这个必须在配置文件中加入
Uri data=Uri.parse("tel:xxxxxx");
Intent intent=new Intent(Intent.ACTION_CALL,data);
startActivity(intent);
发送SMS/MMS:调用发短信的程序
Intent it=new Intent(Intent.ACTION_VIEW);
it.putExtra("sms_body","The SMS text");
it.setType("vnd.android-dir/mms-sms");
startActivity(it);
发送短信
Uri uri=Uri.parse("smsto:0800000123");
Intent it=new Intent(Intent.ACTION_SENDTO,uri);
it.putExtra("sms_body","The SMS text");
startActivity(it);
播放多媒体
Uri uri=Uri.parse("file:///sdcard/song.mp3");
Intent it=new Intent(Intent.ACTION_VIEW,uri);
//it.addFlags(it.FLAG_ACTIVITY_NEW_TASK);//非必须选项
it.setDataAndType(uri,"audio/mp3");
startActivity(it);
Unistall 程序
Uri uri=Uri.parse("package:包名");
Intent it=new Intent(Intent.ACTION_DELETE,uri);
startActivity(it);
安装apk
Uri uri=Uri.fromFile(new File("文件路径"));
String action=Intent.ACTION_VIEW;
Intent intent=new Intent();
intent.setAction(action);
intent.setDataAndType(uri,"application/vnd.android.package-archive");
startActivity(intent);