深入理解 Android 通信信使Intent和IntentFilter

                                         深入理解 Android 通信管家Intent 和IntentFilter

一、Intent对Android的核心和灵魂,是各组件之间的桥梁。四大组件分别为Activity 、Service、BroadcastReceiver、ContentProvider。

而这四种组件是独立的,它们之间可以互相调用,协调工作,最终组成一个真正的Android应用。

Intent的中文意思为“意图”,在Android中可以理解为想要做什么, 所以什么时候要用到Intent就很好理解了。

     

      Android 应用将会根据Intent来启动指定组件,至于到底启动哪个组件,则取决于Intent 的以下属性

 指定Component 属性的Intent就已经明确要启动哪个组件,因此这种方式叫显式Intent, 如果没有指定Component属性的Intent 叫隐式Intent

      Intent 对象大致包含7种属性,
                  Component、Action、Category、Data、Type、Extra和Flag 

     1、Component属性需要接收一个ComponentName对象,ComponentName对象包含如下几个构造器。

              ComponentName(String pkg,String cls): 创建pkg所在包下的cls类所对应的组件

              ComponentName(Context pkg,String cls):创建pkg所对应的包下的cls类所对应的组件。

              ComponentName(Content pkg,Class<?>cls):创建pkg 所对应的包下的cls类所对应的组件。

         这样应用程序就可以根据给定的组件类去启动特定的组件。

           除此之外Intent还包含了如下三个方法。

           setClass(Context packageContext,Class<?>cls):设置组件该Intent将要启动的组件

            setClassName(Context packageContext,String className): 设置该Intent将要启动的组件对应的类名

            setClassName(String packageName ,String className): 设置该Intent将要启动的组件对应的类名

Android 应用的Context代表了访问该应用环境信息的接口,而Android应用的包名则作为应用的唯一标识,因此Android应用的Context 对象与该应用的包名一一对应关系。上面的三个setClass()方法就是制定了包名(分别通过Context指定或String指定)和组件的实现类(分别通过Class指定或通过String指定)

             

2.当Intent没有指定Component属性,要启动的组件就需要配置IntentFilter。通过匹配Action和Category来判断要启动的组件

  Intent 的Action、Category都是一个普通的字符串,其中Action代表该Intent所要完成的一个抽象“动作”,而Category则用于为Action增加额外的附加类别信息。通常Action属性会与Category属性结合使用,因为Action只能指定一个,Category 可以指定多个,也就会出现有可能Action相同,

 下面看一个显式意图的例子

ComponentAttr.java

package org.crazyit.intent;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ComponentAttr extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Button bn = (Button) findViewById(R.id.bn);
		// 为bn按钮绑定事件监听器
		bn.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0)
			{
				// 创建一个ComponentName对象
				ComponentName comp = new ComponentName(ComponentAttr.this,
						SecondActivity.class);
				Intent intent = new Intent();
				// 为Intent设置Component属性
				intent.setComponent(comp);
//				Intent intent = new Intent(ComponentAttr.this,
//					SecondActivity.class);
				startActivity(intent);
			}
		});
	}
}

SecondActivity.java

/**
 *
 */
package org.crazyit.intent;

import android.app.Activity;
import android.content.ComponentName;
import android.os.Bundle;
import android.widget.EditText;


public class SecondActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		EditText show = (EditText) findViewById(R.id.show);
		// 获取该Activity对应的Intent的Component属性
		ComponentName comp = getIntent().getComponent();
		// 显示该ComponentName对象的包名、类名
		show.setText("组件包名为:" + comp.getPackageName()
			+ "\n组件类名为:" + comp.getClassName());
	}
}

隐式意图例子

package org.crazyit.intent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ActionAttr extends Activity
{
	public final static String CRAZYIT_ACTION =
		"org.crazyit.intent.action.CRAZYIT_ACTION";

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Button bn = (Button) findViewById(R.id.bn);
		// 为bn按钮绑定事件监听器
		bn.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0)
			{
				// 创建Intent对象
				Intent intent = new Intent();
				// 为Intent设置Action属性(属性值就是一个普通字符串)
				intent.setAction(ActionAttr.CRAZYIT_ACTION);
				startActivity(intent);
			}
		});
	}
}
SecondActivity.java

/**
 *
 */
package org.crazyit.intent;

import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;


public class SecondActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		EditText show = (EditText) findViewById(R.id.show);
		// 获取该Activity对应的Intent的Action属性
		String action = getIntent().getAction();
		// 显示Action属性
		show.setText("Action为:" + action);
	}
}


在secondActivity标签里配置IntentFilter

<activity android:name=".SecondActivity"
				android:label="@string/app_name">
			<intent-filter>
				<!-- 指定该Activity能响应Action为指定字符串的Intent -->
				<action android:name="org.crazyit.intent.action.CRAZYIT_ACTION" />
				<!-- 指定该Activity能响应Action属性为helloWorld的Intent -->
				<action android:name="helloWorld" />
				<!-- 指定该Action能响应Category属性为指定字符串的Intent -->
				<category android:name="android.intent.category.DEFAULT" />   
			</intent-filter>
		</activity>

注意:当一个Intent创建,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量,因此,虽然上面程序没有指定Category属性,但该Category已经有一个值问android.intent.category.DEFAULT的Category属性值,因此被启动Activity对应的配置元素的<intent-filter>元素里至少还包括一个如下的<category>子元素

2.带有Action和Category的例子

ActionCategoryAttr.java

package org.crazyit.intent;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;


public class ActionCateAttr extends Activity
{
	// 定义一个Action常量
	final static String CRAZYIT_ACTION = 
		"org.crazyit.intent.action.CRAZYIT_ACTION";
	// 定义一个Category常量
	final static String CRAZYIT_CATEGORY =
		"org.crazyit.intent.category.CRAZYIT_CATEGORY";

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Button bn = (Button) findViewById(R.id.bn);
		bn.setOnClickListener(new OnClickListener()
		{
			@Override
			public void onClick(View arg0)
			{
				Intent intent = new Intent();
				// 设置Action属性
				intent.setAction(ActionCateAttr.CRAZYIT_ACTION);
				// 添加Category属性
				intent.addCategory(ActionCateAttr.CRAZYIT_CATEGORY);
				startActivity(intent);
			}
		});
	}
}

SecondActivity.java

/**
 *
 */
package org.crazyit.intent;

import java.util.Set;

import android.app.Activity;
import android.os.Bundle;
import android.widget.EditText;


public class SecondActivity extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.second);
		EditText show = (EditText) findViewById(R.id.show);
		// 获取该Activity对应的Intent的Action属性
		String action = getIntent().getAction();
		// 显示Action属性
		show.setText("Action为:" + action);
		EditText cate = (EditText) findViewById(R.id.cate);
		// 获取该Activity对应的Intent的Category属性
		Set<String> cates = getIntent().getCategories();
		// 显示Action属性
		cate.setText("Category属性为:" + cates);
	}
}
xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="org.crazyit.intent"
	android:versionCode="1"
	android:versionName="1.0">
	<uses-sdk
		android:minSdkVersion="10"
		android:targetSdkVersion="17" />
	<application android:icon="@drawable/ic_launcher" android:label="@string/app_name">
		<activity android:name=".ActionCateAttr"
				android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
		<activity android:name=".SecondActivity"
				android:label="@string/app_name">
			<intent-filter>
				<!-- 指定该Activity能响应action为指定字符串的Intent -->
				<action android:name="org.crazyit.intent.action.CRAZYIT_ACTION" />
				<!-- 指定该Activity能响应category为指定字符串的Intent -->
				<category android:name="org.crazyit.intent.category.CRAZYIT_CATEGORY" />
				<!-- 指定该Activity能响应category为android.intent.category.DEFAULT的Intent -->
				<category android:name="android.intent.category.DEFAULT" />   
			</intent-filter>
		</activity>
	</application>
	<uses-permission android:name="android.permission.READ_CONTACTS" />
	<uses-permission android:name="android.permission.WRITE_CONTACTS" />

</manifest> 
从上面我们可以看出,在第一个Activity中也配置了一个Action,一个Category,标志主程序,也要启动的窗口

3.Data属性和Type属性,data属性通常用于向Action属性提供操作的数据。Data 属性接受一个uri对象,一个URi对象通常是如下形式字符串表示

content://com.android.contacts/contacts/1

格式:scheme://host:port/path

这里如果先设置data,在设置Type ,data 会被覆盖,反过来,先设置Type,再设置data  , Type 会被覆盖

看一个例子

package org.crazyit.intent;

import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import android.app.Activity;
import android.content.Intent;

/**
 * Description:
 * <br/>website: <a href="http://www.crazyit.org">crazyit.org</a>
 * <br/>Copyright (C), 2001-2014, Yeeku.H.Lee
 * <br/>This program is protected by copyright laws.
 * <br/>Program Name:
 * <br/>Date:
 * @author Yeeku.H.Lee [email protected]
 * @version 1.0
 */
public class DataTypeOverride extends Activity
{
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	public void overrideType(View source)
	{
		Intent intent = new Intent();
		// 先为Intent设置Type属性
		intent.setType("abc/xyz");
		// 再为Intent设置Data属性,覆盖Type属性
		intent.setData(Uri.parse("lee://www.fkjava.org:8888/test"));
		Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();
	}

	public void overrideData(View source)
	{
		Intent intent = new Intent();
		// 先为Intent设置Data属性
		intent.setData(Uri.parse("lee://www.fkjava.org:8888/mypath"));
		// 再为Intent设置Type属性,覆盖Data属性
		intent.setType("abc/xyz");
		Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();
	}

	public void dataAndType(View source)
	{
		Intent intent = new Intent();
		// 同时设置Intent的Data、Type属性
		intent.setDataAndType(Uri.parse("lee://www.fkjava.org:8888/mypath"),
				"abc/xyz");
		Toast.makeText(this, intent.toString(), Toast.LENGTH_LONG).show();
	}
}

所以通过setDataAndType就不会覆盖,xml 中这样配置

<data android:mimeType=""
      android:scheme=""
      android:host=""
      android:port=""
      android:path=""
      android:pathPrefix=""
      android:pathPattern=""/>

其中没有指定host,port就不起作用,path也不起作用




 二、使用Intent 启动组件

      启动Activity 2种方式,    startActivity(Intent intent)

                                             startActivityForResult(Intent intent,int requestCode)

      启动Service 2中方式,    ComponentName  startService(Intent intent)

                                              boolean bindService(Intent service,ServiceConnection conn,int flags)

      启动BroadcastReceiver 6种方式, sendBroadcast(Intent intent)

                                                             sendBroadcast(Intent intent ,String recevierPermission)

                                                             sendOrderBroadcast(Intent intent,String recevierPermission,BroadcastReceiver resultReceiver ,Handler scheduler, int initialCode,String initialData,Bundle initialExtras)

                                                             sendOrderedBroadcast(Intent intent,String receiverPermission)

                                                             sendStickyBroadcast(Intent intent)

                                                             sendStickyOrderedBroadcast(Intent intent,BroadcastReceiver resultReceiver,Handler scheduler,int initialCode ,String initialData ,Bundle initialExtras)

                     

                      


三、其他用途大全

显示网页:Uri uri = Uri.parse("http://www.google.com"); 
Intent it   = new Intent(Intent.ACTION_VIEW,uri); 
startActivity(it); 

显示地图:
Uri uri = Uri.parse("geo:38.899533,-77.036476"); 
Intent it = new Intent(Intent.Action_VIEW,uri); 
startActivity(it); 

路径规划:
Uri uri = Uri.parse("http://maps.google.com/maps?f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en"); 
Intent it = new Intent(Intent.ACTION_VIEW,URI); 
startActivity(it); 

拨打电话:
调用拨号程序
Uri uri = Uri.parse("tel:xxxxxx"); 
Intent it = new Intent(Intent.ACTION_DIAL, uri);   
startActivity(it);   
Uri uri = Uri.parse("tel.xxxxxx"); 
Intent it =new Intent(Intent.ACTION_CALL,uri); 
要使用这个必须在配置文件中加入<uses-permission id="android.permission.CALL_PHONE" /> 




发送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("content://media/external/images/media/23"); 
Intent it = new Intent(Intent.ACTION_SEND); 
it.putExtra("sms_body", "some text"); 
it.putExtra(Intent.EXTRA_STREAM, uri); 
it.setType("image/png"); 
startActivity(it); 

发送Email
Uri uri = Uri.parse("mailto:[email protected]"); 
Intent it = new Intent(Intent.ACTION_SENDTO, uri); 
startActivity(it); 
Intent it = new Intent(Intent.ACTION_SEND); 
it.putExtra(Intent.EXTRA_EMAIL, "[email protected]"); 
it.putExtra(Intent.EXTRA_TEXT, "The email body text"); 
it.setType("text/plain"); 
startActivity(Intent.createChooser(it, "Choose Email Client"));   
Intent it=new Intent(Intent.ACTION_SEND);     
String[] tos={"[email protected]"};     
String[] ccs={"[email protected]"};     
it.putExtra(Intent.EXTRA_EMAIL, tos);     
it.putExtra(Intent.EXTRA_CC, ccs);     
it.putExtra(Intent.EXTRA_TEXT, "The email body text");     
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");     
it.setType("message/rfc822");     
startActivity(Intent.createChooser(it, "Choose Email Client")); 

添加附件
Intent it = new Intent(Intent.ACTION_SEND); 
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); 
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3"); 
sendIntent.setType("audio/mp3"); 
startActivity(Intent.createChooser(it, "Choose Email Client")); 

播放多媒体
Intent it = new Intent(Intent.ACTION_VIEW); 
Uri uri = Uri.parse("file:///sdcard/song.mp3"); 
it.setDataAndType(uri, "audio/mp3"); 
startActivity(it); 
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1"); 
Intent it = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(it);
   
Uninstall 程序
Uri uri = Uri.fromParts("package", strPackageName, null); 
Intent it = new Intent(Intent.ACTION_DELETE, uri); 
startActivity(it); 

Install 程序
Uri installUri = Uri.fromParts("package", "xxx", null); 
returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri); 
//搜索应用 
Uri uri = Uri.parse("market://search?q=pname:pkg_name");   
Intent it = new Intent(Intent.ACTION_VIEW, uri);   
startActivity(it);   
//where pkg_name is the full package path for an application   
//显示指定应用的详细页面(这个好像不支持了,找不到app_id) 
Uri uri = Uri.parse("market://details?id=app_id");   
Intent it = new Intent(Intent.ACTION_VIEW, uri);   
startActivity(it);   
//where app_id is the application ID, find the ID   
//by clicking on your application on Market home   
//page, and notice the ID from the address bar 
打开另一程序
Intent i = new Intent();    
   ComponentName cn = new ComponentName("com.drip.android2",    
                   "com.drip.android2.AndroidSearch");    
         i.setComponent(cn);    
         i.setAction("android.intent.action.MAIN");    
         startActivityForResult(i, RESULT_OK); 
 
打开联系人列表
<1>              
    Intent i = new Intent();    
    i.setAction(Intent.ACTION_GET_CONTENT);    
    i.setType("vnd.android.cursor.item/phone");    
    startActivityForResult(i, REQUEST_TEXT);    
  
   <2>    
   Uri uri = Uri.parse("content://contacts/people");    
   Intent it = new Intent(Intent.ACTION_PICK, uri);    
   startActivityForResult(it, REQUEST_TEXT);    
打开录音机
Intent mi = new Intent(Media.RECORD_SOUND_ACTION);    
         startActivity(mi); 
 
  从gallery选取图片   
Inten t i = new Intent();  
  i.setType("image/*");    
       i.setAction(Intent.ACTION_GET_CONTENT);    
       startActivityForResult(i, 11);  
 
打开照相机
<1>Intent i = new Intent(Intent.ACTION_CAMERA_BUTTON, null);    
          this.sendBroadcast(i);    
    <2>long dateTaken = System.currentTimeMillis();    
         String name = createName(dateTaken) + ".jpg";    
         fileName = folder + name;    
         ContentValues values = new ContentValues();    
         values.put(Images.Media.TITLE, fileName);    
         values.put("_data", fileName);    
         values.put(Images.Media.PICASA_ID, fileName);    
         values.put(Images.Media.DISPLAY_NAME, fileName);    
         values.put(Images.Media.DESCRIPTION, fileName);    
         values.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, fileName);    
         Uri photoUri = getContentResolver().insert(    
                   MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);    
              
         Intent inttPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    
         inttPhoto.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);    
         startActivityForResult(inttPhoto, 10);  
  
播放多媒体
Intent it = new Intent(Intent.ACTION_VIEW);    
Uri uri = Uri.parse("file:///sdcard/song.mp3");    
it.setDataAndType(uri, "audio/mp3");    
startActivity(it);    


或者   
Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");      
Intent it = new Intent(Intent.ACTION_VIEW, uri);      
startActivity(it);    
    
或者   
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");   
returnIt = new Intent(Intent.ACTION_VIEW, playUri);   
发送Email
Uri uri = Uri.parse("mailto:[email protected]");
Intent it = new Intent(Intent.ACTION_SENDTO, uri);
startActivity(it);
 
或者:
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, address);
intent.putExtra(Intent.EXTRA_SUBJECT, filename);
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + filename)); ;
intent.setType("text/csv");
startActivity(Intent.createChooser(intent, "EMail File"));
 
或者:
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL, "[email protected]");
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.setType("text/plain");
startActivity(Intent.createChooser(it, "Choose Email Client"));
 
或者:
Intent it=new Intent(Intent.ACTION_SEND);
String[] tos={"[email protected]"};
String[] ccs={"[email protected]"};
it.putExtra(Intent.EXTRA_EMAIL, tos);
it.putExtra(Intent.EXTRA_CC, ccs);
it.putExtra(Intent.EXTRA_TEXT, "The email body text");
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.setType("message/rfc822");
startActivity(Intent.createChooser(it, "Choose Email Client"));
 
或者:
Intent it = new Intent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");
it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");
sendIntent.setType("audio/mp3");
startActivity(Intent.createChooser(it, "Choose Email Client"));


 后台发送短信
注册权限
<uses-permission android:name="android.permission.SEND_SMS" />
代码实现 :
// 获取信息内容
String message ;
// 移动运营商允许每次发送的字节数据有限,我们可以使用Android给我们提供 的短信工具。
if (message != null) {
SmsManager sms = SmsManager.getDefault();
// 如果短信没有超过限制长度,则返回一个长度的List。
List<String> texts = sms.divideMessage(message);
for (String text : texts) {
sms.sendTextMessage(“这里是接收者电话号码”,  “这里是发送者电话号码”,  “这里是短信内容”,  null, null);
}
}
//说明
sms.sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent):
destinationAddress:接收方的手机号码
scAddress:发送方的手机号码
text:信息内容
sentIntent:发送是否成功的回执,
DeliveryIntent:接收是否成功的回执,
 
从google搜索内容
Intent intent = new Intent();    
intent.setAction(Intent.ACTION_WEB_SEARCH);    
intent.putExtra(SearchManager.QUERY,"searchString")    
startActivity(intent);  
APK 安装
Intent intent =new Intenet();


String filepath="/SDCard/XXX.apk";
intent.setDataAndType(Uri.parse("file://" + filepath),"application/vnd.android.package-archive");
starActivity(intent);




猜你喜欢

转载自blog.csdn.net/ustory/article/details/42742635