Android Broadcast Receive广播接收器详解

广播(Broadcast)是一种广泛运用的在应用程序之间传输信息的机制,在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序也可以接受广播并做出程序逻辑上的处理, 比如我们需要让应用程序开机自动启动,其实就是应用了广播的知识。
广播的三要素分别是:
1.广播(Broadcast) - 用于发送广播;
2.广播接收器(BroadcastReceiver) - 用于接收广播;
3.意图(Intent)-用于保存广播相关信息的媒介。
下面是我从网上搜集的一些广播的知识点:
1.普通广播
普通广播是完全异步的,可以在同一时刻(逻辑上)被所有广播接收者接收到,消息传递的效率比较高,但缺点是接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播。
2.有序广播
有序广播是按照接收者声明的优先级别(声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000。也可以调用IntentFilter对象的setPriority()进行设置),被接收者依次接收广播。如:A的级别高于B, B的级别高于C,那么,广播先传给A,再传给B,最后传给C。A得到广播后,可以往广播里存入数据,当广播传给B时,nB可以从广播中得到A存入的数据。
3系统广播
系统广播是Android内置的广播,满足一定条件后系统会自动发送这个广播,不需要我们再定义发送,只需要用的时候接收就可以了,比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一 条广播,时间或时区发生改变也会发出一条广播,摄像头按被按下会触发广播等等。
4自定义广播
自定义广播是用户可以自己定义发送一个广播,看到很多书籍都是这么讲,可以我一直在思考为什么需要自定义广播,或者说自定义广播在Android程序中一般是用在什么地方,因为广播是为了给不同的组件中通信而使用的例如service 与 Activity 不同的进程中,或者不同的应用程序中就会使用广播机制来通信的。
5本地广播
系统广播和自定义广播都属于全局广播,即发出的广播可以被其他任何 的任何应用程序接收到, 并且我们也可以接收来自于其他任何应用程序的广播。这样就很容易会引起安全性的问题, 比如说我们发送的一些携带关键性数据的广播有可能被其他的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播。
为了能够简单地解决广播的安全性问题,Android 引入了一套本地广播机制,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,这样所有的安全性问题就都不存在了。
6动态注册广播
动态注册就是在程序中使用Context.registerReceiver注册。动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写在 onCreate()方法中的。
7静态注册广播
在AndroidManifest.xml中注册广播称之为静态注册,静态注册是常驻型 ,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行,所以一些系统级别的广播比如开机启动广播就必须要用到静态注册的方法,而有些系统广播也是可以动态注册的,比如电量变化广播等可以在程序启动后监听即可。
下面我通过例子简单的介绍一下广播机理:
(1)首先举一个系统广播的例子,这里我们通过静态注册广播的方式来完成
首先要再AndroidManifest.xml中注册广播接收机
<pre>
//注册广播接收机,监听开机广播
<receiver android:name=".MyBroadcastReceive">
<intent-filter>
//通过android:name来指定具体注册哪一个广播接收器
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</pre>
新建广播接收机,创建MyBroadcastReceive.java
<pre>
public class MyBroadcastReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"开机启动",Toast.LENGTH_LONG).show();
}
}
</pre>
运行程序候,重启虚拟机,在开机时可以看到“开机启动”的Toast
(2)下面我们通过静态注册广播的方式完成自定义广播
首先在AndroidManifest.xml文件中静态注册自定广播接收机
<pre>
<receiver android:name=".DiyBroadReceive">
<intent-filter>
//通过android:name来指定具体注册哪一个广播接收器,这里可以自己任意指定name
<action android:name="linus.diyBroadReceive" />
</intent-filter>
</receiver>
</pre>
创建自定义广播接收机,新建DiyBroadReceive.java
<pre>
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setAction("linus.diyBroadReceive");
intent.putExtra("name", "linus");
sendBroadcast(intent);
}
});
</pre>
(3)下面我们来看一下如何动态注册一个自定义广播接收机
<pre>
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//实例化广播接收器
dynamicBroadReceive = new DynamicBroadReceive();
//实例化意图过滤器
filter = new IntentFilter();
//为过滤器添加一个定义的广播,当然这里也可以填系统广播
filter.addAction("linus.dynamicBroadReceive");

            //可以通过setPriority()设置动态广播的优先级,优先级取值范围是-1000到1000
            //注意的是的静态注册的广播要快于动态注册的广播,不管动态注册的优先级设置的多高,不管静态注册的优先级有多低
            filter.setPriority(1000);
            //第一步,注册广播
            registerReceiver(dynamicBroadReceive, filter);
            
            //第二部,发送广播
            Intent intent = new Intent();
            intent.setAction("linus.dynamicBroadReceive");
            intent.putExtra("name","linus-dynamic");
            sendBroadcast(intent);
        }
    });

</pre>
创建自定义广播,新建DynamicBroadReceive.java
<pre>
public class DynamicBroadReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//第三部,接收广播
String name = intent.getExtras().getString("name");
Toast.makeText(context,"动态注册广播后,接收到的名字是"+name,Toast.LENGTH_SHORT).show();
}
}
</pre>
动态注册广播,在结束时必须注销广播
<pre>
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(dynamicBroadReceive);
}
</pre>
(4)下面在举例说明一下本地广播,本地广播无法通过静态注册完成广播注册。因为当广播到来时,应用一定时启动的。本地广播一般时通过LocalBroadcastManager进行管理的
<pre>
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
localBroadReceive = new LocalBroadReceive();
filter = new IntentFilter();
filter.addAction("linus.localBroadReceive");
localBroadcastManager.registerReceiver(localBroadReceive,filter);

            Intent intent = new Intent();
            intent.setAction("linus.localBroadReceive");
            intent.putExtra("name","linus-local");
            localBroadcastManager.sendBroadcast(intent);
        }
    });

</pre>
创建本地广播接收机,创建LocalBroadReceive.java
<pre>
public class LocalBroadReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = intent.getExtras().getString("name");
Toast.makeText(context,"本地广播接收到的name是"+name,Toast.LENGTH_SHORT).show();
}
}
</pre>
本地广播在结束时,也是需要注销广播的。
<pre>
@Override
protected void onDestroy() {
super.onDestroy();
localBroadcastManager.unregisterReceiver(localBroadReceive);
}
</pre>
(5)有序广播就是按照广播的优先级进行广播,不同的应用接收到广播的先后顺序不同。同时先接收到广播的应用可以向后接收到的广播传递数据。这里就不举例说明了。
为了方面大家实践测试,我将整个demo的源码分享一下。
MainActivity.java
<pre>
package linuszhao.js.one.jsbroadcast;

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.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

private Button btn1, btn2,btn3;
//定义意图过滤器
private IntentFilter filter;
//定义广播接收器
DynamicBroadReceive dynamicBroadReceive;

LocalBroadReceive localBroadReceive;
private LocalBroadcastManager localBroadcastManager;

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

    btn1 = (Button) findViewById(R.id.btn1);
    btn2 = (Button) findViewById(R.id.btn2);
    btn3 = (Button) findViewById(R.id.btn3);
    btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent();
            intent.setAction("linus.diyBroadReceive");
            intent.putExtra("name", "linus");
            sendBroadcast(intent);
        }
    });
    btn2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //实例化广播接收器
            dynamicBroadReceive = new DynamicBroadReceive();
            //实例化意图过滤器
            filter = new IntentFilter();
            //为过滤器添加一个定义的广播,当然这里也可以填系统广播
            filter.addAction("linus.dynamicBroadReceive");

            //可以通过setPriority()设置动态广播的优先级,优先级取值范围是-1000到1000
            //注意的是的静态注册的广播要快于动态注册的广播,不管动态注册的优先级设置的多高,不管静态注册的优先级有多低
            filter.setPriority(1000);
            //注册广播
            registerReceiver(dynamicBroadReceive, filter);

            Intent intent = new Intent();
            intent.setAction("linus.dynamicBroadReceive");
            intent.putExtra("name","linus-dynamic");
            sendBroadcast(intent);
        }
    });

    btn3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
            localBroadReceive = new LocalBroadReceive();
            filter = new IntentFilter();
            filter.addAction("linus.localBroadReceive");
            localBroadcastManager.registerReceiver(localBroadReceive,filter);

            Intent intent = new Intent();
            intent.setAction("linus.localBroadReceive");
            intent.putExtra("name","linus-local");
            localBroadcastManager.sendBroadcast(intent);
        }
    });

}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(dynamicBroadReceive);
    localBroadcastManager.unregisterReceiver(localBroadReceive);
}

}
</pre>
activity_main.xml
<pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="linuszhao.js.one.jsbroadcast.MainActivity"
android:orientation="vertical">

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn1"
    android:text="发起自定义广播"/>
<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn2"
    android:text="动态发送广播"/>
<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/btn3"
    android:text="发起本地广播"/>

</LinearLayout>
</pre>
Androidmanifest.xml
<pre>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="linuszhao.js.one.jsbroadcast">

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<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=".MyBroadcastReceive">
        <intent-filter>
            //通过android:name来指定具体注册哪一个广播接收器
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

    //注册广播接收机
    <receiver android:name=".DiyBroadReceive">
        <intent-filter>
            //通过android:name来指定具体注册哪一个广播接收器,这里可以自己任意指定name
            <action android:name="linus.diyBroadReceive" />
        </intent-filter>
    </receiver>

</application>

</manifest>
</pre>
DiyBroadReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

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

/**

  • Created by linus on 2017/3/5.
    */
    public class DiyBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"自定义广播接收机接收到的名字是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>
MyBroadcastReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

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

/**

  • Created by linus on 2017/3/5.
    */
    public class MyBroadcastReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    Toast.makeText(context,"开机启动",Toast.LENGTH_LONG).show();
    }
    }
    </pre>
    DynamicBroadReceive.java
    <pre>
    package linuszhao.js.one.jsbroadcast;

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

/**

  • Created by linus on 2017/3/5.
    */
    public class DynamicBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"动态注册广播后,接收到的名字是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>
LocalBroadReceive.java
<pre>
package linuszhao.js.one.jsbroadcast;

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

/**

  • Created by linus on 2017/3/5.
    */
    public class LocalBroadReceive extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
    String name = intent.getExtras().getString("name");
    Toast.makeText(context,"本地广播接收到的name是"+name,Toast.LENGTH_SHORT).show();
    }
    }

</pre>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,827评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 案例最后效果: 广播的类型: 标准广播 标准广播是完全异步的广播, 也就是当广播发出之后, 所有的广播接收器机会都...
    史慧君阅读 3,118评论 2 50
  • 广播接收器 是Android的四大组件之一,可见广播在Android中的重要性; 1. 什么是广播? 广播(Bro...
    Lost_Robot阅读 1,939评论 2 10
  • 我真的老了,最近我的腿疼得厉害,连下地走路都很困难了,这都是年轻时候落下的病根。年轻的时候不懂得保养自己,现在浑身...
    安人阅读 921评论 3 12