日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

全局事件-广播(Broadcast)

發布時間:2025/3/21 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 全局事件-广播(Broadcast) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是廣播

廣播是Android SDK的四大組件中唯一需要別動接收數據的組件。也就是說對于Activity、ContentProvider和Service都可以主動調用,并獲取返回數據。而負責接收Broadcast數據的接收器卻永遠不知道什么時候可以接收到廣播。從這種表現形式上看,很像面向對象中的事件(Event),對于事件(onClick、onKeydown)來說,從來不會預知用戶什么時候觸發他們,只能默默的等待不可預知的事件發生。因此,廣播也可以被成為全局事件。


接收系統廣播

短信攔截(靜態注冊)

1 編寫廣播接收器類,繼承自android.content.BroadcastReceiver類

ShortMessageReceiver.java

package com.turing.base.activity.broadcastDemo;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.telephony.SmsMessage; import android.widget.Toast;import com.apkfuns.logutils.LogUtils;import java.util.Set;public class ShortMessageReceiver extends BroadcastReceiver {private Handler handler ;public ShortMessageReceiver() {}public ShortMessageReceiver(Handler handler) {this.handler = handler ;}@Overridepublic void onReceive(Context context, Intent intent) {Bundle bundle = intent.getExtras();if (bundle != null) {Set<String> keys = bundle.keySet();//查看收的廣播包含哪些數據for (String key : keys) {LogUtils.e("bundele中的數據" + key);}// 獲取收到的短信Object[] objArray = (Object[]) bundle.get("pdus");String message = parseMessageFromRawData(objArray);Toast.makeText(context, message, Toast.LENGTH_SHORT).show();Message msg = new Message();msg.what = 1 ;msg.obj = message;handler.sendMessage(msg);/**// 定義封裝短信內容的SmsMessage對象數組SmsMessage[] message = new SmsMessage[objArray.length];// 循環處理收到的所有短信for (int i = 0; i < objArray.length; i++) {// 將每條短信數據轉換成SendMessage對象message[i] = SmsMessage.createFromPdu((byte[]) objArray[i]);// 獲取發送短信的電話號碼和短信內容String messageInfo = "手機號:" + message[i].getOriginatingAddress() + "\n";messageInfo += "短信內容:" + message[i].getDisplayMessageBody();//做個簡單的展示Toast.makeText(context, messageInfo, Toast.LENGTH_SHORT).show();}**/}}public String parseMessageFromRawData(Object[] pdus) {if (pdus == null) return null;try {StringBuilder message = new StringBuilder();for (Object pdu : pdus) {SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);if (smsMessage == null) continue;message.append("源號碼:" + smsMessage.getOriginatingAddress() + ",內容:" +smsMessage.getDisplayMessageBody());}return message.toString();} catch (Exception e) {LogUtils.e( "SMSBroadcastReceiver read sms failed", e);} catch (OutOfMemoryError oom) {LogUtils.e( "SMSBroadcastReceiver caused OOM =_=!", oom);//為了避免后續操作出現問題,gc一下System.gc();System.gc();}return null;} }

清單文件配置Receiver

<receiver android:name=".activity.broadcastDemo.ShortMessageReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED" /></intent-filter></receiver>

清單文件配置權限

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

注意事項

  • 如果不知道廣播中包含哪些數據,可以從Bundle.keySet()方法中獲取這些數據的key,將其輸出到Logcat中查看,如上述代碼所示
  • 由于接受的短信內容是以字節數組的形式保存的,為了方便使用這些數據,需要使用SmsMessage.createFromPdu方法將這些字節數據組成的數據轉換為SmsMessage對象
  • SmsMessage建議使用android.telephony.SmsMessage中的。
  • 由于接收器可能接收多條短信,因此通過pdus返回了一個短信數組。
  • 必須要指定<action android:name="android.provider.Telephony.SMS_RECEIVED" /> 我們編寫的短信接收器才可以接收系統的短信廣播,切記
  • 配置權限android.permission.RECEIVE_SMS
  • 即使注冊廣播接收器的程序關閉,接收器仍然會接收到廣播,除非從模擬器或者手機中卸載程序或者注銷接收器,否則無法阻止接收器接收廣播

用代碼注冊廣播接收器

如果在清單文件中配置廣播接收器,程序安裝后就會自動注冊廣播接收器,如果想在適當的時候注冊廣播接收器,在使用完成之后將其注銷就需要使用Java代碼來操作了。

注冊和取消方法

注冊廣播接收器的方法是 registerReceiver,注銷的方法是unregisterReceiver,定義如下:

public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter)public void unregisterReceiver(BroadcastReceiver receiver)

其中receiver表示廣播接收器對象,
filter參數相當于設置intent-filter標簽中的內容。

Code

package com.turing.base.activity.broadcastDemo;import android.app.Activity; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;import com.turing.base.R;public class SmsMessageAct extends Activity implements View.OnClickListener {private EditText et_phone, et_msg;private Button btn_registerReceiver, btn_unRegisterReceiver;private ShortMessageReceiver shortMessageReceiver;private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case 1:String message = (String) msg.obj;String pre = "源號碼:";String suf = ",內容:";et_phone.setText(message.substring((message.indexOf(pre) + pre.length()), message.indexOf(suf)));et_msg.setText(message.substring(message.indexOf(suf) + suf.length(), message.length()));break;default:break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_sms_message);initView();initEvents();// 創建廣播接收器的對象shortMessageReceiver = new ShortMessageReceiver(handler);}private void initEvents() {btn_registerReceiver.setOnClickListener(this);btn_unRegisterReceiver.setOnClickListener(this);}private void initView() {et_phone = (EditText) findViewById(R.id.id_et_phone);et_msg = (EditText) findViewById(R.id.id_et_msg);btn_registerReceiver = (Button) findViewById(R.id.id_btn_registerReceiver);btn_unRegisterReceiver = (Button) findViewById(R.id.id_btn_unRegisterReceiver);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.id_btn_registerReceiver:registerReceiver(shortMessageReceiver, new IntentFilter("android.provider.Telephony.SMS_RECEIVED"));Toast.makeText(this, "動態注冊廣播接收器成功", Toast.LENGTH_SHORT).show();break;case R.id.id_btn_unRegisterReceiver:unregisterReceiver(shortMessageReceiver);Toast.makeText(this, "動態注銷短信廣播接收器over", Toast.LENGTH_SHORT).show();break;default:break;}}@Overrideprotected void onPause() {super.onPause();if (shortMessageReceiver != null) {unregisterReceiver(shortMessageReceiver);Toast.makeText(this, "Activity onPause ,注銷短信廣播接收器over", Toast.LENGTH_SHORT).show();}} }

廣播的優先級

android:priority

通過intent-filter標簽的android:priority屬性可以設置接收器的調用優先級,該屬性值屬于一個整數,數值越大,優先級越高。

Code

<receiver android:name=".activity.service.StartupReceiver"><intent-filter android:priority="100"><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver>
  • 如果不設置優先級別,對于同一個應用程序中的廣播接收器會按照在Manifest清單文件中定義的順序調用。

    • 廣播的優先級只是對同步處理方式起作用,如果在接收器中使用了異步處理方式,則調用的順序除了和優先級有關,還和Android系統的線程調用有關。

來去電攔截

廣播動作

監聽電話狀態以用于攔截來去電,來電(監聽電話狀態)和去電的廣播動作如下:

  • 來電:android.intent.action.PHONE_STATE
  • 去電:android.intent.action.NEW_OUTGOING_CALL

來電可以分解為3個狀態:未接電話時的響鈴,接聽電話 和掛斷電話(可能是對方掛斷,也可能是自己掛斷)

監聽這三個狀態的代碼如下(使用靜態方式注冊的廣播):

CallInReceiver:

package com.turing.base.activity.broadcastDemo;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast;import com.turing.base.R;public class CallInReceiver extends BroadcastReceiver {private static Object obj;public CallInReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {// 獲取電話管理服務,以便獲取電話的狀態TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);switch (telephonyManager.getCallState()) {case TelephonyManager.CALL_STATE_RINGING: // 響鈴String incomingNumber = intent.getStringExtra("incoming_number");Toast.makeText(context, "電話響鈴中......", Toast.LENGTH_SHORT).show();//showPopupWindowToast(context,incomingNumber);break;case TelephonyManager.CALL_STATE_OFFHOOK: //接聽電話Toast.makeText(context, "電話已接通......", Toast.LENGTH_SHORT).show();break;case TelephonyManager.CALL_STATE_IDLE:// 掛斷電話Toast.makeText(context, "掛斷電話......", Toast.LENGTH_SHORT).show();//closeToast();default:break;}}/*** 使用反射,此Toast不會關閉** @param context* @param msg*/ // public static void showToast(Context context, String msg) { // Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); // toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0); // try { // Field field = toast.getClass().getDeclaredField("mTN"); // field.setAccessible(true); // obj = field.get(toast); // Method method = obj.getClass().getDeclaredMethod("show", null); // method.invoke(obj, null); // } catch (Exception e) { // } // // }/*** 通過此方法關閉那個不可關閉的Toast*/ // public static void closeToast() { // if (obj != null) { // try { // Method method = obj.getClass().getDeclaredMethod("hide", null); // method.invoke(obj, null); // } catch (Exception e) { // } // // } // }public static void showPopupWindowToast(Context context, String incomingNumber) {LayoutInflater inflater = LayoutInflater.from(context);View view = inflater.inflate(R.layout.activity_popupwd_toast, null);TextView textView = (TextView)view.findViewById(R.id.tvMsg);textView.setText("電話號碼:" + incomingNumber);final PopupWindow popupWindow = new PopupWindow(view,500 ,100);popupWindow.setTouchable(false);popupWindow.showAtLocation(view, Gravity.CENTER_HORIZONTAL,20 ,0);// 設置定時器,5秒后自動關閉android.os.Handler handler = new android.os.Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {popupWindow.dismiss();}} , 5*1000);}}

CallOutReceiver

package com.turing.base.activity.broadcastDemo;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast;public class CallOutReceiver extends BroadcastReceiver {public CallOutReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {// 獲取去電號碼String outComingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);// showToastToast.makeText(context, "去電......" + outComingNumber, Toast.LENGTH_SHORT).show();//CallInReceiver.showPopupWindowToast(context, outComingNumber);} } <!-- 來電 --><receiver android:name=".activity.broadcastDemo.CallInReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.PHONE_STATE" /></intent-filter></receiver><!-- 去電 --><receiver android:name=".activity.broadcastDemo.CallOutReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="android.intent.action.NEW_OUTGOING_CALL" /></intent-filter></receiver>

設置權限

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

截獲屏幕休眠與喚醒

按手機上的掛斷按鈕后,手機會進入休眠狀態(屏幕變黑),當再此按下手機的任意鍵后,屏幕會喚醒(屏幕變量)。這兩個動作可以通過如下兩個動作連接

廣播動作

  • 休眠狀態 Intent.ACTION_SCREEN_OFF
  • 喚醒狀態 Intent.ACTION_SCREEN_ON
private void screenOnOff() {ScreenOnOffReceiver screenOnOffReceiver = new ScreenOnOffReceiver();IntentFilter intentFilter = new IntentFilter();// 設置屏幕喚醒廣播的動作intentFilter.addAction(Intent.ACTION_SCREEN_ON);// 設置屏幕休眠廣播的動作intentFilter.addAction(Intent.ACTION_SCREEN_OFF);// 注冊registerReceiver(screenOnOffReceiver,intentFilter);} package com.turing.base.activity.broadcastDemo;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log;public class ScreenOnOffReceiver extends BroadcastReceiver {public ScreenOnOffReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {// 接收屏幕喚醒狀態的廣播if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {Log.d("screen", "ok");} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {Log.d("screen", "off");}}}

注意事項:

屏幕喚醒和休眠的廣播,只能通過代碼的以動態的方式注冊,如果在清單文件中配置,則不起作用。


開機自動運行

廣播動作

android.intent.action.BOOT_COMPLETED

Code

package com.turing.base.activity.service;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent;import com.apkfuns.logutils.LogUtils;/*** 只要完成兩項工作: 啟動服務 和 顯示一個Activity提示服務啟動成功(主題設置為Dialog的形式)*/ public class StartupReceiver extends BroadcastReceiver {public StartupReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {LogUtils.e("StartupReceiver onReceive");// 如果是開機啟動的Actionif(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){// 啟動ActivityIntent activityIntent = new Intent(context,BootCompletedMessageAct.class);// 想要在Service中啟動Activity,必須設置如下標志activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(activityIntent);//啟動服務Intent serviceIntent = new Intent(context,StartupService.class);context.startService(serviceIntent);}} } <!-- 開機廣播 --><receiver android:name=".activity.service.StartupReceiver"><intent-filter ><action android:name="android.intent.action.BOOT_COMPLETED" /></intent-filter></receiver>

顯示手機電池的當前電量

查看電池的電量也需要接收一個系統廣播,本demo是通過registerReceiver方法進行注冊的。

廣播動作

Intent.ACTION_BATTERY_CHANGED

Code

package com.turing.base.activity.broadcastDemo;import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView;import com.turing.base.R;public class BatteryInfoAct extends AppCompatActivity {private TextView tv_batteryInfo;private BroadcastReceiver batteryChangedReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {//level標識當前電量的值int level = intent.getIntExtra("level", 0);// scale標識電量的總刻度int scale = intent.getIntExtra("scale", 100);// 將當前電量換算成百分比的形式tv_batteryInfo.setText("電池用量:" + (level * 100 / scale) + "%");}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_battery_info);tv_batteryInfo = (TextView) findViewById(R.id.id_tv_battery);// 注冊廣播registerReceiver(batteryChangedReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));}@Overrideprotected void onPause() {super.onPause();if (batteryChangedReceiver != null) {unregisterReceiver(batteryChangedReceiver);}} }

發送廣播

sendBoradcast

可以通過sendBoradcast的方式發送廣播
方法定義如下:

public void sendBroadcast(Intent intent)

下面的代碼發送了一個廣播,并添加了廣播數據和category

// 指定廣播動作 Intent brdcstIntent= new Intent("com.turing.demo.sendbrdcst.MYBROADCAST"); // 添加category brdcstIntent.addCategory("xxx.xxx.xxx"); // 設置廣播數據 brdcstIntent.putExtra("name","XXXXX"); // 發送廣播 sendBoradcast(brdcstIntent);

Code

兩個工程,proj_send_broadcast, proj_custom_receiver

proj_send_broadcast

public class Main extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);}public void onClick_Send_Broadcast(View view){Intent broadcastIntent = new Intent("mobile.android.ch10.MYBROADCAST");broadcastIntent.addCategory("mobile.android.ch10.mycategory");broadcastIntent.putExtra("name", "broadcast_data");sendBroadcast(broadcastIntent);Toast.makeText(this, "廣播發送成功.", Toast.LENGTH_LONG).show();} }

proj_custom_receiver

CustomReceiver

import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.widget.Toast;public class CustomReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent){if ("mobile.android.ch10.MYBROADCAST".equals(intent.getAction())){String name = intent.getStringExtra("name");Toast.makeText(context, name, Toast.LENGTH_LONG).show();}}}

清單文件

<receiver android:name=".CustomReceiver"><intent-filter><action android:name="mobile.android.ch10.MYBROADCAST" /><category android:name="mobile.android.ch10.mycategory" /></intent-filter></receiver>

驗證廣播接收器是否注冊

private void validateReceiver(String actionName) {// 獲取PackageManagerPackageManager packageManager = getPackageManager();// 指定要查詢廣播的動作Intent intent = new Intent(actionName);// 返回已查到的廣播接收器集合,如果沒有符合條件的廣播,List長度為0List<ResolveInfo> resolveInfos = packageManager.queryBroadcastReceivers(intent,PackageManager.GET_INTENT_FILTERS);// 顯示查詢到的廣播的數量Toast.makeText(this,"已發現" + resolveInfos.size() + "個接收去電廣播的接收器" ,Toast.LENGTH_SHORT).show();StringBuilder sb = new StringBuilder();if(resolveInfos.size() > 0 ){for (ResolveInfo resolveInfo : resolveInfos){sb.append(resolveInfo.toString());}}Toast.makeText(this,sb.toString() ,Toast.LENGTH_SHORT).show();}

總結

以上是生活随笔為你收集整理的全局事件-广播(Broadcast)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。