一、Intent概述
Android中提供了Intent机制来协助各应用间的交互与通信。Intent负责对应用中一次操作的动作、动作涉及到的数据、附加数据等进行描述,Android则根据此Intent的描述,负责找到对应的组件,将相应数据传递给调用的组件并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内部的Activity/Service之间的交互。因此,Intent在这里起着一个中介的作用,它专门提供组件相互调用的相关信息。
Intent的另一个用途是发送广播消息。应用程序和Android系统都可以使用Intent发送广播消息,广播消息的内容可以是与应用程序密切相关的数据信息,也可以是Android的系统信息,例如网络连接变化、电池电量变化、接收到短信和系统设置变化等。如果应用程序注册了BroadcastReceiver,则可以接收到指定的广播信息。
可见,作为不同UI间通信的信使,Intent相当于各个Activity间的桥梁。Activity之间通过Intent进行交互,可以通过Intent启动另外的Activity、启动Service、发起广播Broadcast等,并可通过Bundle传递数据。Intent的使用方式有以下3种:
方式一:通过startActivity()来启动一个新的Activity,一般需要调用Context.startActivity()或Context.startActivityForResult()来传递Intent。
方式二:通过Broadcast机制可以将一个Intent发送给任何对这个Intent感兴趣的BroadcastReceiver,此时一般通过context.sendBroadcast()、contex.sendOrderedBroadcast()或context.sendStickyBroadcast()方法传递。当Broadcast Intent被广播后,所有Intent-filter过滤条件满足的组件都将被激活。
方式三:当需要启动或绑定一个Service组件时,会通过context.startService(Intent)和context.bindService(Intent, ServiceConnection, int)来和后台的Service交互。
二、Intent实现
Intent分为显式Intent和隐式Intent。通过示例工程LearnIntent运行即可看出效果,有关讲解已作为注释夹杂在代码中,其中App1是隐式Intent跨应用启动Activity的对照工程。
LearnIntent activity_main.xml代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/btnStartMyAty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="52dp"
android:text="Start MyAty" />
</RelativeLayout>
LearnIntent MainActivity.java代码如下:
package com.example.learnintent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnStartMyAty).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
/* 显式Intent
* 直接指明被启动的类的定义
* */
// startActivity(new Intent(MainActivity.this, MyAty.class));
/* 隐式Intent
* ①Intent所传入的字符串是被启动的activity Intent-filter action的name值
* ②通过常量访问到字符串
* 优点: 通过隐式Intent配置可以跨应用启动Activity
* */
startActivity(new Intent(MyAty.ACTION));
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
LearnIntent myaty.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
LearnIntent MyAty.java代码如下:
package com.example.learnintent;
import android.app.Activity;
import android.os.Bundle;
public class MyAty extends Activity {
public static final String ACTION = "com.example.learnintent.intent.action.MyAty";
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.myaty);
}
}
LearnIntent AndroidManifest.xml部分主要代码如下:
<!-- .代表程序在运行时将name值直接与package相连接, 成为Activity类的定义的全路径; name值也可以写全路径, 例如com.example.learnintent.MyAty -->
<activity
android:name=".MyAty"
android:exported="false" >
<intent-filter >
<!-- 如果指明intent-filter的category为default, 证明intent-filter的行为方式是Activity -->
<category android:name="android.intent.category.DEFAULT"/>
<!-- action的name值可以是任意字符串, 启动时再根据该字符串启动; -->
<!-- 为了在程序中有更好的区分度, 约定俗成的格式: 包名.intent.action.指定类的名字, 通过action便知晓是哪个类; -->
<!-- 上述方式虽然有特定格式, 不变记忆, 因此编写action时, 一般情况下, 需要在被启动的Activity里面添加名字为ACTION的静态字符串类型常量; 详见MyAty.java定义和MainActivity.java引用 -->
<action android:name="com.example.learnintent.intent.action.MyAty"/>
</intent-filter>
</activity>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/btnStartMyAty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView1"
android:layout_centerHorizontal="true"
android:layout_marginTop="46dp"
android:text="Start MyAty From App1" />
</RelativeLayout>
App1 MainActivity.java代码如下:
package com.example.app1;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btnStartMyAty).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
/* 运行应用能够成功启动MyAty */
/* 如果一个Activity只允许同一个应用内部访问, 不允许通过其它应用访问
* 需在LearnIntent工程MyAty activity配置里面添加android:exported="false"(该值默认为true)
* 运行程序出现异常, 可以通过try...catch语句捕获异常
* */
try {
startActivity(new Intent("com.example.learnintent.intent.action.MyAty"));
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(MainActivity.this, "无法启动指定的Activity", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
请仔细阅读代码和注释,运行相应部分代码便可以观察到显示Intent和隐式Intent的区别和特点。