Android应用程序的基本组件,这些基本组建除了Content Provider之外,几乎全部都是依靠Intent对象来激活和通信的。

下面介绍Intent类,并通过例子来说明Intent一般用法

1.1 Intent类简介

Intent类的对象是组件间通信的载体,组件之间进行通信就是一个个Intent对象在不断地传递。Intent对象主要作用于运行在相同或不同应用程序的Activity,Service和Broadcast Receiver组件之间,对于这3种组件,其作用机制也不相同

一,对于Activity组件,Intent主要通过调用Context.startActivity,Context.startActivityForResult等方法实现传递,其结果是启动一个新的Activity或者使当前的Activity开始新的任务。

二,对于Service组件,Intent主要通过Context.startService和Context.bindService方法实现传递,其作用结果是初始化并启动一个服务或者绑定服务到Context对象。

三,对于Broadcast Receiver组件,Intent主要通过sendBroadcast等一系列发送广播的方法实现传递,其作用结果是将Intent组件以广播的形式发出以便合适的组件接收

一个Intent对象就是一组信息,其包含接收Intent组件所关心的信息(如Action 和 Data)和Android系统关系的信息(如Category),一般来讲,一个Intent对象包含如下内容

1.1.1 Component Name部分

组件名称指明了未来要处理Intent的组件,组件名称封装在一个ComponentName对象中,该对象用于唯一标识一个应用程序组件,如Activity,Service,Content Provider等。ComponontName类包含两个String成员,分别代表组件的全程类名和包名,包名必须和AndroidMainfest.xml中<application>标记中的对应信息一致。

对于Intent对象来说,组件名称不是必须的,如果添加了组件名称则该Intent为“显示Intent”,这样Intent在传递的时候会直接根据ComponentName对象的信息去寻找目标组件。如果不设置组件名称,则为“隐式Intent”,Android会根据Intent中的其他信息来确定应该响应Intent的组件是哪个。

1.1.2 Action部分

Action为一个字符串对象,其描述了该Intent会触发的动作。Android系统中已经预先设定好了一些表征Action的常量,如ACTION_CALL,ACTION_MAIN等,同时,开发人员也可以自己定义Intent的动作描述,一般来讲,自己定义Action字符串应该以应用程序的包名为前缀,如可以定义一个Action为“karat.zhan.StartService”.

因为Action很大程度上觉得了一个Intent的内容(主要是Data和Extras部分),所以定义自己的Action时应该坐到见名知义,同时如果应用程序比较复杂,应该为其定一个整体的Action协议,使所有的Action集中管理

1.1.3 Data部分

Data描述Intent的动作所操作到的数据的URI及类型,不同的Action对应不同的操作数据,比如Action为ACTION_VIEW的Intent的Data应该是“http:”格式的URI.当前组件进行Intent的匹配检查时,正确设置Data的URI资源和数据类型很重要。

1.1.4 Category部分

Category为字符串对象,其包含了可以处理Intent的组件的类别信息,Intent中可以包含任意个Category。同Action一样,Android一样,Android系统预先定义了一些Category常量,但是不可以自定义Category.

调用方法addCategory用来为Intent添加一个Category,方法removeCategory用来移除一个Category;getCategories方法返回已定义的Category

1.1.5 Extras部分

Extras是一组键值对,其包含需要传递给目标组件并由其处理的一些额外信息。

1.1.6 Flags部分

一些有关系统如何启动组件的标志位,所有的标志位都已在Android系统中预先定义

2 IntentFilter类简介

当Intent在组件之间进行传递时,组件如果需要告知Android系统自己能够响应和处理哪些Intent,就需要使用IntentFilter对象。顾名思义,IntentFilter对象负责过滤掉组件无法响应和处理的Intent,只将自己关心的Intent接收进来进行处理。

IntentFilter实行“白名单”管理,即只用列出组件乐于接收的Intent,IntentFilter只会过滤掉隐式Intent,显示的Intent会被直接传递到目标组件,一个隐式的Intent只有通过了组件的某一个IntentFilter的过滤,才可以被组建接收并处理。

像Activity,Service,Broadcast Receiver这些组件可以有一个或者多个IntentFilter,每个IntentFilter相互独立,只需要通过一个即可。每个IntentFilter都是android.content包下的IntentFilter类的对象,除了用于过滤广播的IntentFilter可以在代码中创建外,其他组件的IntentFilter必须在AndroidMainfest.xml文件中进行声明

IntentFilter中具有与Intent对应的用于过滤Action,Data和Category的字段,一个Intent对象要想被一个组件处理,必须通过这三层的检查

2.1 检查Action

尽管一个Intent只可以设置一种Action,一个IntentFilter却可以持有一个或多个Action用于过滤,到达的Intent对象只需要匹配期中一个Action即可。但是IntentFilter的Action部分不可以为空,如果Action部分为空则会过滤掉所有Intent,相反,将通过所有的IntentFilter的Action检查

2.2 检查Data

同Action一样,IntentFilter中的Data部分也可以是一个或者多个,也可以没有。每个Data包含的内容为URI和数据类型,进行Data检查时主要也是对这两点进行比较,比较规则如下:

一,如果Intent对象没有设置Data,只有IntentFilter也未作设置时才可以通过检查;

二,如果Intent对象只设置了URI而没有指定数据类型,只有当其匹配IntentFilter的URI,并且IntentFIlter也米有设置数据类型时该Intent对象才可以通过检查。

三,如果Intent对象只指定了数据类型而没有设置URI,只有当其匹配IntentFIlter的数据类型,并且也没有设置URI时该Intent对象才可以通过检查。

四,如果Intent对象既包含了URI又包含了数据类型,只有当其数据类型匹配IntentFilter中的数据类型并且通过了URI检查时该Intent对象才可以通过检查。

2.3 检查Category

IntentFilter中可以设置多个Category,检查Category时,只有当Intent对象中所有的Category都匹配IntentFilter中的Category时该Intent对象才可以通过检查,并且IntentFilter中的Category可以比Intent中的Category多,但是必须都包含Intent对象中所有的Category.如果一个Intent没有设置Category,则将通过所有IntentFilter的Category检查。

IntentFilter既可以在AndroidMainfest.xml中声明,也可以在代码中动态创建。如果实在AndroidMainfest.xml中声明IntentFilter,需要使用<intent-filter>标记。该标记包含<action>,<data><category>子标签,每个子标签中包含的属性以及对应的方法如下:

子标签        属性                                       说明                                                 对应方法

<action>      name                    字符串,系统预定义或者自己定义                        addAction(string)

<category>  name                                    字符串                                            addCategory(String)

mimeType                数据类型,可以使用通配符                              addDataType(String)

scheme                       这四个部分共同组成了                                 addDataScheme(String)

<data>        host                             RUI,其格式为:                                         addDataAuthority(String)

port                      scheme://host:port/path,                              addDataPath(String)

path                   例如content://karant.zhan:200/files

如果一个到来的Intent对象通过乐意不止一个组件(如Activity,Service等)的IntentFilter的检查,那么系统将会弹出提示,让用户选择激活哪个组件。

下面用三个例子来对Intent进行介绍:

实例1.与Android系统组件通信

本例使用Intent和IntentFilter与Android系统预定义组拨号程序进行通信

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
    android:id="@+id/button"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="拨号"
    />
</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="karant.zhan"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".IntentToSystem"
                  android:label="@string/app_name">
            
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
             <action android:name="android.intent.action.CALL_BUTTON" />
             <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

</application>
    <uses-sdk android:minSdkVersion="8" />

</manifest>

Activity类代码:

package karant.zhan;

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 IntentToSystem extends Activity {
    Button button;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        button = (Button)findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener(){  //监听按钮

@Override
   public void onClick(View v) {
    Intent myIntent = new Intent(Intent.ACTION_DIAL);  //创建Intent对象
    IntentToSystem.this.startActivity(myIntent);   //启动Android内置的拨号程序
    
   }  
         
        });
    }
}

运行效果:

实例2:下面将会是一个应用程序内部组件之间通过Intent和Broadcast Receiver组件通信的例子

在Activity组件中通过单机按钮启动一个Service,Service将会启动一个线程,该线程的工作是定时产生一个随机数,将其封装到Intent对象中传递给Activity,Activity接收到Intent后提取期中的信息将其显示到TextView控件中。单击停止来停止服务

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
       android:id="@+id/buttonStart"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="开始"
    />    
    <Button
    android:id="@+id/buttonStop"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="停止"
    />  
<TextView  
    android:id="@+id/textView"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="未连接"
    />
</LinearLayout>

AndroidMainfest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="karant.zhan"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".IntentToBR"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 <service android:name=".MyService" android:process=":remote" >
   <intent-filter>
    <action android:name="karant.zhan.Myservice"/>
   </intent-filter>
  </service>
    </application>
    <uses-sdk android:minSdkVersion="8" />

</manifest>

Activity类代码:

package karant.zhan;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class IntentToBR extends Activity {
    
 public static final int CMD_STOP_SERVICE = 0;
 Button buttonStart;              //开始服务Button对象引用
 Button buttonStop;               //停止服务Button对象引用
 TextView textView;               //TextView对象引用
 DataReceiver dataReceiver;       //BroadcastReceiver对象
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        buttonStart = (Button)findViewById(R.id.buttonStart);
        buttonStop  = (Button)findViewById(R.id.buttonStop);
        textView = (TextView)findViewById(R.id.textView);
        
        buttonStart.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    Intent myIntent = new Intent(IntentToBR.this, karant.zhan.MyService.class);  
    IntentToBR.this.startService(myIntent);    //发送Intent启动Service
   }
  });
        
        buttonStop.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View arg0) {
    Intent myIntent =  new Intent(); //创建Intent对象
    myIntent.setAction("karant.zhan.IntentToBR");
    myIntent.putExtra("cmd", CMD_STOP_SERVICE);
    sendBroadcast(myIntent);  //发送广播
  }
  });
    }
   
    @Override
    protected void onStart() {
     dataReceiver = new DataReceiver();
     IntentFilter filter =  new IntentFilter();  //创建IntentFilter对象
     filter.addAction("karant.zhan.IntentToBR");
     registerReceiver(dataReceiver, filter);  //注册Broadcast Rceiver
     super.onStart();
    }
    
    @Override
    protected void onStop() {
     unregisterReceiver(dataReceiver); //取消注册Broadcast Receiver
     super.onStop();
    }
    
    private class DataReceiver extends BroadcastReceiver{

@Override
  public void onReceive(Context context, Intent intent) {  //重写onReceive方法
   //下面两行代码从接收到的Intent对象中取出Extra部分的信息并将其作为TextView的显示内容
   double data = intent.getDoubleExtra("data", 0);
   textView.setText("Service的数据为:"+ data);
   
   
  }  //继承自BroadcastReceiver的子类
     
    }
}

MyService类代码:

package karant.zhan;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;

public class MyService extends Service{

CommandReceiver cmdReceiver;  //继承自BroadcastReceiver的子类
 boolean flag;                 //线程执行的标志位
 
 
 
 @Override
 public void onCreate() {
  flag = true;
  cmdReceiver =  new CommandReceiver();
  super.onCreate();
 }

@Override
 public IBinder onBind(Intent intent) {
  //重写onBind
  return null;
 }

//重写onStartCommand
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
     IntentFilter filter = new IntentFilter();  //创建IntentFilter对象
  filter.addAction("karant.zhan.MyService");  
  registerReceiver(cmdReceiver, filter); //注册Broadcast Receiver
  doJob();    //调用方法启动线程
  return super.onStartCommand(intent, flags, startId);
    }
    
    @Override
    public void onDestroy() {
     this.unregisterReceiver(cmdReceiver);  //重写onDestroy方法
     super.onDestroy();
    }
    
    
    public void doJob(){    //新建线程
     new Thread(){
      public void run() {
       while(flag){
        try {
      Thread.sleep(1000);
     } catch (Exception e) {
      e.printStackTrace();
     }
     Intent intent =  new Intent();
     intent.setAction("karant.zhan.IntentToBR");
     intent.putExtra("data", Math.random()); //以data为键以随机数为值
     sendBroadcast(intent);
       }
      }
     }.start();   
    }
    
    private class CommandReceiver extends BroadcastReceiver{

@Override
  public void onReceive(Context context, Intent intent) {
   int cmd  = intent.getIntExtra("cmd", -1); //获取Extra信息
   if(cmd == IntentToBR.CMD_STOP_SERVICE){  //如果需要停止服务
    flag = false;   //停止线程
    stopSelf();    //停止服务
   }
   
  }
     
    }
}

运行效果:

Android应用程序组件之间的通信Intent和IntentFilter的更多相关文章

  1. Android应用程序组件介绍

    应用程序组件是Android应用程序的基本构建单元.每个组件是系统进入你的应用程序的不同入口点.不是所有的组件对于用户都是实际上的入口点,有些是互相依赖的,但是每个组件都有特定的作用——每个都是唯一的 ...

  2. Android中控件之间添加分割线

    将以下view标签放置在需要分割的两个控件之间: <View android:layout_width=”match_parent” android:layout_height=”1dp” an ...

  3. Android笔记(三十一)Android中线程之间的通信(三)子线程给主线程发送消息

    先看简单示例:点击按钮,2s之后,TextView改变内容. package cn.lixyz.handlertest; import android.app.Activity; import and ...

  4. vue-组件之间的通信:

    组件之间的通信:一个组件被调用,那么里面的数据就需要从前者调用,因为在开发中组件时重复调用的,在页面中会反复使用,但是里面的数据是不一样的,谁调用这个组件谁就传递数据给这个组件,所以就要暴露一些接口, ...

  5. 从Android中Activity之间的通信说开来[转]

    http://www.cnblogs.com/virusswb/archive/2011/08/02/2124824.html 引言 最近两个星期在研究android的应用开发,学习了android应 ...

  6. android控件之间事件传递

    public boolean dispatchTouchEvent(MotionEvent ev){} 用于事件的分发.Android中全部的事件都必须经过这种方法的分发.然后决定是自身消费当前事件还 ...

  7. Android笔记(三十三) Android中线程之间的通信(五)Thread、Handle、Looper和MessageQueue

    ThreadLocal 往下看之前,需要了解一下Java的ThreadLocal类,可参考博文: 解密ThreadLocal Looper.Handler和MessageQueue 我们分析一下之前的 ...

  8. Android笔记(三十) Android中线程之间的通信(二)Handler消息传递机制

    什么是Handler 之前说过了,Android不允许主线程(MainThread)外的线程(WorkerThread)去修改UI组件,但是又不能把所有的更新UI的操作都放在主线程中去(会造成ANR) ...

  9. android和javascript之间相互通信实例分析

    1.  AndroidManifest.xml中必须使用许可 "android.permission.INTERNET", 否则会出Web page not available错误 ...

随机推荐

  1. SxsTrace使用的方法

    Windows7平台上有一个强大的SxsTrace工具,可以跟踪调试应用程序运行时需要的动态库的版本和路径.   SxsTrace使用的方法:   1.首先必须以Administrator用户身份登录 ...

  2. Jquery Call ,apply,callee

    //call function A() { name = "abc"; this.ShowName = function (val) { alert(name + ",& ...

  3. delegate Func Action Expression

    using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; na ...

  4. 以太坊系列之十一: 零起步使用remix开发智能合约

    一步一步使用remix开发智能合约 最新版的remix(2017-8-3)只能使用在线开发了,已经没有离线版本了,并且好像在线版本要FQ才能访问(自行解决). 1.打开remix 注意地址如果是htt ...

  5. 001.linux的基础优化(期中架构方面的优化)

    1. linux内核优化 第一步 cat >>/etc/sysctl.conf<<EOF net.ipv4.tcp_fin_timeout = 2 net.ipv4.tcp_t ...

  6. 十三、Node.js-fs模块(上)

    Node.js内置的fs模块就是文件系统模块,负责读写文件以及对文件进行相关操作. 下面直接可参考下面的代码进行fs模块里面基本方法的学习: /** * Created by Administrato ...

  7. python测试笔试题1

    哪一个方法用来返回变量类型? 答案 type 哪一个方法用来列出一个类下的所有属性,方法,以及变量? 答案 dir 字符串方法format是用来去掉字符串的左右空格的么? 答案 不是 python 的 ...

  8. Cygwin apt-cyg ”MD5 sum did not match”

    直接编辑apt-cyg 文件,找到md5sum,替换修改成sha512sum. # check the md5 digest=`cat "desc" | awk '/^instal ...

  9. Squid系统服务脚本

    #!/bin/bash # chkconfig: - 90 25 #其中-的意思是所有运行级别 # config: /etc/squid.conf # pidfile: /usr/local/squi ...

  10. SpringMVC中视图解析器

    视图解析器:固定写法直接coppy就行 1.dispatcherServlet-servlet.xml中添加 <!-- 视图解析器InternalResourceViewResolver --& ...