原文链接:http://www.orlion.ga/572/

一、广播机制

Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广

播可能是来自于系统的,也可能是来自于其他应用程序的。Android提供了一套完整的 API,允许应用程序自由地发送和接收广播。发送广播的方法需要借助Intent。而接收广播的方法则需要引入一个新的概念,广播接收器(Broadcast Receiver)

广播可以分为两种类型:

  • 标准广播:是一种完全异步的广播,广播发出后所有的广播接收器几乎同时收到广播

  • 有序广播:是一种同步广播,广播发出后同一时刻只有一个广播能够收到这条消息,只有当这个广播接收器中的逻辑处理完之后广播才会继续传播。所以此时的广播是有先后顺序的,优先级高的广播接收器就可以先收到广播,并且前面的广播接收器可以截断正在传递的广播,这样后边的广播接收器就收不到广播了

二、接收系统广播

Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息。比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一条广播,时间或时区发生改变也会发出一条广播等等。如果想要接收到这些广播,就需要使用广播接收器。

1、动态注册监听网络变化

注册广播的方式一般有两种,在代码中注册(动态注册)和在AndroidManifest.xml中注册(静态注册)

如何创建一个广播接收器呢?只需要创建一个类继承自BroadcastReceiver,并重写父类的onReceive()方法,这样当有广播来的时候,onReceive()方法就会执行,具体的逻辑放在这个代码中执行

先通过动态注册的方式编写一个监听网络变化的程序。创建一个BroadcastDemo项目,修改MainActivity代码:

package ga.orlion.broadcastdemo;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.widget.Toast; public class MainActivity extends Activity { private IntentFilter intentFilter; private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver , intentFilter);
}
@Override
protected void onDestroy() { super.onDestroy();
unregisterReceiver(networkChangeReceiver);
} class NetworkChangeReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) { ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(context , "network is available" , Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context , "network is unavailable" , Toast.LENGTH_SHORT).show();
}
}
}
}

可以看到,我们在 MainActivity中定义了一个内部类 NetworkChangeReceiver,这个类是继承自 BroadcastReceiver的,并重写了父类的 onReceive()方法。这样每当网络状态发生变化时,onReceive()方法就会得到执行。然后观察 onCreate()方法,首先我们创建了一个 IntentFilter的实例,并给它添加了一个值为 android.net.conn.CONNECTIVITY_CHANGE 的 action,为什么要添加这个值呢?因为当网络状态发生变化时,系统发出的正是一条值为 android.net.conn.CONNECTIVITY_CHANGE 的广播,也就是说我们的广播接收器想要监听什么广播,就在这里添加相应的action就行了。 接下来创建了一个 NetworkChangeReceiver的实例, 然后调用 registerReceiver()方法进行注册,将 NetworkChangeReceiver 的实例和 IntentFilter 的实例都传了进去,这样NetworkChangeReceiver就会收到所有值为android.net.conn.CONNECTIVITY_CHANGE的广播,也就实现了监听网络变化的功能。最后要记得,动态注册的广播接收器一定都要取消注册才行,这里我们是在 onDestroy()方法中通过调用unregisterReceiver()方法来实现的

另外,这里有非常重要的一点需要说明,Android系统为了保证应用程序的安全性做了规定,如果程序需要访问一些系统的关键性信息,必须在配置文件中声明权限才可以,否则程序将会直接崩溃,比如这里查询系统的网络状态就是需要声明权限的。打开AndroidManifest.xml文件,在里面加入如下权限就可以查询系统网络状态了:

2、静态注册实现开机启动

动态注册灵活性很大,但是它必须在程序启动之后才能接受广播,如果想让程序在未启动的情况下接受到广播就需要使用静态注册的方式了。

我们准备让程序接收一条开机广播,当接收到广播的时候就可以在onReceive()方法里执行相应的逻辑,从而实现开机启动的功能,新建一个BootCompleteReceiver继承自BroadcastReceiver,代码:

package ga.orlion.broadcastdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast; public class BootCompleteReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context, "Boot Complete", Toast.LENGTH_SHORT).show();
}
}

这里不再使用内部类方式定义广播接收器,因为一会需要在AndroidManifest.xml中注册这个类。修改AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ga.orlion.broadcastdemo"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            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=".BootCompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
    </application> </manifest>

需要声明权限。

三、发送自定义广播

1、发送标准广播

首先定义一个广播接收器来接收我们的广播,创建MyBroadcastReceiver继承自BroadcastReceiver,代码:

package ga.orlion.broadcastdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast; public class MyBroadcastReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context , "接收到广播了" , Toast.LENGTH_SHORT).show();
} }

在AndroidManifest.xml中注册:

<receiver android:name=".MyBroadcastReceiver">
            <intent-filter>
                <action android:name="ga.orlion.broadcastdemo.MY_BROADCAST" />
            </intent-filter>
        </receiver>

然后修改MainActivity:

        @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("ga.orlion.broadcastdemo.MY_BROADCAST");
sendBroadcast(intent);
}
});
}

点击按钮的时候就发送一条广播。

2、发送有序广播

广播是一种跨进程的通信,因此我们应用程序发出的广播,其他的应用程序应该也可以收到。

现在我们尝试发送有序广播

修改MainActivity:

        @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("ga.orlion.broadcastdemo.MY_BROADCAST");
sendOrderedBroadcast(intent, null);
}
});
}

可以看到,发送有序广播只需要改动一行代码,即将 sendBroadcast()方法改成sendOrderedBroadcast()方法。sendOrderedBroadcast()方法接收两个参数,第一个参数仍然是Intent,第二个参数是一个与权限相关的字符串,这里传入 null就行了。

接下来在配置文件中设定广播接收器的先后顺序,AndroidManifest.xml:

        <receiver android:name=".MyBroadcastReceiver">
            <intent-filter android:priority="100">
                <action android:name="ga.orlion.broadcastdemo.MY_BROADCAST" />
            </intent-filter>
        </receiver>

MyBroadcastReceiver可以选择是否允许广播继续传递了。修改 MyBroadcastReceiver中的代码

package ga.orlion.broadcastdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast; public class MyBroadcastReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) { Toast.makeText(context , "接收到广播了" , Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}

如果在 onReceive()方法中调用了 abortBroadcast()方法,就表示将这条广播截断,后面的广播接收器将无法再接收到这条广播。

四、使用本地广播

前面我们发送和接收的广播全部都是属于系统全局广播, 即发出的广播可以被其他任何的任何应用程序接收到,并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易会引起安全性的问题,为了能够简单地解决广播的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递, 并且广播接收器也只能接收来自本应用

程序发出的广播。本地广播的用法并不复杂,主要就是使用了一个 LocalBroadcastManager来对广播进行

管理,并提供了发送广播和注册广播接收器的方法。

修改MainActivity:

package ga.orlion.broadcastdemo;

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.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 = LocalBroadcastManager.getInstance(this);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("ga.orlion.broadcastdemo.LOCAL_BROADCAST");
localBroadcastManager.sendBroadcast(intent);
}
});
intentFilter = new IntentFilter();
intentFilter.addAction("ga.orlion.broadcastdemo.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, "接收到本地广播", Toast.LENGTH_SHORT).show();
} }
}

首先是通过LocalBroadcastManager的getInstance()方法得到了它的一个实例,然后在注册广播接收器的时候调用的是 LocalBroadcastManager的registerReceiver()方法,在发送广播的时候调用的是LocalBroadcastManager的sendBroadcast()

方法。

Android入门(八)广播的更多相关文章

  1. Android入门:广播发送者与广播接收者

    参考: Android入门:广播发送者与广播接收者 - xiazdong - CSDN博客http://blog.csdn.net/xiazdong/article/details/7768807 一 ...

  2. 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

    本文原作者:“水晶虾饺”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.引言 好多小白初次接触即时通讯(比如:IM或者消息推送应用)时,总是不 ...

  3. 【详细】Android入门到放弃篇-YES OR NO-》各种UI组件,布局管理器,单元Activity

    问:达叔,你放弃了吗? 答:不,放弃是不可能的,丢了Android,你会心疼吗?如果别人把你丢掉,你是痛苦呢?还是痛苦呢?~ 引导语 有人说,爱上一个人是痛苦的,有人说,喜欢一个人是幸福的. 人与人之 ...

  4. UniMelb Comp30022 IT Project (Capstone) - 1.Android入门

    1. Android入门 Android系统架构 Android系统:四层架构.五块区域 1. Linux内核层 Linux Kernel:为Android设备的硬件提供了底层驱动 2. 系统运行库层 ...

  5. Android入门之文件系统操作

    Android入门之文件系统操作(二)文件操作相关指令 (转)   (一)获取总根 File[] fileList=File.listRoots(); //返回fileList.length为1 // ...

  6. Android入门(十二)SQLite事务、升级数据库

    原文链接:http://www.orlion.ga/610/ 一.事务 SQLite支持事务,看一下Android如何使用事务:比如 Book表中的数据都已经很老了,现在准备全部废弃掉替换成新数据,可 ...

  7. Android开发之广播

    广播是Android开发中的一个重要的功能,在Android里面有各式各样的广播,比如:电池的状态变化.信号的强弱状态.电话的接听和短信的接收等等,现在给大家简单介绍一下系统发送.监听这些广播的机制. ...

  8. android之自定义广播

    布局文件 点击按钮发送广播 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...

  9. Android之旅---广播(BroadCast)

    什么是广播 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.我们拿广播电台来做个比方.我们平常使用收音机收音是这样的:许许多多不同的广播电台通过特定的频率来发送他们 ...

随机推荐

  1. 【13_263】Ugly Number

    简单题 Ugly Number My Submissions Question Total Accepted: 32635 Total Submissions: 94009 Difficulty: E ...

  2. Windows XP和Word 2007不能正常使用VSTO插件

    今天帮助同事解决了一个小问题,就是在WindowsXP上,为Word2007开发的插件不能正常显示. 通过搜索关键词 WindowsXp Word 2007 VSTO找到了两个解决方案. http:/ ...

  3. Linux系统MySQL开启远程连接

    1.远程连接上Linux系统,确保Linux系统已经安装上了MySQL数据库.登陆数据库.mysql -uroot -p(密码). 2.创建用户用来远程连接 GRANT ALL PRIVILEGES ...

  4. java-多线程新特性

    Java定时器相关Timer和TimerTask类 每个Timer对象相对应的是单个后台线程,用于顺序地执行所有计时器任务TimerTask对象. Timer有两种执行任务的模式,最常用的是sched ...

  5. android 编译代码注意事项

    1 安装openjdk1.7 sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-apt update sudo apt-get install op ...

  6. VHDL生成的ngc文件被verilog的工程调用的问题

    1. 问题的提出 工程a是一个soft core,用VHDL写的,综合的时候去掉了"Add I/O buffers" ,并将-iob(Pack I/O Registers into ...

  7. sql常见的面试题

    1.用一条SQL语句 查询出每门课都大于80分的学生姓名 name   kecheng   fenshu 张三     语文       81张三     数学       75李四     语文   ...

  8. 黑马程序员——File笔记读,写,复制

    #region ReadAllBytes byte[] buffer = File.ReadAllBytes(@"C:\Users\dell\Desktop\新建文件夹.txt") ...

  9. sass中级语法

    github地址:https://github.com/lily1010/sass/tree/master/course02 用到的sass语法是: sass --watch test.scss:te ...

  10. Xamarin开发Android笔记:使用ZXing进行连续扫描

    在项目开发中需要使用到条码扫描,因为以前就测试过ZXing,感觉识别速度和功能都不错,所以直接引用.不过在实际开发的过程中,却遇到连续扫描的问题,每次扫描识别完成之后,扫描窗体自动关闭了. 在Xama ...