什么是廣播機制?
簡單點來說,是一種廣泛運用在程序之間的傳輸信息的一種方式。比如,手機電量不足10%,此時系統會發出一個通知,這就是運用到了廣播機制。
廣播機制的三要素:
Android廣播機制包含三個要素:廣播(Broadcast) - 用于發送廣播;廣播接收器(BroadcastReceiver) - 用于接收廣播;意圖(Intent)-用于保存廣播相關信息的媒介。
可以把它理解成我們的傳統電視臺,我們的電視就是一個廣播接收器,然而電視有很多頻道,是由電視臺發送出來的,也就是廣播了,意圖可以理解成不同頻道所播放的不同電視內容。我們每次只能觀看一個頻道,也就是說一個廣播接收器只能接受一個廣播,至于如何去區分到底是哪個廣播接收器接收哪個廣播,這里會有個過濾器intent-filter,我們只需要去設置intent的action標示符即可(下文會提到)。
首先,先來說下廣播接收器(BroadcastReceiver):
我們要使用一個廣播需要先注冊它,就像我們新添一個Activity一樣,需要在AndroidManifest.xml里面聲明,廣播亦是如此。
廣播接收器注冊,這里提供了2種方式
1、靜態注冊,也就是在配置文件AndroidManifest.xml聲明:
1 <receiver2 android:name="廣播接收器所在的包名類名"3 android:enabled="true"4 android:2、代碼動態注冊:
1 //創建一個廣播接受者2 MyReceiver receiver = new MyReceiver();3 //創建過濾器,并指定action,使之用于接收同action的廣播4 IntentFilter filter = new IntentFilter("過濾標示符,用來區分接收哪個廣播");5 //注冊廣播接收器 6 Context.registerReceiver(receiver, filter);通過靜態方式注冊的廣播接收器,不需要手動注銷,該對象的實例在onReceive被調用之后就會在任意時間內被銷毀,而通過動態方式注冊的廣播接收器,則需要在Activity進入停止或者銷毀狀態的時候使用unregisterReceiver方法手動注銷。
1 //注銷廣播接收器2 unregisterReceiver(receiver);創建廣播接收器也很簡單,只需要去繼承BroadcastRecevice并實現OnReceive方法即可,當廣播發送后,系統會去檢查廣播接收器的過濾器與廣播所發送的Intent是否一致, 如果一致調用OnReceive方法,若沒有,廣播接收器會一直存在著。
1 public class MyReceiver extends BroadcastReceiver {2 3 @Override4 public void onReceive(Context context, Intent intent) {5 // TODO Auto-generated method stub6 }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 @Override11 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 @Override14 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 @Override22 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 @Override18 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 @Override30 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 @Override14 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.this114 .getSystemService(ALARM_SERVICE);// 獲取系統鬧鐘管理實例115 }116 117 }新聞熱點
疑難解答