Android开发之接收系统广播消息

    BroadcastReceiver除了接收用户所发送的广播消息之外,还有一个重要的用途:接收系统广播。如果应用需要在系统特定时刻执行某些操作,就可以通过监听系统广播来实现。Android的大量系统事件都会对外发送标准广播。以下是Android常见的广播Action常量(详请参考Android API文档中关于Intent的说明)。

Action常量

说明

ACTION_TIME_CHANGED

系统时间被改变。

ACTION_DATE_CHANGED

系统日期被改变。

ACTION_TIMEZONE_CHANGED

系统时区被改变。

ACTION_BOOT_COMPLETED

系统启动完成。

ACTION_PACKAGE_ADDED

新的应用程序被安装。

ACTION_PACKAGE_CHANGED

应用程序被改变。

ACTION_PACKAGE_REMOVED

应用程序被卸载。

ACTION_PACKAGE_RESTARTED

应用程序被重新启动。

ACTION_PACKAGE_DATA_CLEARED

应用程序数据被清理。

ACTION_BATTERY_CHANGED

电池电量改变。

ACTION_SHUTDOWN

系统被关闭。

ACTION_BATTRY_LOW

电池电量低。

ACTION_POWER_CONNECTED 

外接电源被连通。

ACTION_POWER_DISCONNECTED

外接电源被断开。

ACTION_SHUTDOWN   

系统关闭。

ACTION_NEW_OUTGOING_CALL

播出电话。

ACTION _PHONE_STATE

系统通话状态改变。

通过 来监听特殊的广播,即可以实现应用跟随系统执行特定的某些操作。

实例一:开机自动运行的Service


         在实际应用总往往会让一些应用跟随系统启动,比如一个黑名单来电自动拦截的APP,监听垃圾短信的APP... ...等等。为了让Service能跟随系统启动,我们需要让BroadcastReceiver监听Action名为:ACTION_BOOT_COMPLETED常量的Intent,然后在BroadcastReceiver启动特定的Service即可。

程序清单:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class LaunchWithSys extends BroadcastReceiver {      
  2.          @Override  
  3.          public void onReceive(Context context, Intent intent) {  
  4.                    // TODO Auto-generated method stub  
  5.                    Intent launchService=new Intent(context, LaunchService.class);  
  6.                    //启动指定Service  
  7.                    context.startActivity(launchService);  
  8.          }  
  9. }    

         从上面看该LaunchWithSys非常简单,只需要启动指定的Service即可,接下来需要注册用于监听系统开机广播的BroadcastReceiver:因此需要在AndroidManifest.xml注册一个下面的接收器:
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <!—注册一个监听系统开机广播的BroadcastReceiver à  
  2. <receiver android:name=”com.jph.monitorbroadcastfromsys.LaunchWithSys”>  
  3. <intent-filter>  
  4.         <action android:name=”android.intent.action.BOOT_COMPLETED”></action>  
  5. </intent-filter>  
  6. </receiver>  

除此之外,为了能够让程序访问开机启动事件,需要为程序添加如下的权限:
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="html"><!—为程序添加访问系统开机事件的权限 à  
  2.          <uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/>  

实例二:短息提醒


     在Android中当系统收到短信后会发出一个有序的广播,该广播的Intent的Action为android.provider.Telephony.SMS_RECEIVED。因此只需要在程序中开发一个对应的BroadcastReceiver即可监听到系统接收到的短信。

程序清单:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class SmsReceiver extends BroadcastReceiver {  
  2.          @Override  
  3.          public void onReceive(Context context, Intent intent) {  
  4.                    // TODO Auto-generated method stub  
  5.                    //如果收到短信  
  6.                    if (intent.getAction().equals(“android.provider.Telephony.SMS_RECEIVED”)) {  
  7.                             //取消这条有序广播(取消后会让其它应用收不到短信)  
  8.                             abortBroadcast();  
  9.                             Bundle bundle=intent.getExtras();  
  10.                             if (bundle!=null) {//如果数据不为空  
  11.                                      //获得收到的短信数据  
  12.                                      Object[] objArray=(Object[]) bundle.get(“pdus”);  
  13.                                      //根据objArray的大小创建一个SmsMessage数组,用于封装短信内容  
  14.                                      SmsMessage []smsMessage=new SmsMessage[objArray.length];  
  15.                                      StringBuffer sb=new StringBuffer();  
  16.                                      sb.append(“时间:”+new DateFormat().format(“yyyy-MM-dd hh.mm.ss”, new Date()));  
  17.                                      //遍历smsMessage数组取出所有短信  
  18.                                      for (int i = 0; i < smsMessage.length; i++) {  
  19.                                                //将每条字节类型的短信数据转换成SmsMessage对象  
  20.                                                smsMessage[i]=SmsMessage.createFromPdu((byte[])objArray[i]);  
  21.                                                //获取短信发送地址  
  22.                                                sb.append(“发送者:”+smsMessage[i].getOriginatingAddress());  
  23.                                                //获取短信内容  
  24.                                                sb.append(“短信内容:”+smsMessage[i].getDisplayMessageBody()+”\n”);  
  25.                                      }  
  26.                                      Toast.makeText(context, sb.toString(), Toast.LENGTH_LONG).show();  
  27.                             }                            
  28.                    }  
  29.          }         
  30. }  

实例分析:

Ÿ   由于接收到的短信内容是以字节数组形式保存的,为了便于用这些数据,需要使用SmsMessage.createFromPdu方法将这些字节数组形式的数据转换成SmsMessage对象。

Ÿ   由于接收器可能收到多条短信,因此,通过“pdus”返回了一个短信数组(byte[])所以需要遍历这个数组取出每一条短信。

由于需要监测系统发出的接收短信的广播,所以在配置文件中需要进行如下配置: 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <!—注册一个BroadcastReceiver监听系统收到短信发出的广播 à  
  2. <receiver android:name=”com.jph.monitorbroadcastfromsys.SmsReceiver”>  
  3. <!—给接收器设个较高的优先级 以便能在其它程序收到广播前结束广播à  
  4. <intent-filter android:priority=”666”>  
  5. <action android:name=”android.provider.Telephony.SMS_RECEIVED”></action>  
  6. </intent-filter>  
  7. </receiver>  

另外,由于程序需要接收短信,所以需要赋予程序接收短信的权限。

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <!—为程序添加接收短信的权限 à  
  2.          <uses-permission android:name=”android.permission.RECEIVE_SMS”/>  
  3.    
运行效果图:

短消息提醒

实例三:手机电量提醒


        当手机电量发生变化是系统会发出,Intent的Action名为ACTION_BATTERY_CHANGED的广播,当手机电量过低时系统会发出Intent的Action名为ACTION_BATTRY_LOW的广播。所以,只需监测对应Intent的BroadcastReceiver便可实现手机低电量提醒的应用。

程序清单:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class MianActivity extends Activity {  
  2.          TextView show;  
  3.          @Override  
  4.          protected void onCreate(Bundle savedInstanceState) {  
  5.                    super.onCreate(savedInstanceState);  
  6.                    setContentView(R.layout.mian);  
  7.                    show=(TextView)findViewById(R.id.show);  
  8.                    ShowPowerReceiver showPowerReceiver=new ShowPowerReceiver();  
  9.                    IntentFilter filter=new IntentFilter();  
  10.                    filter.addAction(Intent.ACTION_BATTERY_CHANGED);  
  11.                    //注册showPowerReceiver  
  12.                    registerReceiver(showPowerReceiver, filter);  
  13.          }  
  14.          /** 
  15.           * Describe:</br> 
  16.           * 手机电量提醒 
  17.           * */  
  18.          class ShowPowerReceiver extends BroadcastReceiver {  
  19.                    @Override  
  20.                    public void onReceive(Context context, Intent intent) {  
  21.                             // TODO Auto-generated method stub  
  22.                             //判断接收到的是否为电量变化的BroadCast Action  
  23.                             if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {  
  24.                                      //当前电量  
  25.                                      int level=intent.getIntExtra("level"0);  
  26.                                      //总电量  
  27.                                      int scale=intent.getIntExtra("scale"100);  
  28.                                      int current=level*100/scale;  
  29.                                      show.setText("当前电量:"+current+"%");  
  30.                             }  
  31.                    }  
  32.          }  
  33. }  

程序运行效果图:

手机电量提醒

实例四:来去电提醒


       当通话状态改变时候系统会发出,Intent的Action名为ACTION _PHONE_STAT的广播,当手机播出电话时系统会发出Intent的Action名为ACTION_NEW_OUTGOING_CALL的广播。所以,只需监测对应Intent的BroadcastReceiver便可实现来去电提醒的应用。

程序清单:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 来电提醒  
  2. public class InCallReceiver extends BroadcastReceiver  
  3. {  
  4.          private static Object obj;          
  5.          /** 
  6.           * 创建一个永不关闭的Toast 
  7.           * @param context Context context上下文 
  8.           * @param msg String msg 消息提示信息 
  9.           * */  
  10.          public static void showToast(Context context, String msg)  
  11.          {  
  12.                    //创建一个Toast对象  
  13.                    Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);  
  14.                    //设置Toast的显示位置  
  15.                    toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 00);  
  16.                    try  
  17.                    {  
  18.                             //从toast对象中获取mTN对象  
  19.                             Field field = toast.getClass().getDeclaredField("mTN");  
  20.                             field.setAccessible(true);  
  21.                             obj = field.get(toast);  
  22.                             //从TN对象中获得show方法  
  23.                             Method method = obj.getClass().getDeclaredMethod("show"null);  
  24.                             //调用TN对象的show方法来显示Toast信息提示框  
  25.                             method.invoke(obj, null);  
  26.                    }  
  27.                    catch (Exception e)  
  28.                    {  
  29.                    }  
  30.          }  
  31.          /** 
  32.           * 关闭Toast 
  33.           * */  
  34.          public static void closeToast()  
  35.          {  
  36.                    if (obj != null)  
  37.                    {  
  38.                             try  
  39.                             {  
  40.                                      Method method = obj.getClass().getDeclaredMethod("hide"null);  
  41.                                      method.invoke(obj, null);  
  42.                             }  
  43.                             catch (Exception e)  
  44.                             {  
  45.                             }  
  46.                    }  
  47.          }  
  48.          @Override  
  49.          public void onReceive(final Context context, final Intent intent)  
  50.          {  
  51.                    //获取电话管理服务  
  52.                    TelephonyManager tm = (TelephonyManager) context  
  53.                                      .getSystemService(Service.TELEPHONY_SERVICE);  
  54.    
  55.                    switch (tm.getCallState())  
  56.                    {  
  57.                             case TelephonyManager.CALL_STATE_RINGING://响铃  
  58.                                      String incomingNumber = intent  
  59.                                                         .getStringExtra("incoming_number");  
  60.                                      showToast(context, incomingNumber);  
  61.                                      break;  
  62.                             case TelephonyManager.CALL_STATE_OFFHOOK://接听电话  
  63.                                      Log.d("call_state""offhook");  
  64.                                      break;  
  65.    
  66.                             case TelephonyManager.CALL_STATE_IDLE://挂断电话  
  67.                                      closeToast();  
  68.                    }  
  69.          }  
  70. }  
  71.    
  72. //去电提醒  
  73. public class OutCallReceiver extends BroadcastReceiver  
  74. {        @Override  
  75.          public void onReceive(Context context, Intent intent)  
  76.          {  
  77.                    //获取去电的电话号码  
  78.                    String outcomingNumber = intent  
  79.                                      .getStringExtra(Intent.EXTRA_PHONE_NUMBER);  
  80.                    InCallReceiver.showToast(context, outcomingNumber);  
  81.          }  
  82.    
  83. }  

配置文件:AndroidManifest.xml

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <!-- 为程序添加访问电话状态的权限 -->  
  2. <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  3.          <!-- 为程序添加允许程序监视,修改或放弃播出电话 -->  
  4. <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />  
  5.    
  6. <!-- 注册一个BroadcastReceiver监听系发出的电话状态的广播 -->  
  7. <receiver android:name=".InCallReceiver" android:enabled="true">  
  8.          <intent-filter>  
  9.                    <action android:name="android.intent.action.PHONE_STATE" />  
  10.          </intent-filter>  
  11. </receiver>  
  12.  <!-- 注册一个BroadcastReceiver监听系统发出的新来电的广播 -->  
  13. <receiver android:name=".OutCallReceiver" android:enabled="true">  
  14.          <intent-filter>  
  15.                    <action android:name="android.intent.action.NEW_OUTGOING_CALL" />  
  16.          </intent-filter>  
  17. </receiver>          
  18.            
程序运行效果图:

来去电提醒
       最后:由于在接收广播的时候,系统会为每一次接收广播单独创建一个广播接收器,即使是同一个广播的多次接收。因此,当电话处于不同的通话状态时,实际上是在不同的接收器对象中发生的,所以需要使用静态变量来保存Toast对象,不然closeTost我无法获取在上一个状态创建的Toast对象,也就无法关闭Toast信息框了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值