Intent的api:http://www.android-doc.com/reference/android/content/Intent.html
一.Intent的属性(详见api中Intent的Constants)
1.action,执行的动作,除了android提供的action,也可以自定义action(以包名为前缀),例如com.example.project.SHOW_COLOR
2.data,执行动作要操作的数据(以URI表示),例如content://contacts/1
3.category,被执行动作的附加信息
4.extras,附加信息
隐式Intent:
如果Intent明确指定了目标组件的类名称,则为显式Intent,否则为隐式Intent。对于隐式Intent,android会根据Intent中的信息(例如action,data,category)去查找目标组件。隐式Intent默认的category为android.intent.category.DEFAULT,所以,所有希望接收隐式Intent的目标组件都要有android.intent.category.DEFAULT这个属性。
二.Intent Filter
Intent Filter是用来描述组件能接收哪些Intent。如果是显式Intent,那么无需考虑Intent Filter,否则就要涉及到Intent Filter。
对于隐式Intent,仅当它能够通过组件的Intent Filter之一才能够传递给组件。
如果不声明Intent Filter,则只能通过显式调用。
android是通过action、data、category这三个属性来查找目标组件的。
例子:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<data android:mimeType="video/mpeg" android:scheme="http"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
1.action检查
如果Intent指明了action,则目标组件的Intent Filter必须包含这个action,否则不能匹配。
如果Intent没有指明action,则通过检查。
2.category检查
如果Intent指明了category,则目标组件的Intent Filter必须包含这个category,否则不能匹配。
如果Intent没有指明category,则通过检查。
3.data检查
每个data元素指定数据类型(mimeType)和一个URI。URI有四个属性:scheme,host,port和path,对应于URI的格式如下:
scheme://host:port/path,其中称host:port为authority
例如一个URI为:content://com.demo.service:200/folder/1
当比较Intent和Intent Filter的URI时,以Intent Filter的URI为基础,看Intent的data的URI是否匹配。
如果Intent Filter仅指定scheme,所有有此scheme的URI都匹配;
如果Intent Filter指定scheme和authority,所有匹配scheme和authority的URI都通过检查,而不管它们的path;
如果四个属性都指定了,要全部匹配才能算是匹配。当然,Intent Filter中的path一般通过包含通配符来要求匹配path中的一部分。
mimeType属性指定数据的MIME类型。Intent和Intent Filter都可以用"*"通配符匹配子类型字段,例如“text/*”,“audio/*”表示任何子类型
MIME:
1.类型:
Text:用于标准化地表示的文本信息,文本消息可以是多种字符集和或者多种格式的;
Multipart:用于连接消息体的多个部分构成一个消息,这些部分可以是不同类型的数据;
Application:用于传输应用程序数据或者二进制数据;
Message:用于包装一个E-mail消息;
Image:用于传输静态图片数据;
Audio:用于传输音频或者音声数据;
Video:用于传输动态影像数据,可以是与音频编辑在一起的视频数据格式。
2.子类型:
text/plain(纯文本)
text/html(HTML文档)
application/xhtml+xml(XHTML文档)
image/gif(GIF图像)
image/jpeg(JPEG图像)【PHP中为:image/pjpeg】
image/png(PNG图像)【PHP中为:image/x-png】
video/mpeg(MPEG动画)
application/octet-stream(任意的二进制数据)
application/pdf(PDF文档)
application/msword(Microsoft Word文件)
application/vnd.wap.xhtml+xml (wap1.0+)
application/xhtml+xml (wap2.0+)
message/rfc822(RFC 822形式)
multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示)
application/x-www-form-urlencoded(使用HTTP的POST方法提交的表单)
multipart/form-data(同上,但主要用于表单提交时伴随文件上传的场合)
3.文件类型——MIME类型的匹配表
//{后缀名, MIME类型}
{".3gp", "video/3gpp"},
{".apk", "application/vnd.android.package-archive"},
{".asf", "video/x-ms-asf"},
{".avi", "video/x-msvideo"},
{".bin", "application/octet-stream"},
{".bmp", "image/bmp"},
{".c", "text/plain"},
{".class", "application/octet-stream"},
{".conf", "text/plain"},
{".cpp", "text/plain"},
{".doc", "application/msword"},
{".exe", "application/octet-stream"},
{".gif", "image/gif"},
{".gtar", "application/x-gtar"},
{".gz", "application/x-gzip"},
{".h", "text/plain"},
{".htm", "text/html"},
{".html", "text/html"},
{".jar", "application/java-archive"},
{".java", "text/plain"},
{".jpeg", "image/jpeg"},
{".jpg", "image/jpeg"},
{".js", "application/x-javascript"},
{".log", "text/plain"},
{".m3u", "audio/x-mpegurl"},
{".m4a", "audio/mp4a-latm"},
{".m4b", "audio/mp4a-latm"},
{".m4p", "audio/mp4a-latm"},
{".m4u", "video/vnd.mpegurl"},
{".m4v", "video/x-m4v"},
{".mov", "video/quicktime"},
{".mp2", "audio/x-mpeg"},
{".mp3", "audio/x-mpeg"},
{".mp4", "video/mp4"},
{".mpc", "application/vnd.mpohun.certificate"},
{".mpe", "video/mpeg"},
{".mpeg", "video/mpeg"},
{".mpg", "video/mpeg"},
{".mpg4", "video/mp4"},
{".mpga", "audio/mpeg"},
{".msg", "application/vnd.ms-outlook"},
{".ogg", "audio/ogg"},
{".pdf", "application/pdf"},
{".png", "image/png"},
{".pps", "application/vnd.ms-powerpoint"},
{".ppt", "application/vnd.ms-powerpoint"},
{".prop", "text/plain"},
{".rar", "application/x-rar-compressed"},
{".rc", "text/plain"},
{".rmvb", "audio/x-pn-realaudio"},
{".rtf", "application/rtf"},
{".sh", "text/plain"},
{".tar", "application/x-tar"},
{".tgz", "application/x-compressed"},
{".txt", "text/plain"},
{".wav", "audio/x-wav"},
{".wma", "audio/x-ms-wma"},
{".wmv", "audio/x-ms-wmv"},
{".wps", "application/vnd.ms-works"},
//{".xml", "text/xml"},
{".xml", "text/plain"},
{".z", "application/x-compress"},
{".zip", "application/zip"},
{"", "*/*"}
还要说明的是,如果一个Intent能够通过不止一个Activity或Service的Intent Filter,android系统将弹出一个Dialog要求用户选择哪个组件被激活。但是,如果没有符合的组件,将会抛出异常。
三.在Intent中传递数据
1.通过data属性
例如:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
但是data属性只能传递数据的URI地址,如果需要传递一些数据对象,就需要利用extra了。
2.通过extra属性(略)
//
一般情况下,会将Intent获取信息的代码放到onCreate方法中,但这样也会存在着一个隐患。默认情况下,当通过Intent获取一个Activity的时候,就算已经存在一个相同的正在运行的Activity,系统都会创建一个新的Activity实例并显示出来。为了不让Activity多次实例化,需要设置Activity的启动模式为单任务模式,如:
<activity
android:name=".Main2Activity"
android:launchMode="singleTask"
android:label="@string/title_activity_main2" >
</activity>
这样,当Intent第一次启动activity时,activity实例化并调用onCreate();当Intent第二次启动activity时,activity不再实例化并调用onNewIntent()。因此,在单任务模式下,应该将Intent获取信息的代码放到onCreate()和onNewIntent()中。
//
四.在Intent中传递对象
要求对象要实现Parcelable接口
例子:
package com.example.testintent;
import java.util.HashMap;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
public String name;
public HashMap<String, String> scores = new HashMap<String, String>();
public Student()
{
name = "unknown";
scores = null;
}
//返回id
@Override
public int describeContents() {
return 0;
}
//写入信息
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeMap(scores);
}
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
@Override
public Student createFromParcel(Parcel source) {
Student student = new Student();
student.name = source.readString();
student.scores = source.readHashMap(HashMap.class.getClassLoader());
return student;
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
package com.example.testintent;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button) findViewById(R.id.next)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.example.testintent.ACTION1");
Student student = new Student();
HashMap<String, String> sc = new HashMap<String, String>();
sc.put("english", "98");
sc.put("computer", "59");
student.name = "tom";
student.scores = sc;
ArrayList<Student> al = new ArrayList<Student>();
al.add(student);
intent.putParcelableArrayListExtra("a", al);
Bundle bundle = new Bundle();
bundle.putString("username", "android");
intent.putExtra("b",bundle);
startActivity(intent);
}
});
}
}
package com.example.testintent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
public class Main2Activity extends Activity {
private String tag = getClass().getName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("b");
Log.v(tag, bundle.getString("username"));
ArrayList<Student> al = new ArrayList<Student>();
al = intent.getParcelableArrayListExtra("a");
if(al != null)
{
Student student = (Student) al.get(0);
Log.v(tag, student.name);
Iterator iterator = student.scores.entrySet().iterator();
while (iterator.hasNext())
{
Map.Entry entry = (Map.Entry)iterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue();
Log.v(tag, key + " " + value);
}
}
}
}
<activity
android:name=".Main2Activity"
android:label="@string/title_activity_main2" >
<intent-filter>
<action android:name="com.example.testintent.ACTION1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
五.实现Activity之间的协同
通过Intent,可以将数据传递给下一个Activity,那么,新启动的Activity如何将数据返回给之前的Activity呢?这时就需要startActivityForResult方法了。startActivityForResult方法将在回调方法onActivityResult中获取返回信息。
例子:
package com.example.testintent;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private int requestCode = 1;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
((Button) findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.example.testintent.ACTION1");
Bundle bundle = new Bundle();
bundle.putString("content", (String)textView.getText());
intent.putExtra("a", bundle);
startActivityForResult(intent, requestCode);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == this.requestCode)
{
if(resultCode == RESULT_OK)
{
Bundle bundle = data.getBundleExtra("b");
textView.setText(bundle.getString("newcontent"));
}
}
}
}
package com.example.testintent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class Main2Activity extends Activity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
editText = (EditText) findViewById(R.id.editText);
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("a");
editText.setText(bundle.getString("content"));
((Button) findViewById(R.id.save)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Main2Activity.this, MainActivity.class);
Bundle bundle = new Bundle();
bundle.putString("newcontent", editText.getText().toString());
intent.putExtra("b", bundle);
setResult(RESULT_OK, intent);
finish();
}
});
((Button) findViewById(R.id.abort)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_CANCELED);
finish();
}
});
}
}
重点就是void onActivityResult(int requestCode, int resultCode, Intent data)了
第一个参数为请求代码,因为一个activity可能发出多个请求,可以通过请求代码进行区分;
第二个参数为结果代码,代表请求返回的结果类型;
第三个参数为返回的Intent对象,它携带了返回的数据信息。