Android四大组件—BroadcastReceiver

1.BroadcastReceiver是什么?

       BroadcastReceiver从字面意思上看是广播接收者的意思,Android系统中利用广播作为一种通信的手段。这里举一个很形象的例子,在我们上学期间想必都参加过开学典礼吧,在每年的开学典礼中都会有表扬上学期成绩优秀的学生这一环节,这时候就会在讲台上广播上台领奖学生的姓名班级,下面的学生听到自己的名字后就上台领奖。其实这就是Android中广播机制的处理流程,即大喇叭—>发送广播—>所有学生接受广播—>相关的学生进行事件处理。

       Android系统在很多时候都会发送一些列的广播,比如手机的电量不足,断开网络,完成开机等,这些广播叫做系统广播,每个APP就如台下的学生一样都会接收到,如果你想让你写的APP在开机后自动运行就需要监听开机的广播。广播机制是一个典型的观察者模式,它最大的特点是发送方并不关心接收放是否接受到发送的数据,更不关心接收方在接收到数据后是如何处理的,通过这样的方式来达到发送方和接收方完全解耦合。

使用广播机制的演示效果为:


2.广播的分类

       广播分为两种类型:标准广播和有序广播

  • 标准广播:异步执行的广播,发出广播后所有的广播接收器将会在同一时间内接收到这条广播
  • 有序广播:同步执行的广播,发出广播后在同一时间只有一个广播接收器可以接收到,只有这个广播接收器处理完当前的逻辑之后才能传递给下一个广播接收器,当然前面的广播接收器可以选择继续传递给下一个还是不进行传递
3.广播的注册方式
       BroadcastReceiver既然属于Android的四大组件,就一定要进行注册,与大多数的注册方式一样分为静态注册与动态注册
  • 静态注册:静态注册需要在Manifest文件中使用<IntentReceiver>进行注册,通过静态注册可以让程序在没有运行的情况下接收到广播
       静态注册需要自定义一个类并且继承BroadcastReceiver,重写onReceive完成事务处理。接下来在AndroidManifest.xml文件中进行注册即可
       以下是监听开机的广播
       自定义一个BootCompleteReceiver继承自BroadcastReceiver并且重写onReceive
package com.example.administrator.broadcastreceiveractivity;

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

/**
 * Created by ChuPeng on 2016/12/19.
 */

public class BootCompleteReceiver extends BroadcastReceiver
{
    private final String ACTION_BOOT = "android.intent.action.BOOT_COMPLETED";
    public void onReceive(Context context, Intent intent)
    {
        if(intent.getAction().equals(ACTION_BOOT))
        {
            Toast.makeText(context, "开机完成", Toast.LENGTH_SHORT).show();
        }
    }
}
       接下来还需要在Manifest.xml文件中进行注册
<receiver android:name=".BootCompleteReceiver">
    <intent-filter>
	<action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
       还需要加入可以监听开机的权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  • 动态注册:动态注册需要在代码中指定IntentFilter,然后根据想要监听的广播添加Action,想要监听什么样子的广播就要添加相应的Action,不过在不用广播接收器的时候需要调用unregisterReceiver()方法解除注册。与静态注册不同,动态注册需要运行程序广播接收器才能接收到相应的广播
       动态注册需要自定义一个类并且继承BroadcastReceiver,重写onReceive完成事务处理。接下来在onCreate()方法中进行注册即可
      以下是监听网络变化的广播
      自定义一个NetWorkReceiver继承自BroadcastReceiver并且重写onReceive
package com.example.administrator.broadcastreceiveractivity;

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

/**
 * Created by ChuPeng on 2016/12/19.
 */

public class NetWorkReceiver extends BroadcastReceiver
{
    public void onReceive(Context context, Intent intent)
    {
        Toast.makeText(context, "网络状态发生改变", Toast.LENGTH_SHORT).show();
    }
}
       接下来在onCreate()方法 中进行注册
package com.example.administrator.broadcastreceiveractivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends BaseActivity
{
    private NetWorkReceiver broadcastReceiver;
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        //监听网络状态变化的监听
        broadcastReceiver = new NetWorkReceiver();
        IntentFilter intentFilter = new IntentFilter();
        //加入广播需要监听的行为
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        //对广播进行注册
        registerReceiver(broadcastReceiver, intentFilter);
    }

    protected void onDestroy()
    {
        super.onDestroy();
        //对广播解除注册
        unregisterReceiver(broadcastReceiver);
    }
}
4.发送普通广播
       上面所说到的都是接收系统发送的广播并且做出相应的处理逻辑,我们不仅仅可以接收系统发送的广播也可以自己发送广播,自己接收并且做出相应的处理
在发送广播前需要自定义一个接收器,在发送广播后在接收器中进行处理
发送广播分为标准广播和有序广播两种
  • 标准广播:通过sendBroadcast()方法进行发送
  • 有序广播:通过sendBroadcast()方法进行发送,可以在Manifest.xml文件中设置接收器的优先级,通过android:priority="100"进行设置,优先级越高越先接收到广播,通过abortBroadcast()截断广播继续向下一个传播。(优先级可选为:-1000~1000)
       自定义一个广播接收器
package com.example.administrator.broadcastreceiveractivity;

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

/**
 * Created by ChuPeng on 2016/12/20.
 */

public class CommonReceiver extends BroadcastReceiver
{
    private final String ACTION_COMMON = "com.example.administrator.broadcastreceiveractivity.common";
    public void onReceive(Context context, Intent intent)
    {
        if(ACTION_COMMON.equals(intent.getAction()))
        {
            Toast.makeText(context, "账号密码都是111", Toast.LENGTH_SHORT).show();
        }
    }
}
       在AndroidManifest.xml文件中对广播接收器进行注册
<receiver android:name=".CommonReceiver">
    <intent-filter>
        <action android:name="com.example.administrator.broadcastreceiveractivity.common"/>
    </intent-filter>
</receiver>
       在程序中发送一条广播,在广播接收器中的逻辑就会执行
package com.example.administrator.broadcastreceiveractivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends BaseActivity
{
    private Button messageButton;
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        messageButton = (Button) findViewById(R.id.message);
        messageButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                Intent intent = new Intent();
                intent.setAction("com.example.administrator.broadcastreceiveractivity.common");
                sendBroadcast(intent);
            }
        });
    }

    protected void onDestroy()
    {
        super.onDestroy();
        //对广播解除注册
        unregisterReceiver(broadcastReceiver);
    }
}
5.发送本地广播
       其实上面用到的普通广播是全局广播,也就是其它的应用中也能接收到我们发送的广播,这样就容易引起一些安全问题,为了解决这个问题Android为我们提供了本地广播的机制,使用该机制发出的广播只会在该应用内部传播,并且接收器也只能接收本应用发送的广播
       本地广播需要使用LocalBroadcastManager进行管理
       使用LocalBroadcastManager.getInstance()方法得到一个对象,再通过registerReceiver()方法注册广播,通过sendBroadcast()方法发送广播,通过unregisterReceiver()方法取消注册广播
在使用本地广播的时候需要注意
  • 本地广播无法通过静态注册来接收,相比全局广播来说更加高效
  • 在广播中启动Activity需要为intent中加入FLAG_ACTIVITY_NEW_TASK,使用一个新的任务栈来存放新启动的Activity,否则会报错
  • 在广播中如果要弹出AlertDialog,需要将对话框的类型设置为TYPE_SYSTEM_ALERT(alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)),否则AlertDialog将无法弹出
       接下来将要实现强制下线的功能(当账号被别人登录时,此时本账号会被强制下线)
       首先要定义一个管理Activity的类,在关闭所有Activity时使用
package com.example.administrator.broadcastreceiveractivity;

import android.app.Activity;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by ChuPeng on 2016/12/19.
 */

public class ActivityCollector
{
    private static List<Activity> activityList = new ArrayList<Activity>();
    //加入Activity
    public static void addActivity(Activity activity)
    {
        activityList.add(activity);
    }
    //删除Activity
    public static void removeActivity(Activity activity)
    {
        activityList.remove(activity);
    }
    //清除所有Activity
    public static void cleanActivity()
    {
        for(int i = 0; i < activityList.size(); i++)
        {
            if(!activityList.get(i).isFinishing())
            {
                activityList.get(i).finish();
            }
        }
    }
}
       定义一个基类BaseActivity
package com.example.administrator.broadcastreceiveractivity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

/**
 * Created by ChuPeng on 2016/12/19.
 */

public class BaseActivity extends AppCompatActivity
{
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        ActivityCollector.addActivity(this);
    }
    protected void onDestroy()
    {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}
       编写登录界面
package com.example.administrator.broadcastreceiveractivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends BaseActivity
{
    private NetWorkReceiver broadcastReceiver;
    private EditText userName;
    private EditText password;
    private Button loginButton;
    private Button messageButton;
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        //监听网络状态变化的监听
        broadcastReceiver = new NetWorkReceiver();
        IntentFilter intentFilter = new IntentFilter();
        //加入广播需要监听的行为
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        //对广播进行注册
        registerReceiver(broadcastReceiver, intentFilter);
        //初始化界面控件
        userName = (EditText) findViewById(R.id.usernameEdit);
        password = (EditText) findViewById(R.id.userpsdEdit);
        loginButton = (Button) findViewById(R.id.login);
        messageButton = (Button) findViewById(R.id.message);
        loginButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                if(userName.getText().toString().equals("111") && password.getText().toString().equals("111"))
                {
                    Intent intent = new Intent(MainActivity.this, ContentActivity.class);
                    startActivity(intent);
                }
                else
                {
                    Toast.makeText(MainActivity.this, "点击获取信息按钮获取账号密码", Toast.LENGTH_SHORT).show();
                }
            }
        });
        messageButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                Intent intent = new Intent();
                intent.setAction("com.example.administrator.broadcastreceiveractivity.common");
                sendBroadcast(intent);
            }
        });
    }

    protected void onDestroy()
    {
        super.onDestroy();
        //对广播解除注册
        unregisterReceiver(broadcastReceiver);
    }
}
       自定义一个广播接收器用来接收到广播后执行强制下线的动作
package com.example.administrator.broadcastreceiveractivity;

import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.WindowManager;

/**
 * Created by ChuPeng on 2016/12/19.
 */

public class OffLineReceiver extends BroadcastReceiver
{
    public void onReceive(final Context context, Intent intent)
    {
        AlertDialog.Builder dialog = new AlertDialog.Builder(context);
        dialog.setTitle("警告:");
        dialog.setMessage("您的账号在别处登录,请重新登陆~");
        dialog.setCancelable(false);
        dialog.setPositiveButton("确定", new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                //消除说有Activity
                ActivityCollector.cleanActivity();
                Intent intent = new Intent(context, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                //重新启动登录界面
                context.startActivity(intent);
            }
        });
        AlertDialog alertDialog = dialog.create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.show();
    }
}
       最后还需要在AndroidManifest.xml中进行注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.broadcastreceiveractivity">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".BootCompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
        <activity android:name=".ContentActivity">
        </activity>
        <receiver android:name=".CommonReceiver">
            <intent-filter>
                <action android:name="com.example.administrator.broadcastreceiveractivity.common"/>
            </intent-filter>
        </receiver>
    </application>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
</manifest>
6.常用的系统广播
广播名说明备注
Intent.ACTION_AIRPLANE_M
关闭或打开飞行模式时的广播

Intent.ACTION_BATTERY_CH
充电状态,或者电池的电量发生变化电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LO
电池电量低

Intent.ACTION_BATTERY_OK
电池电量充足

Intent.ACTION_AIRPLANE_MODE_CHANGED
关闭或打开飞行模式

Intent.ACTION_BATTERY_CHANGED
充电状态,或者电池的电量发生变化
电荷级别改变,只能在代码注册
Intent.ACTION_BATTERY_LOW
电池电量低

Intent.ACTION_BATTERY_OKAY
电池电量充足
从电池电量低变化到饱满时会发出广播
Intent.ACTION_BOOT_COMPLETED
在系统启动完成后,这个动作被广播一次
只有一次
Intent.ACTION_CAMERA_BUTTON
按下照相时的拍照按键时发出的广播
硬件按键
Intent.ACTION_CLOSE_SYSTEM_DIALOGS
当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏

Intent.ACTION_CONFIGURATION_CHANGED
设备当前设置被改变时发出的广播界面语言,设备方向,等 请参考Configuration.java
Intent.ACTION_DATE_CHANGED设备日期发生改变时
Intent.ACTION_DEVICE_STORAGE_LOW设备内存不足时发出的广播此广播只能由系统使用,其它APP不可用
Intent.ACTION_DEVICE_STORAGE_OK设备内存从不足到充足时发出的广播此广播只能由系统使用,其它APP不可用
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE移动APP完成之后,发出的广播移动是指:APP2SD
Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE正在移动APP时,发出的广播移动是指:APP2SD
Intent.ACTION_GTALK_SERVICE_CONNECTEDGtalk已建立连接时发出的广播
Intent.ACTION_GTALK_SERVICE_DISCONNECTEDGtalk已断开连接时发出的广播
Intent.ACTION_HEADSET_PLUG在耳机口上插入耳机时发出的广播
Intent.ACTION_INPUT_METHOD_CHANGED改变输入法时发出的广播
Intent.ACTION_LOCALE_CHANGED设备当前区域设置已更改时发出的广播
Intent.ACTION_MANAGE_PACKAGE_STORAGE
表示用户和包管理所承认的低内存状态通知应该开始
Intent.ACTION_MEDIA_BAD_REMOVAL
未正确移除SD卡
扩展卡已经从SD卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)
Intent.ACTION_MEDIA_BUTTON
按下”Media Button” 按键时发出的广播
有”Media Button” 按键的话(硬件按键)
Intent.ACTION_MEDIA_CHECKING
插入外部储存装置
比如SD卡时,系统会检验SD卡,此时发出的广播
Intent.ACTION_MEDIA_EJECT
已拔掉外部大容量储存设备发出的广播
不管有没有正确卸载
Intent.ACTION_MEDIA_MOUNTED
插入SD卡并且已正确安装
扩展介质被插入而且已经被挂载
Intent.ACTION_MEDIA_NOFS
拓展介质存在,但使用不兼容FS(或为空)的路径安装点检查介质包含在Intent.mData领域

Intent.ACTION_MEDIA_REMOVED
外部储存设备已被移除,扩展介质被移除
不管有没正确卸载,都会发出此广播
Intent.ACTION_MEDIA_SCANNER_FINISHED
已经扫描完介质的一个目录

Intent.ACTION_MEDIA_SCANNER_SCAN_FILE
请求媒体扫描仪扫描文件并将其添加到媒体数据库

Intent.ACTION_MEDIA_SCANNER_STARTED
开始扫描介质的一个目录

Intent.ACTION_MEDIA_SHARED
扩展介质的挂载被解除 (unmount)
它已经作为 USB 大容量存储被共享
Intent.ACTION_PACKAGE_ADDED
成功的安装APK
数据包括包名(最新安装的包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_CHANGED
一个已存在的应用程序包已经改变
包括包名
Intent.ACTION_PACKAGE_DATA_CLEARED
清除一个应用程序的数据时发出的广播
清除包程序不能接收到这个广播
Intent.ACTION_PACKAGE_INSTALL
触发一个下载并且完成安装时发出的广播
比如在电子市场里下载应用
Intent.ACTION_PACKAGE_REMOVED
成功的删除某个APK之后发出的广播
正在被安装的包程序不能接收到这个广播
Intent.ACTION_PACKAGE_REPLACED
替换一个现有的安装包时发出的广播(不管现在安装的APP比之前的新还是旧

Intent.ACTION_PACKAGE_RESTARTED
用户重新开始一个包
重新开始包程序不能接收到这个广播
Intent.ACTION_POWER_CONNECTED
插上外部电源时发出的广播

Intent.ACTION_POWER_DISCONNECTED
已断开外部电源连接时发出的广播

Intent.ACTION_REBOOT
重启设备时的广播

Intent.ACTION_SCREEN_OFF
屏幕被关闭之后的广播

Intent.ACTION_SCREEN_ON
屏幕被打开之后的广播

Intent.ACTION_SHUTDOWN
关闭系统时发出的广播

Intent.ACTION_TIMEZONE_CHANGED
时区发生改变时发出的广播

Intent.ACTION_TIME_CHANGED
时间被设置时发出的广播

Intent.ACTION_TIME_TICK
当前时间已经变化(正常的时间流逝)
每分钟都发送,只能通过来注册
Intent.ACTION_UID_REMOVED
一个用户ID已经从系统中移除发出的广播

Intent.ACTION_UMS_CONNECTED
设备已进入USB大容量储存状态时发出的广播

Intent.ACTION_UMS_DISCONNECTED
设备已从USB大容量储存状态转为正常状态时发出的广播

Intent.ACTION_WALLPAPER_CHANGED
设备墙纸已改变时发出的广播

Intent.ACTION_USER_PRESENT
用户唤醒设备

Intent.ACTION_NEW_OUTGOING_CALL
拨打电话








以上Demo的源代码地址:点击打开链接





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值