Android笔记之广播
为了容易理解,可以将广播代入到事件模型中,发送广播消息看做是触发event,BroadcastReceiver是处理事件的回调逻辑。
广播这种模型中涉及到两个角色,就是广播的发送者和接收者,所以会涉及到如何发送和如何接收广播。

同时因为系统中可能会有很多的广播,为了不被乱七八糟的东西混淆视听,每个广播给它一个action,这样广播接收器就可以使用action来过滤出自己感兴趣的广播,也可以将action看做是一个频道,每个广播都有一个自己的频道,广播接收器为了不串台就只收听自己感兴趣的一个或多个频道。

广播的分类
按作用域划分
广播按照作用域可以分为全局广播和本地广播。
全局广播的作用域超出此应用程序,发出的全局广播可以被所有应用程序接收,也可以接收其它应用程序发出的全局广播。
本地广播就是作用域限定在本应用中,发出的广播只能在应用内部传递,同样也只接收应用内部的本地广播。
这样是因为我们在自己的应用内传递关键信息,如果不限制作用域的话就有可能被其它应用收到,这样很容易引起安全性问题。

按接收顺序划分
按接收顺序分为普通广播(无序广播)和有序广播。
普通广播:使用Context#sendBroadcast(Intent intent)发送,普通广播是异步的(所以又叫无序广播),广播接收者的顺序无法确定,因为是异步的,所以不能够被停止掉,这种方式保证每个广播接收器都能够接收到广播,并且收到的就是原始的广播信息(因为从发送者直接到接收者,中间没有经过其它人)。
有序广播:使用Context#sendOrderedBroadcast方法发送,所有要接收此条广播的接收器要排队接收,类似于一条处理链,链上的每个接收器都可以选择从这里终止不再向下传递,所以有序广播是可以被终止的,不保证每个接收器都一定能够接收到广播,同样的,因为链式向后面传递,那么前面的接收者也可以对广播修改后再往下传递,所以此方式除链上的第一个节点外其他接收器收到的数据都有可能被篡改过。另外既然有序广播接收的时候需要排队,那么排队的依据是什么呢,就是在注册的时候intent-filter的android:priority来决定。

粘性广播:使用Context#sendStickyBroadcast发送,粘性广播被发送后,最后一个粘性广播将被粘在系统上,在一段时间内如果有新的广播接收器注册的话那么它将能够接收到这个被粘住的广播,尽管在这个广播被发送的时候它还没有注册,但就是粘了一下收到了。
发送广播
发送全局广播
sendBroadcast()方法第一个参数接收一个Intent,第二个参数是与权限相关的字符串。
发送全局无序广播: Context#sendBroadcast
发送全局有序广播: Context#sendOrderedBroadcast
Intent intent = new Intent("foo.BAR");
sendOrderedBroadcast(intent, null);
发送本地广播
本地广播使用LocalBroadcastManager来管理。
发送本地有序广播:LocalBroadcastManager.getInstance(this).sendBroadcast
发送本地无序广播:LocalBroadcastManager.getInstance(this).sendBroadcastSync
接收广播
接收广播的套路
1. 要接收广播需要创建一个类继承android.content.BroadcastReceiver,并在其onReceive方法中实现对广播事件的处理逻辑
2. 然后将创建的广播接收器注册,注册的方式有静态注册(AndroidManifest.xml)和动态注册(Java代码)两种,如果接收广播需要权限的话还要声明使用相应权限。
3. 然后当有符合条件的广播到来的时候会自动调用广播接收器的onReceive方法
静态注册和动态注册的区别
静态注册:在应用程序关闭后,当有广播来临时仍然能够接收到被调用,应用场景是需要时刻监听广播(即使在应用程序退出后)。
动态注册:短命鬼,广播接收器的生命周期跟随组件在变,应用场景是只在某段时间才需要监听广播。
拦截广播
要在有序广播接收器的处理链上拦截广播,在onReceive方法中调用aboryBroadcast即可拦截广播不再向后传递而是从此处停止。
@Override
public void onReceive(Context context, Intent intent) {
boolean foo = intent.getBooleanExtra("foo", false);
if (foo) {
abortBroadcast();
}
}
本地广播的注册
本地广播只能通过动态注册的方式。因为静态广播主要是为了让应用程序在不启动的时候也能够接收到广播,而本地广播因为都是在应用程序内传递的,所以本地广播都是在应用启动时才有的,所以本地广播不能使用静态注册的方式。
注册本地广播接收器: LocalBroadcastManager.getInstance(this).registerReceiver();
取消注册本地广播接收器:LocalBroadcastManager.getInstance(this).unregisterReceiver();
onReceive的耗时操作
onReceive的执行时间最多只有10秒钟,当超过10秒的时候将会报错,所以不应该在其中执行耗时的方法,正确的方式是启动一个Service执行耗时操作。
静态注册
在AndroidManifest.xml文件中注册广播接收器:
<!-- 静态注册广播接收器 -->
<receiver
android:name=".FooBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="cc11001100.foo" />
</intent-filter>
</receiver>
name: 继承了BroadcastReceiver的广播接收器
enable: 是否启动此接收器
exported:是否允许接收此应用以外的广播,如果为false表示只接收此应用内的广播,即本地广播接收器,否则为全局广播接收器。
intent-filter:增加action过滤广播,其属性priority用于设置此广播接收器的优先级,范围是[-1000, 1000]
action ,系统中会有很多乱七八糟的广播,这个是用来过滤只接收自己需要的广播,intent-filter下可以有多个action
对于静态注册,如果使用的是Android Studio的话,可以通过:

创建的类会继承BroadcastReceiver并且自动在AndroidManifest.xml文件中静态注册。
下面是一个静态注册的例子:
广播接收器:
package cc11001100.androidstudy_005; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast; /**
* @author CC11001100
*/
public class FooBroadcastReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
int value = intent.getIntExtra("foo", 0);
Toast.makeText(context, Integer.toString(value), Toast.LENGTH_LONG).show();
Log.i("FooBroadcastReceiver", "onReceive: " + value);
} }
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cc11001100.androidstudy_005.MainActivity"> <Button
android:id="@+id/sendBroadcastBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Broadcast"
tools:ignore="MissingConstraints"
android:onClick="sendBroadcastBtn"/> </android.support.constraint.ConstraintLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cc11001100.androidstudy_005"> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
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=".FooBroadcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cc11001100.foo" />
</intent-filter>
</receiver> </application> </manifest>
MainActivity:
package cc11001100.androidstudy_005; import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View; import java.util.Random; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getName(); @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
} /**
* 绑定的按钮事件,发送广播事件供接收
*/
public void sendBroadcastBtn(View view) {
Intent intent = new Intent();
intent.setAction("cc11001100.foo");
intent.putExtra("foo", new Random().nextInt());
sendBroadcast(intent);
Log.i(TAG, "sendBroadcastBtn: ");
}
}
前面提到过静态注册的广播接收器即使在应用退出后仍然可以接收广播,那么有没有办法停掉它呢?
PackageManager
动态注册
在程序运行的时候使用Java代码注册,称为动态注册,动态注册要记得在组件的onDestroy中unregisterReceiver广播接收器。
动态注册的步骤:
1. 定义广播接收器类
2. 创建IntentFilter,通过setAction设置所要接收的广播
3. 使用Context#registerReceiver(BroadcastReceiver receiver, IntentFilter filter)方法注册接收器
下面是一个动态注册的例子,广播接收器,对接收到的广播做处理:
package cc11001100.androidstudy_005; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast; /**
* @author CC11001100
*/
public class FooBroadcastReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
int value = intent.getIntExtra("foo", 0);
Toast.makeText(context, Integer.toString(value), Toast.LENGTH_LONG).show();
Log.i("FooBroadcastReceiver", "onReceive: " + value);
} }
布局文件,放一个按钮,每单击一次就发送一个广播供广播接收器接收:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cc11001100.androidstudy_005.MainActivity"> <Button
android:id="@+id/sendBroadcastBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send Broadcast"
tools:ignore="MissingConstraints"
android:onClick="sendBroadcastBtn"/> </android.support.constraint.ConstraintLayout>
MainActivity:
package cc11001100.androidstudy_005; import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View; import java.util.Random; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getName();
private FooBroadcastReceiver fooBroadcastReceiver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 动态注册广播接收器
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("cc11001100.foo");
fooBroadcastReceiver = new FooBroadcastReceiver();
registerReceiver(fooBroadcastReceiver, intentFilter);
} @Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(fooBroadcastReceiver);
} /**
* 绑定的按钮事件,发送广播事件供接收
*/
public void sendBroadcastBtn(View view) {
Intent intent = new Intent();
intent.setAction("cc11001100.foo");
intent.putExtra("foo", new Random().nextInt());
sendBroadcast(intent);
Log.i(TAG, "sendBroadcastBtn: ");
}
}
.
Android笔记之广播的更多相关文章
- Android学习笔记(广播机制)
1.Android的广播机制介绍 收听收音机也是一种广播,在收音机中有很多个广播电台,每个广播电台播放的内容都不相同.接受广播时广播(发送方)并不在意我们(接收方)接收到广播时如何处理.好比我们收听交 ...
- Android学习笔记_19_广播接收者 BroadcastReceiver及其应用_窃听短信_拦截外拨电话
一.广播接收者类型: 广播被分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”. 普通广播是完全异步的,可以在同一时刻(逻辑上 ...
- android菜鸟学习笔记26----Android广播消息及BroadcastReceiver
1.广播类型: Android中的广播有两种类型:标准广播和有序广播.其中,标准广播是完全异步发送的广播,发出之后,几乎所有的广播接收者都会在同一时刻收到这条广播消息,因而,这种类型的广播消息是不可拦 ...
- Android笔记(二十六) Android中的广播——BroadcastReceiver
为了方便进行系统级别的消息通知,Android有一套类似广播的消息机制,每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会接收自己所关心的广播内容,这些广播可能是来自于系统,也可能是来自于 ...
- 我的Android笔记--我对安卓系统的一些了解
敲了这么长时间代码,记录一下我对Android的一些概念,下面大部分内容来源自网络资料和官方给的文档. 1,Android操作系统的核心属于Linux的一个分支,具有典型的Linux调度和功能 ...
- Android开发之广播
广播是Android开发中的一个重要的功能,在Android里面有各式各样的广播,比如:电池的状态变化.信号的强弱状态.电话的接听和短信的接收等等,现在给大家简单介绍一下系统发送.监听这些广播的机制. ...
- android之自定义广播
布局文件 点击按钮发送广播 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmln ...
- Android之旅---广播(BroadCast)
什么是广播 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.我们拿广播电台来做个比方.我们平常使用收音机收音是这样的:许许多多不同的广播电台通过特定的频率来发送他们 ...
- Android笔记——Android中数据的存储方式(二)
我们在实际开发中,有的时候需要储存或者备份比较复杂的数据.这些数据的特点是,内容多.结构大,比如短信备份等.我们知道SharedPreferences和Files(文本文件)储存这种数据会非常的没有效 ...
随机推荐
- BZOJ5291 BJOI2018链上二次求和(线段树)
用线段树对每种长度的区间维护权值和. 考虑区间[l,r]+1对长度为k的区间的贡献,显然其为Σk-max(0,k-i)-max(0,k-(n-i+1)) (i=l~r). 大力展开讨论.首先变成Σk- ...
- JAVA里面的“指针”
JAVA里面的“指针” 众所周知,在java里面是没有指针的.那为何此处还要说java里面的“指针”呢?我们知道在C/C++中,指针是指向内存中的地址.那么在Java里 ...
- 为什么家里的宽带的IP显示的是外地?
作者:NightCoffee链接:https://www.zhihu.com/question/22547945/answer/21734955来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...
- svmrank 的误差惩罚因子c选择 经验
C是一个由用户去指定的系数,表示对分错的点加入多少的惩罚,当C很大的时候,分错的点就会更少,但是过拟合的情况可能会比较严重,当C很小的时候,分错的点可能会很多,不过可能由此得到的模型也会不太正确,所以 ...
- KMP之Z-function (扩展kmp)
http://codeforces.com/blog/entry/3107 // s[0, ..., n-1], z[0] = 0// z[i] is the length of the longes ...
- Ubuntu实用软件安装[转]
Gedit编辑器配置 Ubuntu14.04从安装软件到卸载软件,删除安装包 linux wget 命令用法详解(附实例说明) ==================================== ...
- 内容显示在HTML页面底端的一些处理方式
1.概要: 手机页面底端有时候需要显示版权信息,诸如一行文字或者一个背景图片,但是页面的滚动长度未知,需要考虑两个问题 当页面高度小于屏幕高度时候: 希望最后一行信息显示在屏幕底端,同时也就是页面底端 ...
- linux 第三周读书笔记-----第一二章 20135334赵阳林
第一章 Linux内核简介 1.1 Unix的历史 由于Unix系统设计简洁并且在发布时提供源代码,所以许多其他组织和团体都对它进了进一步的开发. Unⅸ虽然已经使用了40年,但计算机科学家仍然认为它 ...
- Android源码批量下载及导入到Eclipse
1.去http://code.google.com/p/msysgit/downloads/list 下载Git,进行安装 2.生成批量下载脚本文件 下载批量工具CreatAutoGetSh(工具 ...
- Java虚拟机性能监控与调优
1 基于JDK命令行工具的监控 1.1 JVM的参数类型 1.1.1 标准参数 在JVM的各个版本基本上保持不变,很稳定的. -help -server -client -version -showv ...