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. 解决iReport打不开的一种方法

    解决iReport打不开的一种方法 iReport版本:iReport-5.6.0-windows-installer.exe 系统:Win7 64位 JDK:1.7 在公司电脑安装没问题,能打开,但 ...

  2. 使用Recyclerview实现图片水平自动循环滚动

    简介: 本篇博客主要介绍的是如何使用RecyclerView实现图片水平方向自动循环(跑马灯效果) 效果图: 思路: 1.准备m张图片 1.使用Recyclerview实现,返回无数个(实际Inter ...

  3. 宏定义(无参宏定义和带参宏定义),C语言宏定义详解

    1.宏定义说明 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中所有宏名,替换成宏 ...

  4. [SinGuLaRiTy] 2017 百度之星程序设计大赛 初赛A

    [SinGuLaRiTy-1036] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 小C的倍数问题 Time Limit: 2000/100 ...

  5. 查看服务器的ip地址

    因测试需要查看服务器的ip地址,故进行搜索. 1.(操作成功的方法)在浏览器输入www.ip.cn,可查询出ip地址: 2.(说明书的操作方法,但我未能查询到ip地址)在浏览器输入http://ip. ...

  6. 洛谷P4526 【模板】自适应辛普森法2(Simpson法)

    题面 传送门 题解 据说这函数在\(x>15\)的时候趋近于\(0\) 据说当且仅当\(a<0\)时积分发散 所以直接套自适应\(simpson\)吧-- //minamoto #incl ...

  7. mysql设计-基本操作

    mysql 设计 1)服务器管理 2)数据库管理 3)表管理 4)字段管理 5)索引管理 操作 1)sql语句 2)单表操作 3)多表操作 索引 记录 字段 mysam innodb ibdata1 ...

  8. 最近关于linux的一些小问题。

    redhat 用yum更新时需要注册付费.centos 不用. 原来版本的ifconfig 在centos中变为了ip addr.

  9. TX2 dts、dtb编译与反编译

    设备树(Device Tree)包括DTC(device tree compiler),DTS(device tree source和DTB(device tree blob). dtc编译器能够把 ...

  10. TX2中设备树烧写

    将要修改的设备树文件拷贝到下面的目录替换相应的文件 ../64_TX2/Linux_for_Tegra_tx2/kernel/dtb 用micro-USB线连接TX2上的USB OTG口和PC机的US ...