Android基本组件之BroadcastReceiver

BroadcastReceiver基本概念

  在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver是对程序中发送出来的Broadcast进行过滤接受并响应的一类组件。

 

如何使用BroadcastReceiver

  1.首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用 sendOrderBroadcast()、sendStickyBroadcast()方法或者sendBroadcast()方法,把 Intent对象以广播方式发送出去。

  2.当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceive()方法。

 

如何使用BroadcastReceiver

  1.首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用 sendOrderBroadcast()、sendStickyBroadcast()方法或者sendBroadcast()方法,把 Intent对象以广播方式发送出去。

  2.当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceive()方法。

 

注册BroadcastReceiver有两种方式:

  静态注册:在AndroidManifest.xml中用标签生命注册,并在标签内用标签设置过滤器。

  <receiver android:name="myRecevice">    //继承BroadcastReceiver,重写onReceiver方法

    <intent-filter>    

      <action android:name="com.dragon.net"></action> //使用过滤器,接收指定action广播

      </intent-filter>

  </receiver> 

  上面的xml文件中在AndroidManifest.xml中注册了一个名为myRecevice的继承BroadcastReceiver的类,它的过滤器定义在<intent-filter.../>标签中。

 

  动态注册:在代码中实例化一个继承BroadcastReceiver的类,并实例化过滤器,通过Activity的静态方法registerReceiver()注册。

  myReceiver = new MyReceiver(this);

  IntentFilter intentFilter = new IntentFilter();

  intentFilter.addAction(String);   //为BroadcastReceiver指定action,使之用于接收同action的广播

      registerReceiver(myReceiver,intentFilter);

 

  下面这段代码是动态注册方法的演示:

package com.example.receiverdemo;

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

public class ReceiverActivity extends Activity 
{
    private Button bind;
    private Button sent;
    private Button unbind;
    
    private MyReceiver receiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_receiver);

        bind = (Button)findViewById(R.id.bind);
        sent = (Button)findViewById(R.id.sent);
        unbind = (Button)findViewById(R.id.unbind);
        
        receiver = new MyReceiver(this);
        
        bind.setOnClickListener(new OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
                IntentFilter intentfilter = new IntentFilter();
                intentfilter.addAction("qwerty");
                
                registerReceiver(receiver, intentfilter);
            }
        });
        
        sent.setOnClickListener(new OnClickListener() 
        {   
            @Override
            public void onClick(View v) 
            {
                Intent intent = new Intent();
                intent.setAction("qwerty");
                intent.putExtra("msg", "耗子");
                sendBroadcast(intent);
            }
        });
        
        unbind.setOnClickListener(new OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
                unregisterReceiver(receiver);
            }
        });
    }
}

 

注1:对于动态注册receiver而言,一般情况下最好是在onResume方法中注册,在onPause方法中取消注册。

  之所以要这样,是因为这样可以减少Android程序的内存使用。只有在Activity运行的时候我们才注册receiver,而当Activity失去焦点的时候我们就取消了注册。(如果不理解,可以参看Activity的生命周期图)。

注2:BroadcastReciver对象的生命周期只有十秒左右,如果在 onReceive() 内做超过十秒内的事情,就会报错

  每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 所以在BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR(Application No Response) 的对话框。

 

怎么用好 BroadcastReceiver :

  如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 。这里不能使用子线程来解决 , 因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束BroadcastReceiver 就先结束了 。BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的所在进程很容易在系统需要内存时被优先杀死 。因为它属于空进程 ( 没有任何活动组件的进程 )。如果它的宿主进程被杀死 ,那么正在工作的子线程也会被杀死 。所以采用子线程来解决是不可靠的 。

 

 

进一步的补充:

Broadcast 类型

在本文中我们暂时只介绍两种Broadcast

1.Normal Broadcast 普通广播

  发送这种广播,能够在同一时刻(逻辑上)被所有的注册的接收者收到,它的效率比较高。

  缺点:不能将结果传递给下一个接受者,而且不能终止Broadcast Intent的传播。

  在Activity中通过静态方法sendBroadcast()方法发送。

2.Ordered Broadcast 有序广播

  接收者将按照预想声明的优先级一次接收Broadcast。优先级声明在<intent-filter .../>的android:priority属性中,也可以在代码中调用IntentFilter的setPriority()方法进行设置。优先级的取值范围为-1000~1000,数值越大优先级越高。

  通过接收者setResultExtras()将结果传递给下一个接受者,通过abrotBroadcast()方法终止Broadcast的继续传播。下一个接收者通过getResultExtras()方法获取上一个接收者的结果。

  在Activity中通过静态方法sendOrderedBroadcast()方法发送。

 

  下面这段代码演示不同优先级别的receiver的接收情况:

 

package com.example.receiverdemo;

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

public class ReceiverActivity extends Activity 
{
    private Button bind;
    private Button sent;
    private Button unbind;
    
    private MyReceiver receiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_receiver);

        bind = (Button)findViewById(R.id.bind);
        sent = (Button)findViewById(R.id.sent);
        unbind = (Button)findViewById(R.id.unbind);
        
        receiver = new MyReceiver(this);
        
        bind.setOnClickListener(new OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
                IntentFilter intentfilter = new IntentFilter();
                intentfilter.addAction("qwerty");
                intentfilter.setPriority(999);
                registerReceiver(receiver, intentfilter);
            }
        });
        
        sent.setOnClickListener(new OnClickListener() 
        {   
            @Override
            public void onClick(View v) 
            {
                Intent intent = new Intent();
                intent.setAction("qwerty");
                intent.putExtra("msg", "耗子");
                sendOrderedBroadcast(intent, null);
            }
        });
        
        unbind.setOnClickListener(new OnClickListener() 
        {
            @Override
            public void onClick(View v) 
            {
                unregisterReceiver(receiver);
            }
        });
    }
}

 

 

 

package com.example.receiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

public class MyReceiver extends BroadcastReceiver
{
    private Context context;
    
    public MyReceiver(Context context)
    {
        this.context = context;
    }
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        String msg = intent.getStringExtra("msg");
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        Bundle extras = new Bundle();
        extras.putString("test", "mouse");
        setResultExtras(extras);
    }

}

 

package com.example.receiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

public class MyReceiver1 extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        Bundle bundle = getResultExtras(true);
        String text = bundle.getString("test");
        String msg = intent.getStringExtra("msg");
        
        Toast.makeText(context, msg+text, Toast.LENGTH_SHORT).show();
        
        abortBroadcast();
    }

}

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.receiverdemo"
    android:versionCode="1"
    android:versionName="1.0" >

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.receiverdemo.ReceiverActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <receiver
            android:name = "com.example.receiverdemo.MyReceiver1">
            <intent-filter android:priority="0">
                <action android:name="qwerty"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/bind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注册" />
    <Button
        android:id="@+id/sent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送" />
    <Button
        android:id="@+id/unbind"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="注销" />

</LinearLayout>

 

 

posted @ 2013-09-25 15:56  火小邪123  阅读(290)  评论(0编辑  收藏  举报