[Android基础]Intent

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对象,它携带了返回的数据信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值