Android BroadcastReceiver的使用

BroadcastReceiver

A 、特别关注:

  • 广播接收器的生命周期:关键在于BroadcastReceiver中的onReceive()方法,从onReceive()里的第一行代码开始,onReceive()里的最后一行代码结束。
  • 一个广播到来的时候,用什么方式提醒用户是最友好的呢?第一种方式是吐司,第二种方式是通知。注:不要使用对话框,以免中断了用户正在进行的操作。

B、用途:

发送通知,更新UI或者数据,应用程序间相互通信,监听系统状态(比如开机,网络等)

 

《》普通广播的创建步骤:

1、创建一个继承自BroadcastReceiver的子类,重写onReceive()方法,在onReceive中填写广播处理代码

2、为上面创建的BroadcastReceiver子类进行配置,即配置能够启动它的<intent-filter>属性

3、在发送广播的组件中,创建启动上面的BroadCastReceiver子类的Intent实例

4、调用Context的sendBroadcast(Intent intent)方法来启动指定的BroadcastReceiver

下面介绍一下如何为BroadcastReceiver进行Intent属性的配置,

方法一:

这非常的简单,和Activity、Service的配置没有什么分别,就是在Manifest.xml文件中进行配置,只不过BroadcastReceiver配置时的根元素为<receiver……/>,如:

<receiver android:name=".MReceiver">
            <intent-filter >
                <action android:name="action.SMS_BROADCAST"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
</receiver>

 

方法二:

还可以在发送广播的java代码中,进行配置,方法如下:

比如,我们已经创建好了一个名为MReceiver的继承自BroadcastReceiver的子类,那么配置如下:

一般我们都是在Activity的onCreate方法中添加如下代码

IntentFilter filter = new IntentFilter();
  filter.addAction(SMS_BROADCAST);
  MReceiver mReceiver = new MReceiver() ;
  registerReceiver(mReceiver , filter);

 之后一般在onDestroy方法中取消注册

     //取消注册,一定要记得,不然有时系统会报错
     @Override
     protected void onDestroy() {
         super.onDestroy();
         unregisterReceiver(mReceiver);

 

需要和注意的是,使用第二种方法时,在Manifest.xml文家中并不需要对BroadcastReceiver进行任何的配置和说明,也就是说,连

<receiver android:name=”.MReceiver”/>都不用加,

(从这个例子中不难看出这样的一个问题,实际上Android中的Activity 、Service、BroadcastReceiver虽然表面上是由系统自动调用的其中的方法的,好像并不用我们创建它们的实例对象,但是在Manifest.xml文件中对他们所作的声明其实在编译阶段就是用来创建它们的实例对象的)

上面的两种方法都可以,但是其中有些许不同:

①当我们用第一中方法对BroadcastReceiver的子类进行配置的时候,并不需要显式的创建一个BroadcastReceiver对象,这种情况下,当一个Intent需要启动这个BroadcastReceiver时,系统会自动的创建一个BroadcastReceiver实例对象,当这个onReceiver()方法执行完毕后,BroadcastReceiver对象就会被销毁

②但是使用第二种方法需要显示的创建一个BroadcastReceiver对象,之后进行配置

下面举一个例子:

Activity文件

public class BroadcateMain extends Activity {
    final static String SMS_BROADCAST = "action.SMS_BROADCAST";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broadcate_main);
        IntentFilter filter = new IntentFilter();
        filter.addAction(SMS_BROADCAST);
        MReceiver mReceiver = new MReceiver() ;
        registerReceiver(mReceiver , filter);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new  Intent() ;
                intent.setAction(SMS_BROADCAST);
                intent.putExtra("msg","从远方发来贺电");
                sendBroadcast(intent);
            }
        });
    }
}

 

BroadcastReceiver文件

public class MReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context
                ,"接收到消息的Action为:"+intent.getAction()
                  +"\n消息的内容为:"+intent.getStringExtra("msg")
                , Toast.LENGTH_LONG).show();
    }
}

5、需要注意的一点是:一般不要在BroadcastReceiver的onReceive方法中执行耗时操作,也不能够开辟一条新的线程,因为BroadcastReceiver对象的生命周期更短,当BroadcastReceiver被销毁后,如果还有空线程在执行的话,在内存紧张时会自动将线程销毁,这时可以在BroadcastReceiver的onReceive方法中启动一个Service对象来处理耗时操作,具体的实现方法如下实例:

public class MyReceiver extends BroadcastReceiver{

    @Override

    public void onReceive(Context context , Intent intent){

        Intent intent = new Intent(context , MyService.class) ;

        context.startService(intent) ;
    
    }
    
}

 

《》有序广播的创建步骤

1、有序广播的创建步骤和普通广播的创建几乎一样,只有一下几点区别

2、在Manifest.xml文件中为BroadcastReceiver进行配置的时候,可以通过<intent-filter …./>的android:priority属性为BroadcastReceiver设定优先级,级别从-1000到1000,数值越大优先级越高

3、如果我们现在有多个BroadcastReceiver,并且我们为他们配置的Intent属性都一样的话,那么当一个能够启动他们的Intent发来启动请求的时候,那么这些BroadcastReceiver会按照事先设定的优先级的由高到低依次启动执行,只有高优先级的BroadcastReceiver执行完毕后,低优先级的BroadcastReceiver才能够启动执行

4、此外,当前接收到Intent信息的BroadcastReceiver能够终止Intent继续向低优先级的BroadcastReceiver的传播,只需要调用absorBroadcast()方法即可,这样所有的低优先级的BroadcastReceiver就都不会被启动了

5、当前接收到Intent信息的BroadcastReceiver能够将一些数据传递给下一个接收者,只需要调用setResultExtras(Bundle bundle)方法就能够将存在Bundle中的数据传递给下一个接收者,下一个BroadcastReceiver接收到Intent之后,调用

public Bundle getResultExtras(true)方法就能够获得上一个BroadcastReceiver传来的Bundle数据

6、而普通广播是完全异步的,也就是说,如果多个BroadcastReceiver都配置了相同的Intent 属性值,那么如果使用Intent启动这些BroadcastReceiver时,所有的BroadcastReceiver将会在几乎同一时间接收到(理论上),消息的传递效率较高,但是却不能够将处理结果传递给下一个BroadcastReceiver接收者,也无法停止Intent的传播

举例如下:

Activity文件

public class SortedBroadcast extends Activity {    
    final static String SMS = "action.SEND_SMS" ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sorted_broadcast);
        
        Button sendSMS = (Button)findViewById(R.id.sendSMS);
        sendSMS.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                Intent intent = new Intent () ;
                intent.setAction(SMS);
                intent.putExtra("msg", "从远方发来贺电");
                sendOrderedBroadcast(intent , null) ;
            }
        });
    }
}

 

MyReceiver1.java 文件

public class MyReceiver1 extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, 
                "Action:"+intent.getAction()
                +"\n消息的内容:"+intent.getStringExtra("msg")
                , Toast.LENGTH_LONG).show();
        
        //创建一个Bundle对象,并存入数据
        Bundle bundle = new Bundle() ;
        bundle.putString("value", "你怎么了?");
        setResultExtras(bundle) ;
        //取消Broadcast的继续传播
        //abortBroadcast() ;
    }
}

MyReceiver2.java文件

public class MyReceiver2 extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = getResultExtras(true) ;
        String value = bundle.getString("value");
        Toast.makeText(context , "第一个广播传来的消息:"+value , Toast.LENGTH_LONG).show(); 
    }
}

 

Manifest.xml文件:

<application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".SortedBroadcast"
            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=".MyReceiver1">
            <intent-filter android:priority="20">
                 <action android:name="action.SEND_SMS"/>
                 <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>
        <receiver android:name=".MyReceiver2">
            <intent-filter 
                android:priority="0">
                <action android:name="action.SEND_SMS"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </receiver>
    </application>

 

五、各种各样的广播: 

在android中有很多系统自带的intent.action,通过监听这些事件我们可以完成很多功能。

    1. 开机: String BOOT_COMPLETED_ACTION 广播:在系统启动后。这个动作被广播一次(只有一次)。监听: “android.intent.action.BOOT_COMPLETED”
    2. 电话拨入: String ANSWER_ACTION 动作:处理拨入的电话。监听: “android.intent.action.ANSWER”
    3. 电量变化: String BATTERY_CHANGED_ACTION 广播:充电状态,或者电池的电量发生变化。监听: “android.intent.action.BATTERY_CHANGED”
    4. 日期改变: String DATE_CHANGED_ACTION 广播:日期被改变。 监听:“android.intent.action.DATE_CHANGED”
    5. 取消更新下载: String FOTA_CANCEL_ACTION 广播:取消所有被挂起的 (pending) 更新下载。 监听:“android.server.checkin.FOTA_CANCEL”
    6. 更新开始安装: String FOTA_READY_ACTION 广播:更新已经被下载 可以开始安装。监听 “android.server.checkin.FOTA_READY”
    7. 主屏幕: String HOME_CATEGORY 类别:主屏幕 (activity)。设备启动后显示的第一个 activity。 监听:"android.intent.category.HOME”
    8. 新应用: String PACKAGE_ADDED_ACTION 广播:设备上新安装了一个应用程序包。监听: “android.intent.action.PACKAGE_ADDED”
    9. 删除应用: String PACKAGE_REMOVED_ACTION 广播:设备上删除了一个应用程序包。监听: “android.intent.action.PACKAGE_REMOVED”
    10. 屏幕关闭: String SCREEN_OFF_ACTION 广播:屏幕被关闭。监听: “android.intent.action.SCREEN_OFF”
    11. 屏幕开启: String SCREEN_ON_ACTION 广播:屏幕已经被打开。 监听:“android.intent.action.SCREEN_ON”
    12. 时区改变: String TIMEZONE_CHANGED_ACTION 广播:时区已经改变。监听: “android.intent.action.TIMEZONE_CHANGED”
    13. 时间改变: String TIME_CHANGED_ACTION 广播:时间已经改变(重新设置)。 “android.intent.action.TIME_SET”
    14. 时间流逝: String TIME_TICK_ACTION 广播:当前时间已经变化(正常的时间流逝)。 “android.intent.action.TIME_TICK”
    15. 进入大容量存储模式: String UMS_CONNECTED_ACTION 广播:设备进入 USB 大容量存储模式。 “android.intent.action.UMS_CONNECTED”
    16. 退出大容量存储模式: String UMS_DISCONNECTED_ACTION 广播:设备从 USB 大容量存储模式退出。 “android.intent.action.UMS_DISCONNECTED”
    17. 壁纸改变: String WALLPAPER_CHANGED_ACTION 广播:系统的墙纸已经改变。 “android.intent.action.WALLPAPER_CHANGED”
    18. web搜索: String WEB_SEARCH_ACTION 动作:执行 web 搜索。 “android.intent.action.WEB_SEARCH”
    19. 网络变化: String CONNECTIVITY_CHANGE_ACTION 动作:网络变化。“android.intent.action.CONNECTIVITY_CHANGE_ACTION”

《》LocalBroadcastManager本地广播——可以用来代替Handler更新UI

在android-support-v4.jar中引入了LocalBroadcastManager,称为局部通知管理器,这种通知的好处是安全性高,效率也高,适合局部通信,

之前我们发送和接收的广播全部都是属于全局广播,即发出去的广播可以被其他任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样一来,必然会造 成安全问题。于是便有了本地广播:即只能在本应用程序中发送和接收广播。这就要使用到了LocalBroadcastManager这个类来对广播进行管理。

下面举一个例子就会非常容易的掌握这个局部广播的用法

 

package com.example.broadcasttest;

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.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {
    private IntentFilter intentFilter;

    private LocalReceiver localReceiver;

    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //通过LocalBroadcastManager的getInstance()方法得到它的一个实例
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(
                        "com.example.broadcasttest.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent);//调用sendBroadcast()方法发送广播
            }
        });
        //动态注册本地的广播接收器
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);
    }

    class LocalReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "received local broadcast",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

注:本地广播是无法通过静态注册的方式来接收的

 

posted @ 2014-11-11 21:32  RoperLee  阅读(1370)  评论(0)    收藏  举报