`
hyz301
  • 浏览: 371508 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android学习轨迹之一:Android BroadcastReceiver 学习

阅读更多
BroadcastReceiver 用于异步接收广播Intent。主要有两大类,用于接收广播的:
  • 正常广播 Normal broadcasts(用 Context.sendBroadcast()发送)是完全异步的。它们都运行在一个未定义的顺序,通常是在同一时间。这样会更有效,但意味着receiver不能包含所要使用的结果或中止的API。  
  • 有序广播 Ordered broadcasts(用 Context.sendOrderedBroadcast()发送)每次被发送到一个receiver。所谓有序,就是每个receiver执行后可以传播到下一个receiver,也可以完全中止传播——不传播给其他receiver。 而receiver运行的顺序可以通过matched intent-filter 里面的android:priority来控制,当priority优先级相同的时候,Receiver以任意的顺序运行。
    要注意的是,即使是Normal broadcasts,系统在某些情况下可能会恢复到一次传播给一个receiver。 特别是receiver可能需要创建一个进程,为了避免系统超载,只能一次运行一个receiver。
    Broadcast Receiver 并没有提供可视化的界面来显示广播信息。可以使用Notification和Notification Manager来实现可视化的信息的界面,显示广播信息的内容,图标及震动信息。
生命周期
    一个BroadcastReceiver 对象只有在被调用onReceive(Context, Intent)的才有效的,当从该函数返回后,该对象就无效的了,结束生命周期。
    因此从这个特征可以看出,在所调用的onReceive(Context, Intent)函数里,不能有过于耗时的操作,不能使用线程来执行。对于耗时的操作,请start service来完成。因为当得到其他异步操作所返回的结果时,BroadcastReceiver 可能已经无效了。
发送广播
    事件的广播比较简单,构建Intent对象,可调用sendBroadcast(Intent)方法将广播发出。另外还有sendOrderedBroadcast(),sendStickyBroadcast()等方法,请查阅API Doc。
    1.new Intent with action name 
        Intent intent = new Intent(String action);
      或者 只是new Intent, 然后
        intent.setAction(String action);
    2.set data等准备好了后,in activity,
        sendBroadcast(Intent); // 发送广播
接收广播
    通过定义一个继承BroadcastReceiver类来实现,继承该类后覆盖其onReceiver方法,并在该方法中响应事件。
public class SMSReceiver extends BroadcastReceiver { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
                // get data from SMS intent 
                Bundle bundle = intent.getExtras(); 
                if (bundle != null){ 
                        // get message by "pdus" 
                        Object[] objArray = (Object[]) bundle.get("pdus"); 
                        // rebuild SMS 
                        SmsMessage[] messages = new SmsMessage[objArray.length]; 
                        for (int i=0; i < objArray.length; i++){ 
                               messages[i] = SmsMessage.createFromPdu((byte[])objArray[i]);                                StringBuilder str = new StringBuilder("from: "); 
                                str.append(messages[i].getDisplayOriginatingAddress()); 
                                str.append("\nmessage:\n"); 
                                str.append(messages[i].getDisplayMessageBody()); 
                                Toast.makeText(context, str.toString(), Toast.LENGTH_LONG) 
                                                .show(); 
                        } 
                } 
        } 
}
 注册Receiver
   注册有两种方式:
   1. 静态方式,在AndroidManifest.xml的application里面定义receiver并设置要接收的action。
<receiver android:name=".SMSReceiver"> 
        <intent-filter> 
                <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
        </intent-filter> 
</receiver>
 2. 动态方式, 在activity里面调用函数来注册,和静态的内容差不多。一个形参是receiver,另一个是IntentFilter,其中里面是要接收的action。
public class HelloDemo extends Activity {    
        private BroadcastReceiver receiver;    
        @Override 
        protected void onStart() { 
                super.onStart(); 
                receiver = new CallReceiver(); 
                registerReceiver(receiver, new IntentFilter("android.intent.action.PHONE_STATE")); 
        } 
        @Override 
        protected void onStop() { 
                unregisterReceiver(receiver); 
                super.onStop(); 
        } 
}
    一个receiver可以接收多个action的,即可以有多个intent-filter,需要在onReceive里面对intent.getAction(action name)进行判断。
    个人推荐使用静态注册方式,由系统来管理receiver,而且程序里的所有receiver,可以在xml里面一目了然。而动态注册方式,隐藏在代码中,比较难发现。
    而且动态注册,需要特别注意的是,在退出程序前要记得调用Context.unregisterReceiver()方法。一般在activity的onStart()里面进行注册, onStop()里面进行注销。官方提醒,如果在Activity.onResume()里面注册了,就必须在Activity.onPause()注销。
Permission权限
  要接收某些action,需要在AndroidManifest.xml里面添加相应的permission。例如接收SMS:
<uses-permission android:name="android.permission.RECEIVE_SMS" />
 下面给出动态注册的接收来电的广播处理的CallReceiver的代码:
   一种方式是直接读取intent.getStringExtra("incoming_number")来获取来电号码:
public class CallReceiver extends BroadcastReceiver { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
                TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 
                        switch(teleManager.getCallState()){ 
                case TelephonyManager.CALL_STATE_RINGING: //响铃 
                        Toast.makeText(context, "Ringing: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show(); 
                        break; 
                case TelephonyManager.CALL_STATE_OFFHOOK: //接听 
                        Toast.makeText(context, "OffHook: " + intent.getStringExtra("incoming_number"), Toast.LENGTH_LONG).show(); 
                        break; 
                case TelephonyManager.CALL_STATE_IDLE: //挂断 
                        Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG).show(); 
                        break; 
                } 
        } 
}
 在运行时,发现除了响铃时可以获取来电号码,接听和挂断都不能成功获取的,显示为null。
   另一种方式是通过PhoneStateListener的onCallStateChanged来监听状态的变化:
public class CallReceiver extends BroadcastReceiver { 
        private Context m_context; 
        @Override 
        public void onReceive(Context context, Intent intent) { 
                m_context = context; 
                TelephonyManager teleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 
                teleManager.listen(new PhoneStateListener(){ 
                        @Override 
                        public void onCallStateChanged(int state, String incomingNumber) { 
                                switch(state){ 
                                case TelephonyManager.CALL_STATE_RINGING: //响铃 
                                        Toast.makeText(m_context, "Ringing: " + incomingNumber, Toast.LENGTH_LONG) 
                                                                .show(); 
                                        break; 
                                case TelephonyManager.CALL_STATE_OFFHOOK: //接听 
                                        Toast.makeText(m_context, "OffHook: " + incomingNumber, Toast.LENGTH_LONG) 
                                        .show(); 
                                        break; 
                                case TelephonyManager.CALL_STATE_IDLE: //挂断 
                                        Toast.makeText(m_context, "Idle: " + incomingNumber, Toast.LENGTH_LONG) 
                                        .show(); 
                                        break; 
                                } 
                        }}, PhoneStateListener.LISTEN_CALL_STATE);  
        } 
}
 运行时也发现incomingNumber在接听和挂断时获取为blank。
    因为这里监听的是通话的状态变化,所以这个receiver会被调用3次。
    监听通话状态需要加上权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
 ===========
小结:
1. 对于sendBroadCast的intent对象,需要设置其action name; 
2. 推荐使用显式指明receiver,在配置文件AndroidManifest.xml指明; 
3. 一个receiver可以接收多个action; 
4. 每次接收广播都会重新生成一个接收广播的对象,再次调用onReceive;
5. 在BroadCast 中尽量不要处理太多逻辑问题,建议复杂的逻辑交给Activity 或者 Service 去处理。
分享到:
评论

相关推荐

    Google Android SDK开发范例大全(PDF高清完整版1)(4-1)

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK开发范例大全(PDF完整版4)(4-4)

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK开发范例大全(PDF高清完整版3)(4-3)

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK开发范例大全的目录

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK开发范例大全(完整版附部分源码).pdf

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的...

    Google Android SDK 开发范例大全01

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK 开发范例大全02

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google+Android+SDK开发范例大全

    6.4 开始与停止系统服务——Service与Runnable整合并用 6.5 通过短信发送email通知——BroadcastReceiver与Intent整合 6.6 手机拨接状态——PhoneStateListener之onCallStateChanged 6.7 有来电,发送邮件通知——...

    Google Android sdk 开发范例大全 部分章节代码

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Google Android SDK开发范例大全(完整版)

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

Global site tag (gtag.js) - Google Analytics