什么是广播机制?

简单点来说,是一种广泛运用在程序之间的传输信息的一种方式。比如,手机电量不足10%,此时系统会发出一个通知,这就是运用到了广播机制。

广播机制的三要素:

Android广播机制包含三个要素:广播(Broadcast) - 用于发送广播;广播接收器(BroadcastReceiver) - 用于接收广播;意图(Intent)-用于保存广播相关信息的媒介。

可以把它理解成我们的传统电视台,我们的电视就是一个广播接收器,然而电视有很多频道,是由电视台发送出来的,也就是广播了,意图可以理解成不同频道所播放的不同电视内容。我们每次只能观看一个频道,也就是说一个广播接收器只能接受一个广播,至于如何去区分到底是哪个广播接收器接收哪个广播,这里会有个过滤器intent-filter,我们只需要去设置intent的action标示符即可(下文会提到)。

首先,先来说下广播接收器(BroadcastReceiver):

我们要使用一个广播需要先注册它,就像我们新添一个Activity一样,需要在AndroidManifest.xml里面声明,广播亦是如此。

广播接收器注册,这里提供了2种方式

1、静态注册,也就是在配置文件AndroidManifest.xml声明:

  1. <receiver
  2. android:name="广播接收器所在的包名类名"
  3. android:enabled="true"
  4. android:process=":remote" >
  5. <intent-filter>
  6. <action android:name="过滤标示符,用来区分接收哪个广播" />
  7. </intent-filter>
  8. </receiver>

2、代码动态注册:

  1. //创建一个广播接受者
  2. MyReceiver receiver = new MyReceiver();
  3. //创建过滤器,并指定action,使之用于接收同action的广播
  4. IntentFilter filter = new IntentFilter("过滤标示符,用来区分接收哪个广播");
    //注册广播接收器
    Context.registerReceiver(receiver, filter); 

通过静态方式注册的广播接收器,不需要手动注销,该对象的实例在onReceive被调用之后就会在任意时间内被销毁,而通过动态方式注册的广播接收器,则需要在Activity进入停止或者销毁状态的时候使用unregisterReceiver方法手动注销。

  1. //注销广播接收器
  2. unregisterReceiver(receiver);

创建广播接收器也很简单,只需要去继承BroadcastRecevice并实现OnReceive方法即可,当广播发送后,系统会去检查广播接收器的过滤器与广播所发送的Intent是否一致, 如果一致调用OnReceive方法,若没有,广播接收器会一直存在着。

  1. public class MyReceiver extends BroadcastReceiver {
  2.  
  3. @Override
  4. public void onReceive(Context context, Intent intent) {
  5. // TODO Auto-generated method stub
  6. }
  7. }

注意事项:

BroadcastReceiver的生命周期只有10秒,不要在OnReceive方法内执行任何耗时操作,若要执行耗时操作可以通过发送Intent给Service操作,切记不能去开子线程,由于BroadcastReceiver只有10秒的生命周期,当宿主线程挂了,那么子线程也自动销毁了。

广播(Broadcast):

先来说下广播的种类,分为三种:

普通广播(Normal Broadcasts):

1、所有广播接收者都可以接收到的广播,同级别的接收者接收顺序随机不确定。

2、不能拦截广播的继续传播也不能处理处理广播

3、同级别动态注册高于静态注册

有序广播(Ordered Broadcasts):

1、按照接收者的优先级接收,优先级可以在intnt-filter里的priority里设置,值越大,优先级越高。

2、可以拦截广播的继续传播,高级别的广播接收器可以决定低级别的广播接收器是否能接收到广播。可以处理广播。

3、同级别动态注册高于静态注册

黏性广播(Sticky Broadcasts):

1、不能处理广播传递给下一个接收者,而且广播一直存在,不销毁。(不常用)

发送广播的方式:

以上3种广播的发送方式分别是:

Context.sendBroadcast()

Context.sendOrderBroadcast()

Context.sendStickyBroadcast()

随手写了个简单小demo,看下效果:

广播接收类:

  1. package com.example.broadcasttest;
  2.  
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.widget.Toast;
  7.  
  8. public class MyBroadcastReceive extends BroadcastReceiver {
  9.  
  10. @Override
  11. public void onReceive(Context context, Intent intent) {
  12. Toast.makeText(context, "广播被收到了!", Toast.LENGTH_SHORT).show();
  13. }
  14.  
  15. }

主程序类:

  1. package com.example.broadcasttest;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.Button;
  9.  
  10. public class MainActivity extends Activity {
  11.  
  12. private Button bt;
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17.  
  18. this.bt=(Button) findViewById(R.id.button);
  19. bt.setOnClickListener(new OnClickListener() {
  20.  
  21. @Override
  22. public void onClick(View v) {
  23. Intent intent=new Intent();
  24. intent.putExtra("msg", "你好,我是一个广播");
  25. intent.setAction("com.lcw.broadcast");
  26. intent.setClass(MainActivity.this, MyBroadcastReceive.class);
  27.  
  28. MainActivity.this.sendBroadcast(intent);
  29. }
  30. });
  31.  
  32. }
  33.  
  34. }

AndroidManifest.xml

  1. <receiver
  2. android:name="com.example.broadcasttest.MyBroadcastReceive"
  3. >
  4. <intent-filter>
  5. <action android:name="com.lcw.broadcast"></action>
  6. </intent-filter>
  7. </receiver>

配合PendingIntent和广播机制实现一个小闹钟:

先看来先什么是PendingIntent:

Intent的主要功能是表示用户的一种操作意图,当用户使用Intent之后则立刻执行用户所需要的操作,但是在Android之中也提供了一个PendingIntent操作,表示的是将要发生的操作,所谓的将要发生的Intent指的是在当前的Activity不立即使用此Intent进行处理,而将此Intent封装后传递给其他的Activity程序,而其他的Activity程序在需要使用此Intent时才进行操作。(更简单来讲:PendingIntent就是Intent的延迟包装类)

下面是PendingIntent的一些常用API:

No.
方法及常量
类型
描述
1
public static final int FLAG_CANCEL_CURRENT
常量
重新生成一个新的PendingIntent对象
2
public static final int FLAG_NO_CREATE
常量
如果不存在PendingIntent对象,则创建一个新的
3
public static final int FLAG_ONE_SHOT
常量
创建的PendingIntent对象只使用一次
4
public static final int FLAG_UPDATE_CURRENT
常量
如果PendintIntent对象已经存在,则直接使用,并且实例化一个新的Intent对象
5
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags)
普通
通过PendingIntent启动一个新的Activity
6
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
普通
通过PendingIntent启动一个新的Broadcast
7
public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags)
普通
通过PendingIntent启动一个新的Service

好了,直接代码说话吧,国际惯例先看下效果图:

  

上图的效果是利用PendingIntent包装一个意图为系统闹钟的Intent延迟到指定时间发送广播,然后定义了一个广播接收器不断扫描系统,一旦接收到此广播立即在广播接受器的OnReceive方法里调用另一个Activity,而这个Activity仅仅是一个对话框用来显示信息,如二图。由于使用到了广播机制,所以就算不开着这个Activity也可以在后台监控着这个广播。

看下具体代码吧,首先是这个对话框类,很简单的一个AlertDialog

  1. package com.example.alarmtest;
  2.  
  3. import java.text.SimpleDateFormat;
  4. import java.util.Date;
  5.  
  6. import android.app.Activity;
  7. import android.app.AlertDialog;
  8. import android.content.DialogInterface;
  9. import android.os.Bundle;
  10.  
  11. /**
  12. *
  13. * 闹钟警报类(对话框显示)
  14. *
  15. */
  16. public class AlarmActivity extends Activity {
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. new AlertDialog.Builder(AlarmActivity.this)
  21. .setIcon(R.drawable.ic_launcher)
  22. .setTitle("闹钟提醒")
  23. .setMessage(
  24. "闹钟响起,当前时间为:"
  25. + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
  26. .format(new Date()))
  27. .setPositiveButton("关闭", new DialogInterface.OnClickListener() {
  28.  
  29. @Override
  30. public void onClick(DialogInterface dialog, int which) {
  31. AlarmActivity.this.finish();
  32. }
  33. }).show();
  34. }
  35. }

再来看下广播接收器类,这里只是在Receive方法里调用上面那个Activity

  1. package com.example.alarmtest;
  2.  
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. /**
  7. *
  8. * 广播接收类(跳转闹钟提醒类)
  9. *
  10. */
  11. public class AlarmBroadcastReceiver extends BroadcastReceiver {
  12.  
  13. @Override
  14. public void onReceive(Context context, Intent intent) {
  15. Intent intent2=new Intent(context,AlarmActivity.class);
  16. intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  17. context.startActivity(intent2);
  18. }
  19.  
  20. }

看下主程序类

  1. package com.example.alarmtest;
  2.  
  3. import java.util.Calendar;
  4.  
  5. import android.app.Activity;
  6. import android.app.AlarmManager;
  7. import android.app.PendingIntent;
  8. import android.content.Intent;
  9. import android.os.Bundle;
  10. import android.view.View;
  11. import android.view.View.OnClickListener;
  12. import android.widget.Button;
  13. import android.widget.TextView;
  14. import android.widget.TimePicker;
  15. import android.widget.Toast;
  16. import android.widget.TimePicker.OnTimeChangedListener;
  17.  
  18. public class MainActivity extends Activity {
  19. // 声明界面控件
  20. private TimePicker timePicker;
  21. private TextView textView;
  22. private Button set;
  23. private Button cancel;
  24.  
  25. // 变量
  26. private int hourOfDay = 0;
  27. private int minute = 0;
  28.  
  29. // 日期操作
  30. private Calendar calendar;
  31.  
  32. // 闹钟管理
  33. private AlarmManager alarmManager;
  34.  
  35. @Override
  36. protected void onCreate(Bundle savedInstanceState) {
  37. super.onCreate(savedInstanceState);
  38. setContentView(R.layout.activity_main);
  39. initView();// 初始化控件
  40. initAction();// 初始化事件
  41. }
  42.  
  43. private void initAction() {
  44. this.timePicker.setOnTimeChangedListener(new OnTimeChangedListener() {// 设置时间控件监听
  45.  
  46. @Override
  47. public void onTimeChanged(TimePicker view, int hourOfDay,
  48. int minute) {// 这是回调函数,hourOfDay指当前选中时间,minute指当前选中分钟
  49. // 实例化并设置Calendar类
  50. MainActivity.this.calendar = Calendar.getInstance();
  51. MainActivity.this.calendar.setTimeInMillis(System
  52. .currentTimeMillis());
  53. MainActivity.this.calendar.set(Calendar.HOUR_OF_DAY,
  54. hourOfDay);
  55. MainActivity.this.calendar.set(Calendar.MINUTE, minute);
  56. MainActivity.this.calendar.set(Calendar.SECOND, 0);
  57. // 存储变量值,便于一会更新TextView控件
  58. MainActivity.this.hourOfDay = hourOfDay;
  59. MainActivity.this.minute = minute;
  60.  
  61. }
  62. });
  63.  
  64. this.set.setOnClickListener(new OnClickListener() {// 设置确定按钮监听
  65.  
  66. @Override
  67. public void onClick(View v) {
  68. Intent intent = new Intent(MainActivity.this,
  69. AlarmBroadcastReceiver.class);
  70. intent.setAction("com.lcw.alarm");
  71. PendingIntent operation = PendingIntent.getBroadcast(
  72. MainActivity.this, 0, intent,
  73. PendingIntent.FLAG_UPDATE_CURRENT);// 启动一个广播,PendingIntent为Intent的包装
  74. MainActivity.this.alarmManager
  75. .set(AlarmManager.RTC_WAKEUP,
  76. MainActivity.this.calendar.getTimeInMillis(),
  77. operation);
  78. MainActivity.this.textView.setText("闹钟时间:"
  79. + MainActivity.this.hourOfDay + "时"
  80. + MainActivity.this.minute + "分" + "00秒");
  81. Toast.makeText(MainActivity.this, "闹钟设置完毕!", Toast.LENGTH_SHORT)
  82. .show();
  83.  
  84. }
  85. });
  86.  
  87. this.cancel.setOnClickListener(new OnClickListener() {// 取消按钮监听
  88.  
  89. @Override
  90. public void onClick(View v) {
  91. Intent intent = new Intent(MainActivity.this,
  92. AlarmBroadcastReceiver.class);
  93. intent.setAction("com.lcw.alarm");
  94. PendingIntent operation = PendingIntent.getBroadcast(
  95. MainActivity.this, 0, intent,
  96. PendingIntent.FLAG_UPDATE_CURRENT);
  97. MainActivity.this.alarmManager.cancel(operation);
  98. MainActivity.this.textView.setText("当前闹钟未设置");
  99. Toast.makeText(MainActivity.this, "闹钟已删除!",
  100. Toast.LENGTH_SHORT).show();
  101. }
  102. });
  103.  
  104. }
  105.  
  106. private void initView() {
  107. this.timePicker = (TimePicker) findViewById(R.id.timepicker);
  108. this.timePicker.setIs24HourView(true);// 设置时间控件24小时制
  109. this.textView = (TextView) findViewById(R.id.timetext);
  110. this.set = (Button) findViewById(R.id.set);
  111. this.cancel = (Button) findViewById(R.id.cancel);
  112.  
  113. MainActivity.this.alarmManager = (AlarmManager) MainActivity.this
  114. .getSystemService(ALARM_SERVICE);// 获取系统闹钟管理实例
  115. }
  116.  
  117. }

安卓开发笔记——Broadcast广播机制(实现自定义小闹钟)的更多相关文章

  1. 安卓开发笔记——自定义广告轮播Banner(实现无限循环)

    关于广告轮播,大家肯定不会陌生,它在现手机市场各大APP出现的频率极高,它的优点在于"不占屏",可以仅用小小的固定空位来展示几个甚至几十个广告条,而且动态效果很好,具有很好的用户& ...

  2. [开发技巧]·Numpy广播机制的深入理解与应用

    [开发技巧]·Numpy广播机制的深入理解与应用 1.问题描述 我们在使用Numpy进行数据的处理时,经常会用到广播机制来简化操作,例如在所有元素都加上一个数,或者在某些纬度上作相同的操作.广播机制很 ...

  3. 安卓开发笔记——丰富多彩的TextView

    随手笔记,记录一些东西~ 记得之前写过一篇文章<安卓开发笔记——个性化TextView(新浪微博)>:http://www.cnblogs.com/lichenwei/p/4411607. ...

  4. 安卓开发笔记——关于开源项目SlidingMenu的使用介绍(仿QQ5.0侧滑菜单)

    记得去年年末的时候写过这个侧滑效果,当时是利用自定义HorizontalScrollView来实现的,效果如下: 有兴趣的朋友可以看看这篇文件<安卓开发笔记——自定义HorizontalScro ...

  5. 安卓开发笔记——打造万能适配器(Adapter)

    为什么要打造万能适配器? 在安卓开发中,用到ListView和GridView的地方实在是太多了,系统默认给我们提供的适配器(ArrayAdapter,SimpleAdapter)经常不能满足我们的需 ...

  6. 安卓开发笔记——关于Handler的一些总结(上)

    接上篇文章<安卓开发笔记——关于AsyncTask的使用>,今天来讲下在安卓开发里"重中之重"的另一个异步操作类Handler. 今天打算先讲下关于Handler的一些 ...

  7. 安卓开发笔记——深入Activity

    在上一篇文章<安卓开发笔记——重识Activity >中,我们了解了Activity生命周期的执行顺序和一些基本的数据保存操作,但如果只知道这些是对于我们的开发需求来说是远远不够的,今天我 ...

  8. 安卓开发笔记——TabHost组件(二)(实现底部菜单导航)

    上面文章<安卓开发复习笔记——TabHost组件(一)(实现底部菜单导航)>中提到了利用自定义View(ImageView+TextView)来设置一个底部菜单的样式 这边再补充一种更为灵 ...

  9. 安卓开发笔记——TabHost组件(一)(实现底部菜单导航)

    什么是TabHost? TabHost组件的主要功能是可以进行应用程序分类管理,例如:在用户使用windows操作系统的时候,经常见到如图所示的图形界面.     TabHost选项卡,说到这个组件, ...

随机推荐

  1. 用B表更新A表

    UPDATE dbo.POR_LOT SET POR_LOT.SHIPPED_FLAG =B.SHIPPED_FLAGFROM POR_LOT A INNER JOIN ( SELECT T5.LOT ...

  2. asp.net gridview 如何实现行点击事件

    第一步:绑定行点击事件 protected void GV_DATA_RowDataBound( object sender, GridViewRowEventArgs e ) { if( e.Row ...

  3. [git]git project仓库迁移

    转自:https://segmentfault.com/q/1010000000124379 如果你想从别的 Git 托管服务那里复制一份源代码到新的 Git 托管服务器上的话,可以通过以下步骤来操作 ...

  4. DLL接口的实现(虚函数)

    DLL接口的实现(虚函数) 我们在c++编程过程中往往要用到各种不同形式的程序库,这些库的发布方式有动态库和静态库.对于静态类库,设计良好的静态类库能实现功能上的隔离,无法避免类库实现必须重新编译.链 ...

  5. ansible普通用户su切换

    [root@361way.com ~]# cat /etc/ansible/hosts [test01] 10.212.52.14 ansible_ssh_user=test ansible_ssh_ ...

  6. fiddler手机端抓包

    1. 买个360随身wifi,插在台式机上生成热点,手机连上自己的wifi 如果电脑与手机本就在一个局域网,省略这一步 2. 在fiddler中如下设置: 3. 查看电脑无线连接属性 4. 在手机上设 ...

  7. MVC教程八:母版页(布局页)视图

    一.母版页介绍和使用 母版页的扩展名为".cshtml",也叫做视图布局页,它相当于网页的模板.在其他网页中,只要引用了母版页,母版页的页面内容就可以自动显示出来,设计者可以修改引 ...

  8. 如何将mysql表结构导出成Excel格式的(并带备注)另附转为word表格的方法

    方法一: 1.使用一个MySQL管理工具:SQLyog,点击菜单栏“数据库”下拉的最后一项: 导出的格式如下: 2.要想转成Excel格式的只需手动将该表复制到Excel中去. 方法二: 1.以下用的 ...

  9. DataWindow.Net组件示例(全部开源)

    1概述 1.1功能简介 Sybase公司的PowerBuilder开发工具,在以前VS工具没有成事以前,是相当风光的.微软都要与其合作,学习它Db方面的技术,才成就了SQLServer数据库.PB开发 ...

  10. R语言进行数据预处理

    R语言进行数据预处理wranging li_volleyball 2016年3月22日 data wrangling with Rpackages:tidyr dplyr Ground rules l ...