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即可。

程序清单:

public class LaunchWithSys extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
                   // TODO Auto-generated method stub
                   Intent launchService=new Intent(context, LaunchService.class);
                   //启动指定Service
                   context.startActivity(launchService);
         }
}  

从上面看该LaunchWithSys非常简单,只需要启动指定的Service即可,接下来需要注册用于监听系统开机广播的BroadcastReceiver:因此需要在AndroidManifest.xml注册一个下面的接收器:

<!—注册一个监听系统开机广播的BroadcastReceiver à
<receiver android:name=”com.jph.monitorbroadcastfromsys.LaunchWithSys”>
<intent-filter>
        <action android:name=”android.intent.action.BOOT_COMPLETED”></action>
</intent-filter>
</receiver>

除此之外,为了能够让程序访问开机启动事件,需要为程序添加如下的权限:

<pre name="code" class="html"><!—为程序添加访问系统开机事件的权限 à
         <uses-permission android:name=”android.permission.RECEIVE_BOOT_COMPLETED”/>

实例二:短息提醒

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

程序清单:

public class SmsReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
                   // TODO Auto-generated method stub
                   //如果收到短信
                   if (intent.getAction().equals(“android.provider.Telephony.SMS_RECEIVED”)) {
                            //取消这条有序广播(取消后会让其它应用收不到短信)
                            abortBroadcast();
                            Bundle bundle=intent.getExtras();
                            if (bundle!=null) {//如果数据不为空
                                     //获得收到的短信数据
                                     Object[] objArray=(Object[]) bundle.get(“pdus”);
                                     //根据objArray的大小创建一个SmsMessage数组,用于封装短信内容
                                     SmsMessage []smsMessage=new SmsMessage[objArray.length];
                                     StringBuffer sb=new StringBuffer();
                                     sb.append(“时间:”+new DateFormat().format(“yyyy-MM-dd hh.mm.ss”, new Date()));
                                     //遍历smsMessage数组取出所有短信
                                     for (int i = 0; i < smsMessage.length; i++) {
                                               //将每条字节类型的短信数据转换成SmsMessage对象
                                               smsMessage[i]=SmsMessage.createFromPdu((byte[])objArray[i]);
                                               //获取短信发送地址
                                               sb.append(“发送者:”+smsMessage[i].getOriginatingAddress());
                                               //获取短信内容
                                               sb.append(“短信内容:”+smsMessage[i].getDisplayMessageBody()+”\n”);
                                     }
                                     Toast.makeText(context, sb.toString(), Toast.LENGTH_LONG).show();
                            }
                   }
         }
}

实例分析:

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

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

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

<!—注册一个BroadcastReceiver监听系统收到短信发出的广播 à
<receiver android:name=”com.jph.monitorbroadcastfromsys.SmsReceiver”>
<!—给接收器设个较高的优先级 以便能在其它程序收到广播前结束广播à
<intent-filter android:priority=”666”>
<action android:name=”android.provider.Telephony.SMS_RECEIVED”></action>
</intent-filter>
</receiver>

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

<!—为程序添加接收短信的权限 à
         <uses-permission android:name=”android.permission.RECEIVE_SMS”/>
 

运行效果图:

实例三:手机电量提醒

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

程序清单:

public class MianActivity extends Activity {
         TextView show;
         @Override
         protected void onCreate(Bundle savedInstanceState) {
                   super.onCreate(savedInstanceState);
                   setContentView(R.layout.mian);
                   show=(TextView)findViewById(R.id.show);
                   ShowPowerReceiver showPowerReceiver=new ShowPowerReceiver();
                   IntentFilter filter=new IntentFilter();
                   filter.addAction(Intent.ACTION_BATTERY_CHANGED);
                   //注册showPowerReceiver
                   registerReceiver(showPowerReceiver, filter);
         }
         /**
          * Describe:</br>
          * 手机电量提醒
          * */
         class ShowPowerReceiver extends BroadcastReceiver {
                   @Override
                   public void onReceive(Context context, Intent intent) {
                            // TODO Auto-generated method stub
                            //判断接收到的是否为电量变化的BroadCast Action
                            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
                                     //当前电量
                                     int level=intent.getIntExtra("level", 0);
                                     //总电量
                                     int scale=intent.getIntExtra("scale", 100);
                                     int current=level*100/scale;
                                     show.setText("当前电量:"+current+"%");
                            }
                   }
         }
}

程序运行效果图:

实例四:来去电提醒

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

程序清单:

来电提醒
public class InCallReceiver extends BroadcastReceiver
{
         private static Object obj;
         /**
          * 创建一个永不关闭的Toast
          * @param context Context context上下文
          * @param msg String msg 消息提示信息
          * */
         public static void showToast(Context context, String msg)
         {
                   //创建一个Toast对象
                   Toast toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
                   //设置Toast的显示位置
                   toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
                   try
                   {
                            //从toast对象中获取mTN对象
                            Field field = toast.getClass().getDeclaredField("mTN");
                            field.setAccessible(true);
                            obj = field.get(toast);
                            //从TN对象中获得show方法
                            Method method = obj.getClass().getDeclaredMethod("show", null);
                            //调用TN对象的show方法来显示Toast信息提示框
                            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)
                            {
                            }
                   }
         }
         @Override
         public void onReceive(final Context context, final Intent intent)
         {
                   //获取电话管理服务
                   TelephonyManager tm = (TelephonyManager) context
                                     .getSystemService(Service.TELEPHONY_SERVICE);

                   switch (tm.getCallState())
                   {
                            case TelephonyManager.CALL_STATE_RINGING://响铃
                                     String incomingNumber = intent
                                                        .getStringExtra("incoming_number");
                                     showToast(context, incomingNumber);
                                     break;
                            case TelephonyManager.CALL_STATE_OFFHOOK://接听电话
                                     Log.d("call_state", "offhook");
                                     break;

                            case TelephonyManager.CALL_STATE_IDLE://挂断电话
                                     closeToast();
                   }
         }
}

//去电提醒
public class OutCallReceiver extends BroadcastReceiver
{        @Override
         public void onReceive(Context context, Intent intent)
         {
                   //获取去电的电话号码
                   String outcomingNumber = intent
                                     .getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                   InCallReceiver.showToast(context, outcomingNumber);
         }

}

配置文件:AndroidManifest.xml

<!-- 为程序添加访问电话状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
         <!-- 为程序添加允许程序监视,修改或放弃播出电话 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />

<!-- 注册一个BroadcastReceiver监听系发出的电话状态的广播 -->
<receiver android:name=".InCallReceiver" android:enabled="true">
         <intent-filter>
                   <action android:name="android.intent.action.PHONE_STATE" />
         </intent-filter>
</receiver>
 <!-- 注册一个BroadcastReceiver监听系统发出的新来电的广播 -->
<receiver android:name=".OutCallReceiver" android:enabled="true">
         <intent-filter>
                   <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
         </intent-filter>
</receiver>
         

程序运行效果图:

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

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

时间: 2024-10-15 13:35:34

Android开发之接收系统广播消息的相关文章

android开发 socket接收图片并保存

逻辑:接收到socket之后需要将socket发送的图片数据保存下来并通知handler更新界面 关键代码: public void readImage(Socket socket) { try { InputStream in = socket.getInputStream(); BufferedInputStream bis = new BufferedInputStream(in); Bitmap bitmap = BitmapFactory.decodeStream(bis);//这个好

BroadcastReceiver接收系统广播消息

Android常用的广播Action常量: ACTION_TIME_CHANGED:系统时间被改变. ACTION_DATE_CHANGED:系统日期被改变. ACTION_TIMEZONE_CHANGED:系统时区被改变. ACTION_BOOT_COMPLETED:系统启动完成. ACTION_PACKAGE_ADDED:系统添加包. ACTION_PACKAGE_CHANGED:系统的包改变. ACTION_PACKAGE_REMOVED:系统的包被删除. ACTION_PACKAGE_R

【Android开发那点破事】消息推送BroadcastReceiver,点击通知打开两次Activity问题

Android开发中,通常会使用BroadcastReceiver来接受Push推送消息.当APP收到推送通知时,我们需要在通知的点击事件中加入自己的逻辑.比如跳转到MainActivity.比如下面的代码(注意红色部分): public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (JPushInterface.ACTION_REGISTRATION_ID.equ

Android 开发艺术探索——第十章 Android的消息机制

Android 开发艺术探索--第十章 Android的消息机制读书笔记 Handler并不是专门用于更新UI的,只是常被用来更新UI 概述 Android的消息机制主要值得就是Handler的运行机制,Handler的运行需要底层的MessageQueue和Looper的支撑. MessageQueue即为消息队列,顾名思义,它的内部存储了一组消息,以队列的的形式对外提供插入和删除的工作.虽然叫队列,但内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表. Looper意思为循

android开发 Activity间消息的传递方式

<pre name="code" class="java">//MainActivity.java Intent intent = new Intent(); Bundle bundle = new Bundle(); bundle.putInt("data1", 10); bundle.putString("data2", "data"); //从当前的MainActivity 切换到Acti

Android开发笔记(一百零四)消息推送SDK

推送的集成 常用概念 推送:从服务器把消息实时发到客户端app上,这就是推送,推送可用于发送系统通知.发送推荐信息.发送聊天消息等等. 别名:用于给移动设备取个好记的名字,比如电脑有计算机名,可以把别名理解为开发者给移送设备起的外号.不过,多个移动设备可以起一样的别名,这几个设备就会同时收到发给该别名的消息. 标记:用于给移动设备打标签,可以理解为分类,比如超市里的泰国大米既可以打上"粮食制品"的标签,也可以打上"进口商品"的标签.服务器可以统一给某个种类的移动设备

Android开发学习之路-Handler消息派发机制源码分析

注:这里只是说一下sendmessage的一个过程,post就类似的 如果我们需要发送消息,会调用sendMessage方法 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } 这个方法会调用如下的这个方法 public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMilli

Delphi XE7 用indy开发微信公众平台(4)- 接收普通消息

接收普通消息 type TMsgType = (event, text, image, voice, video, location, link); TMessage = Record ToUserName: String; FromUserName: String; CreateTime: Integer; MsgType: String; end; uses System.SysUtils, System.JSON, TypInfo, Xml.XMLIntf, Xml.XMLDoc, Act

《微信企业号开发日志》之接收普通消息

接收普通消息 普通消息是指员工向企业号应用发送的消息,包括文本.图片.语音.视频.地理位置等类型.普通消息会推送到每个应用在管理端设置的URL(以下假设该URL为http://api.3dept.com). 请求说明 Http请求方式: POST http://api.3dept.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS&timestamp=13500001234&nonce=123412323 text消息 <xml> <T