作为不同UI间通信的信使,Intent相当于各个Activity间的桥梁,Activity之间通过Intent进行交互,可以通过Intent启动另外的Activity、启动Service、发起广播Broadcast等,并通过Buddle传递数据,Intent的使用方式有以下3种:
第一种,通过startActivity()来启动一个新的Activity,一般需要调用Context.startActivity或Context.start Activity For Result()来传递Intent。第二种,通过broadcast机制可以将一个Intent发送给任何对这个Intent感兴趣的Broadcast Receiver,此时一般通过Context.sendBroadcast()、Context.sendOrderedBroadcast()或Context.sendStickyBroadcast()方法传递。第三种,当BroadcastIntent被广播后,所有IntentFilter过滤条件满足的组件都将会被激活。当需要启动或绑定一个Service组件时,会通过Context.startService(Intent)和Context. Context.bindService(Intent, ServiceConnection, int)来和后台的Service交互。
Intent由组件名称、执行动作描述Action、该动作相关联的数据的描述Data、动作分类描述Category、数据类型描述Type、目标组件描述Component、附加信息描述Extras及Flag等几部分组成
。
组件名称:用于标识唯一的应用程序组件,即指明了期望的Intent组件,一般由相应组件的类名与包名组合而
Action:Action实际上是一个描述了Intent即将触发动作的名称的字符串,在Intent类中已经有一些用常量字符串表示的不同Action。
Data:Android中采用执行数据的一个URI来表示Data
Category:Category是对目标组件类别信息的描述
Extra:Extra中封装了一些额外的以键值对形式存在的附加信息。Intent通过putExtras()与getExtras()方法来存储和获取Extra。
Flag:一些有关系统如何启动组件的标志位。
Intent filter实际上相当于Intent的过滤器,一个应用程序开发完成后,需要告诉Android系统自己能够处理哪些隐性的Intent请求,这就要声明Intent filter,用于声明该应用程序接收什么样的Intent请求即可。Intent filter过滤Intent时,一般是通过Action、Data及Category三方面进行检测,检查Action、检查Data、检查Category。
Intent又可以分为显示与隐式,显式Intent直接指明要启动的组件:intent.setClass(源Activity名.this,目的Activity名.class); startActivity(intent)而隐式Intent方式没有指定component属性,因此需要Android进行解析,并将此Intent映射给可以处理此Intent的Activity、Receiver或Service,解析过程中,Android是通过Intent的action、type、category等属性来进行判断的。
Intent在传递过程中要找到目标消费者,它们往往是另一个Activity、IntentReceiver或Service一般有两种方法来匹配: 一种是直接指定目的Activity的显示匹配。另一种是隐式匹配,此时要匹配Intent的几项值1. Action的值在Android中有很多预定义,如果想直接转到自己定义的Intent接收者,可以在接收者的IntentFilter中加入一个自定义的Action值。2.Data/Type:可以用Uri来做为data。3. Category:一般不需要在Intent中设置。如果写Intent Receiver,就在AndroidManifest.xml的Activity的IntentFilter中包含android.category.DEFAULT,这样所有不设置Category的Intent都会与这个Category匹配。4. extras:是其它所有附加信息的集合。
Intent的实现:
启动同一个工程中的另一个Activity,Intent最常用的用途就是连接一个应用当中的各个Activity,启动一个特定Activity核心代码如下:
intent.setClass(源Activity名.this, 目的Activity名.class);startActivity( intent)述代码被执行后目的Activity将被创建并移到整个Activity堆栈的顶部。主Activity中部分相关代码如下(注意在AndroidManifest文件中添加对SecondActivity的说明)
public class HelloIntent_MainActivity extends Activity {
Button startBtn;//定义Button示例
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);//采用main.xml布局
startBtn = (Button)findViewById(R.id.mybutton1);//将Button实例和布局中定义的Button建立联系
startBtn.setOnClickListener(new OnClickListener() { //侦听Button被单击
public void onClick(View v) {
start();//详见下面的函数体
}});
}
void start(){
Intent intent = new Intent(HelloIntent_MainActivity.this,SecondActivity.class);
intent.setClass(this, SecondActivity.class);
startActivity(intent);//启动
}
}
AndroidManifest.xml代码:
<activity android:name=".目的Activity名称"></activity>
Activity还可以启动不同应用程序中的Activity。
public class IntentAnotherProject_MainActivity extends Activity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button startBtn = (Button)findViewById(R.id.button1);
startBtn.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
Intent intent = new Intent();
intent.setClassName("com.AbsoluteLayout","com.AbsoluteLayout.AbsoluteLayout_activity");
startActivity(intent);
break;
default:
break;
}
}
}
有时需要将想启动的Activity的描述信息放置到Intent里面,而不明确指定需要打开哪个名称的Activity,此时一般会用到Uri来描述数据,Uri代表了要操作的数据,Uri由几部分组成Content Provider(其scheme已经由Android所规定),外部调用者可以根据这个标识来找到它;路径(path,可以用来表示我们要操作的数据)。
Uri案例:
public class IntentUsageonOpenURL_MainActivity extends Activity implements View.OnClickListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button mybutton = (Button)findViewById(R.id.mybtn1);//将按钮实例mybutton和在布局中的定义关联
mybutton.setOnClickListener(this);//侦听按钮被单击事件
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.mybtn1://如果单击了指定的按钮
TextView mytv = (TextView)findViewById(R.id.mytv1);
mytv.setText(mytv.getText());
Uri myuri = Uri.parse("http://www.hnu.edu.cn");
Intent myintent = new Intent(Intent.ACTION_VIEW,myuri);//第1参数是动作,第2个是数据
startActivity(myintent);
break;
default:
break;
}
}
}
在上述代码中修改Intent相关语句,可以通过Intent播放音频,相关语句如下:
Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file:///sdcard/song.mp3");
it.setDataAndType(uri, "audio/mp3");
startActivity(it);
如在上述应用程序中将Intent部分语句换成下面的代码,则可实现拨打电话号码123456的功能
Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel:123-456"));
startActivity(intent);
举个例子,下面的是一个检查并拨号的应用程序:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);//采用默认Main.xml布局
Button mybutton=(Button)this.findViewById(R.id.Button01);//将Button实例和布局中的组件关联
mybutton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.Button01://如果单击了指定的按钮
//下面是拨打指定电话号码的程序段
EditText phonenumber=(EditText)findViewById(R.id.myEditText); ////将Edit实例和布局中的组件关联
phonenumber.setHint("请输入数字");
String strTel=phonenumber.getText().toString();
if(PhoneNumberUtils.isGlobalPhoneNumber(strTel)){
Intent myintent=new Intent(Intent.ACTION_DIAL,Uri.parse("tel://"+strTel));
startActivity(myintent);
}
else {//不合法则提示
Toast.makeText(this, "您输入的不是电话号码!",3000).show();//最后的参数是显示时间
//Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse("tel:123-456"));
//startActivity(intent);
break;
}
default:
finish();//结束
}
}
}
运行效果: