所谓的官博机制可以理解成为1对多的概念

即一个喇叭所有的人都能听到(统一范围内)

为了便于及逆行系统级别的消息通知

Android引入了一套广播机制

而且更容易进行实现。

3.1、广播机制的简介

再Andriod中的广播机制很灵活

因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册

这样该程序就会只接收到自己所关心的广播内容

这些广播肯能来源于系统,也可能来源于其他 程序

Android提供了一套完整的API

允许应用程序自由的发送和接受广播

广播可以分为两种类型:

1、标准广播

是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻

接受这条广播信息,因此没有任何先后顺序可言。

这种广播的执行效率会高,但是同时也意味着他是无法被截断

示意图:

2、有序广播

是一种同步执行的广播,再广播发出之后,同一时刻只会有一个广播接收器能接收到这条广播信息

当这个广播接器中的逻辑执行完毕后,广播才会继续传递

此种的广播接收器是先后顺序的

优先级较高的接收器可以先接收到消息

前面的广播可以截断正在传递的广播

3.2、接受系统广播

1、动态监听网络变化

广播接收器可以自由的对自己感兴趣的广播进行注册

这样再响应的广播发出时,广播接收器就能接收到该广播

注册广播的方式一把有两种:

1、代码中进行注册

2、AndroidManifest.xml中进行注册

前者动态烛台,后者静态注册

如何创建一个广播接收器:

只需要新建一个类,继承BroadcastReceiver,并且重写父类的onReceive()方法即可

当有广播来时。该方法就会执行

小实例:

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
private NetWorkChengeReceiver netWorkChengeReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstlayout);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
}
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
netWorkChengeReceiver = new NetWorkChengeReceiver();
registerReceiver(netWorkChengeReceiver,intentFilter);
} @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(netWorkChengeReceiver);
} class NetWorkChengeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("net:", "onReceive: ");
Toast.makeText(context,"ntework",Toast.LENGTH_LONG).show();
}
}
}

自定义的NetWorkChangeReceiver继承BroadCastReceiver

并且实现onReceive()方法

这里如果网络发生变化会进行显示相关的信息

再onCreate()方法中

首先创建一个IntentFilter的实例

为其添加一个值,此时的值时网络发生变化时,系统发出的一条通道信息就是上述的值

也就是说广播接收器想要监听什么广播就需要添加响应的action

然后创建一个NetWorkChangeReceiver的实例

最后调用registerReceiver()方法进行注册,将NetWorkChangeReceiver和IntentFilter的实例都传进去

这样NetWorkChangeReceiver就会接收到值为android.net.conn.CONNECTIVITY_CHANGE的广播

也就实现了监听网络的变化

动态注册的广播接收器一定要取消注册才行,这里需要再onDestroy()方法中通过unregisterReceiver()方法来实现

这里运行程序,进行测试。

此时只是简单对网络的变化进行提示

此时还能进一步提示是否启动网络的功能

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
private NetWorkChengeReceiver netWorkChengeReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstlayout);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
}
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
netWorkChengeReceiver = new NetWorkChengeReceiver();
registerReceiver(netWorkChengeReceiver,intentFilter);
} @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(netWorkChengeReceiver);
} class NetWorkChengeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) { ConnectivityManager conn = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo net = conn.getActiveNetworkInfo();
if (net !=null && net.isAvailable()){
Toast.makeText(context,"open",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(context,"close"
,Toast.LENGTH_LONG).show();
}

}
}
}

再onReceive()方法中

首先通过getSystemService()得到了ConnectivityManager 的实例

这是一个系统服务类,专门用于管理网络连接的。

然后使用getActiveNetworkInfo()方法可以得到NetWorkInfoo的实例

接着调用NetworkInfo的isAvailable()方法,可以判断当前是否有网络了

这里有一个重要的问题:权限

Android为了保护用户设备的安全和隐私

做了严格规定:

如果程序需要进行一些对用户来说比较敏感的操作

就必须再配置文件中进行声明权限

否则程序将会直接崩溃

此时需要在AndroidManifest.xml文件中

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ccrr.myapplication">
  ...
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>

这是第一个权限问题

在Android中有许多需要权限才可以进行的

重新执行项目:

此时开启

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

动态注册的广播接收器是可以自动的控制注册和注销

在灵活方面有很大的优势

但是也存在缺点:必须要在程序启动之后才能接到广播,因为注册的逻辑是写在onCreate()方法中的

使用静态注册可以在未启动的情况下就能接收到广播

准备一个让程序接受一条开机广播

当收到这条广播时就可以在onReceive()方法这里执行相应的逻辑

从而实现开机启动的功能

右键--new --Other--Broadcast Receiver

首先写广播的接收器名

Exported属性表示是否允许这个广播接收器接受本程序以外的广播

Enabled属性 表示使用启用这个广播接收器

public class BootCompleteReceiver extends BroadcastReceiver {
public BootCompleteReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Boot complete",Toast.LENGTH_LONG).show();
}
}

在onReceive()方法中使用其弹出一条信息

静态的广播接收器一定要在AndroidManifest.xml文件中进行注册

此时已经自动进行注册了:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ccrr.myapplication"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <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>
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application> </manifest>

出现了receiver标签所有的静态广播接收器都是在这里进行住的

通过android:name 来制定具体注册哪一个广播接收器: <action android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

同时还需要指定:<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

否则不能收到开机广播

系统启动之后会发出一条值为:android.permission.RECEIVE_BOOT_COMPLETED的广播

可以看到在<intent-filter>标签中加了action

监听系统开机的广播也需要声明权限使用<uses-permission>

重新启动之后:

程序已经可以接受开机广播了

将模拟器关闭重启

在启动之后就会收到开机广播

这可能会失败,需要对程序进行相关的更使用:

详情可见:https://blog.csdn.net/baidu_27196493/article/details/78269674

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ccrr.myapplication"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <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>
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> <receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application> </manifest>
BootCompleteReceiver.java
public class BootCompleteReceiver extends BroadcastReceiver {
public BootCompleteReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
String ation = intent.getAction().toString();
if
(ation.equals(Intent.ACTION_BOOT_COMPLETED)){
Log.d("ooo","Boot");
Toast.makeText(context,"Boot complete",Toast.LENGTH_LONG).show();
}
}
}

此时启动之后就会进行打印在屏幕上!!!

注意:

不要再onReceive()方法中添加过多的逻辑或者任何耗时的操作

因为在广播接收器中不允许开启线程的

当onReceive()方法运行较长时间没有结束时程序就会报错

广播接收器更多的是扮演一种打开程序其他组件的角色

如:创建一条状态栏的通知,或者启动一个服务

3.3、发送自定义广播

主要实践:标准广播和有序广播

1、发送标准广播

发送广播之前首先定义一个广播接收器来准备接受此广播才行

public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"MyBroadcastReceiver",Toast.LENGTH_LONG).show();
}
}

在收到自定义的广播时就会弹出相关的信息。

        <receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ccrr.myapplication.MyBroadcastReceiver"></action>
</intent-filter>
</receiver>

这里的代码是自动生成的,此时需要之定义action

这里让自定的MyBroadcastReceiver  接受一条值为com.example.ccrr.myapplication.MyBroadcastReceiver的广播

因此在发送这样一条广播

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <Button
android:id="@+id/button_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send Broadcast"/> </LinearLayout>

在这里定义一个按钮,用于作为发送广播的触发点

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
private NetWorkChengeReceiver netWorkChengeReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstlayout);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
} Button button = (Button) findViewById(R.id.button_send);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.ccrr.myapplication.MyBroadcastReceiver");
sendBroadcast(intent);
}
});
}
}

按钮的点击事件加入自定义广播逻辑

首先构建了一个Intent对象,并且把要发送的广播值传入

然后调用Context的sendBroadcast()方法将广播发送出去com.example.ccrr.myapplication.MyBroadcastReceiver这条广播接收器就会接收到消息

此时发出去的广播就是一条标准广播

由于是使用Intent进行数据传递

因此还可以在Intent中携带数据传递给广播接收器

2、发送有序广播

广播是一种可以跨进程的通信方式

之前程序内发出的广播其他的应用程序也是可以接收到的

此时新建一个项目

新建一个广播接收器用于接收上文中的自定义广播

AnotherBroadcastReceiver.java

public class AnotherBroadcastReceiver extends BroadcastReceiver {
public AnotherBroadcastReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"AnotherBroadcastReceiver",Toast.LENGTH_LONG).show();
throw new UnsupportedOperationException("Not yet implemented");
}
}

此时需要在onReceive()方法中进行显示一部分信息

这里的action是上文中的

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ccrr.applicationtwo"> <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=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ccrr.myapplication.MyBroadcastReceiver"></action>
</intent-filter>
</receiver>

</application> </manifest>

这里的action是上文说过的

此时点击上文中的按钮进行显示操作:

此时点击操作可以同时显示两个工程中的打印信息

以上均是标准广播!!!

 有序广播如下:

此时还是在第一个项目中进行更改

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstlayout); Button button = (Button) findViewById(R.id.button_send);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.ccrr.myapplication.MyBroadcastReceiver");
sendOrderedBroadcast(intent,null); }
});
}

只需要改动一条代码

sendBroadcast()方法改成sendOrderedBroadcast()

接收两个参数:

1、是Intent

2、是一个与权限相关的字符串

两个程序都可以接收到这条广播

广播接收器是由先后顺序的

前面的广播接收器还可以将广播截断,以阻止其继续传播

如何设置广播接收器的先后顺序呢?

第一个项目

     <receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.example.ccrr.myapplication.MyBroadcastReceiver"></action>
</intent-filter>
</receiver>

这里指定android:priority属性给广播接收器设置优先级

优先级高的广播接收器可以先收到广播

此时将其设置为100

既然已经获得了优先权,还可以选择是否允许广播继续传递:

第一个项目中:

MyBroadcastReceiver.java

public class MyBroadcastReceiver extends BroadcastReceiver {
public MyBroadcastReceiver() {
} @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"MyBroadcastReceiver",Toast.LENGTH_LONG).show();
abortBroadcast();
}
}

在onReceive()方法,就表示这条广播截断

此时后面的广播接收器就无法再接受此条广播

测试:

这里只有一个进行了打印!!!

以上的测试都在第一个项目中

第二个项目只是使用了一个监听

其余的都在第一个项目中进行实现!!!

3.4、使用本地广播

之前的均属于系统全局广播

即发出的广播可以被其他任何应用程序接收到

并且可以接收到来自其他任何程序的广播

这样很容易引起安全性问题

如发送一些携带关键性数据的广播可能被其他应用程序截获

或者其他程序不停的向我们的广播接收器发送各种垃圾广播

为了能够简单的解决安全问题

Android引入了一套本地广播机制

这个广播只能再内部进行

并且广播只能接受来自本地应用程序发出的广播

此时的安全性问题就都不存在了

再MainActivity中:

主要使用LocalBroadcastManager来对广播进行管理

并且提供了发送广播和注册广播接收器的方法

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
private NetWorkChengeReceiver netWorkChengeReceiver; //本地广播
private LocalReceiver localReceiver;
private LocalBroadcastManager localBroadcastManager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.firstlayout);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null){
actionBar.hide();
}//本地广播
//获取实例
localBroadcastManager= localBroadcastManager.getInstance(this); intentFilter = new IntentFilter();
intentFilter.addAction("com.example.ccrr.myapplication.LocalReceiver");
localReceiver = new LocalReceiver();
     //注册本地广播接收器
localBroadcastManager.registerReceiver(localReceiver,intentFilter); Button button = (Button) findViewById(R.id.button_send);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.ccrr.myapplication.LocalReceiver");
localBroadcastManager.sendBroadcast(intent);
}
}); } @Override
protected void onDestroy() {
super.onDestroy();//本地广播
localBroadcastManager.unregisterReceiver(localReceiver);
} class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"LocalReceiver",Toast.LENGTH_LONG).show();
}
} }

首先通过LocalBroadcastManager的方getInstance()方法得到一个实例

然后再注册广播接收器的时候调用LocalBroadcastManager的registerReceiver()方法

再发送广播的时候调用LocalBroadcastManager的sendBroadcast()方法

此时再按钮的点击事件中发送一条com.example.ccrr.myapplication.LocalReceiver

再LocalReceiver中接收这条消息

此时的广播接收器只能再本地进行接受,其他程序时无法进行接受的,只能在本程序内进行创博

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

静态注册主要是为了程序再未启动的时候也能接受广播

发送本地广播时,程序已经启动了

优点:

1、可以明确知道发送的广播不hi离开我们的程序,不用担心数据的泄露

2、其他程序无法将广播发送到程序的内部,无需担心安全漏洞的隐患

3、发送本地广播比发送系统全局广播将会更加高效

3、Android-全局大喇叭-广播机制的更多相关文章

  1. Android 中的广播机制

    Android 中的广播机制 Android 中的广播,按照广播响应范围,可以分为应用内广播和全局广播.按照广播的接收方式,可以分为标准广播和有序广播. 广播的分类 响应范围 应用内广播:此类广播只能 ...

  2. <Android基础> (五) 广播机制

    1)接收系统广播:a.动态注册监听网络变化 b.静态注册实现开机启动 2)发送自定义广播:a.发送标准广播 b.发送有序广播 3)使用本地广播 第五章 5.1 广播机制 Android中的每个程序都可 ...

  3. Android中使用广播机制退出多个Activity

    谷歌百度一下,Android中退出多个Activity的方法,大家讨论的很多. 在实习的时候,看到公司的项目退出多个Activity,是采用LinkedList方法,毕业设计的时候,也参照了那种方法. ...

  4. 【Android】BroadCast广播机制应用与实例

    如何编写广播接收器 第一步:需要继承BroadcastReceiver类,覆写其中的onReceive()方法. class MyBroadcastReceiver extends Broadcast ...

  5. Android 中的消息传递,详解广播机制

    --------------------------------------广播机制简介--------------------------------------------- Android中的广 ...

  6. Android广播机制:Broadcast

    转载:Android总结篇系列:Android广播机制 1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广 ...

  7. 九、Android学习第八天——广播机制与WIFI网络操作(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 九.Android学习第八天——广播机制与WIFI网络操作 今天熟悉了An ...

  8. Android广播机制简介

    为什么说Android中的广播机制更加灵活呢?这是因为Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来 ...

  9. Android开发之广播

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

随机推荐

  1. 字符串匹配问题(lfyzoj)

    问题描述 字符串中只含有括号 (),[],<>,{},判断输入的字符串中括号是否匹配.如果括号有互相包含的形式,从内到外必须是<>,(),[],{},例如.输入: [()] 输 ...

  2. JAVA基础之——数据结构

    JAVA数据结构有8种,如下所示,本文从使用场景,优缺点方面讲解. 1 数组Array ArrayList 使用场景:有序的存储同一类型数据的集合,固定大小 优点:通过索引查找方便 缺点:插入或删除一 ...

  3. 为什么要学习 UML?

    UML 的首要价值是沟通和理解.好的图形可以帮助沟通设计思想,尤其是要回避许多细节时,图形也可以帮助你理解软件系统或业务流程.作为团队的成员,尝试弄清楚某些东西时,图形有助于理解和沟通整个团队所理解到 ...

  4. CentOS 安装Parallels Tools

    为了做到Mac和Linux之间共享文件夹,因此需要安装Parallels Tool, 具体安装步骤可以参考 install parallels tool for linux guest http:// ...

  5. linux ubuntu 安装nginx

    参考原文 在Ubuntu下安装Nginx有以下方法,但是如果想要安装最新版本的就必须下载源码包编译安装. 一.基于APT源安装 sudo apt-get install nginx 安装好的文件位置: ...

  6. mybatis-generator 动态生成实体对象、dao 以及相关的xml映射文件

    .新建maven空项目 2.修改pom.xml文件 <?xml version="1.0" encoding="UTF-8"?> <proje ...

  7. UOJ#55. 【WC2014】紫荆花之恋

    传送门 暴力思路就是每次点分治计算答案 点分治之后,条件可以变成 \(dis_i-r_i\le r_j-dis_j\) 每次只要查找 \(r_j-dis_j\) 的排名然后插入 \(dis_j-r_j ...

  8. Django—Form两种解决表单数据无法动态刷新的方法

    一.无法动态更新数据的实例 1. 如下,数据库中创建了班级表和教师表,两张表的对应关系为“多对多” from django.db import models class Classes(models. ...

  9. Spring Data MongoDB 级联操作

    DBRef 方式关联 DBRef 就是在两个Collection之间定义的一个关联关系,暂不支持级联的保存功能 例子:一个Person对象有多个Book对象,一对多关系 实体Person public ...

  10. Visual Studio解决方案vs2005/vs2008/vs2010/vs2012/vs2013/vs2015版本互相转换工具

    原文:http://blog.csdn.net/xiejiashu/article/details/52397641   本文转自EasyDarwin团队成员Alex的博客:http://blog.c ...