ITPub博客

首页 > Linux操作系统 > Linux操作系统 > Android系统中的广播(Broadcast)机制简要介绍和学习计划 .(二)

Android系统中的广播(Broadcast)机制简要介绍和学习计划 .(二)

原创 Linux操作系统 作者:broadviewbj 时间:2012-11-01 15:05:17 0 删除 编辑
 再来看MainActivity的界面文件,它定义在res/layout/main.xml文件中:

  1. xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"   
  6.     android:gravity="center">  
  7.     <LinearLayout  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_marginBottom="10px"  
  11.         android:orientation="horizontal"   
  12.         android:gravity="center">  
  13.         <TextView    
  14.         android:layout_width="wrap_content"   
  15.             android:layout_height="wrap_content"   
  16.             android:layout_marginRight="4px"  
  17.             android:gravity="center"  
  18.             android:text="@string/counter">  
  19.         TextView>  
  20.         <TextView    
  21.             android:id="@+id/textview_counter"  
  22.         android:layout_width="wrap_content"   
  23.             android:layout_height="wrap_content"   
  24.             android:gravity="center"  
  25.             android:text="0">  
  26.         TextView>  
  27.     LinearLayout>  
  28.     <LinearLayout  
  29.         android:layout_width="fill_parent"  
  30.         android:layout_height="wrap_content"  
  31.         android:orientation="horizontal"   
  32.         android:gravity="center">  
  33.         <Button   
  34.             android:id="@+id/button_start"  
  35.             android:layout_width="wrap_content"  
  36.             android:layout_height="wrap_content"  
  37.             android:gravity="center"  
  38.             android:text="@string/start">  
  39.         Button>  
  40.         <Button   
  41.             android:id="@+id/button_stop"  
  42.             android:layout_width="wrap_content"  
  43.             android:layout_height="wrap_content"  
  44.             android:gravity="center"  
  45.             android:text="@string/stop" >  
  46.         Button>  
  47.      LinearLayout>    
  48. LinearLayout>  
        这个界面配置文件也很简单,等一下我们在模拟器把这个应用程序启动起来后,就可以看到它的截图了。

        应用程序用到的字符串资源文件位于res/values/strings.xml文件中:

  1. xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string name="app_name">Broadcaststring>  
  4.     <string name="counter">Counter: string>  
  5.     <string name="start">Start Counterstring>  
  6.     <string name="stop">Stop Counterstring>  
  7. resources>  
         最后,我们还要在工程目录下放置一个编译脚本文件Android.mk:

  1. LOCAL_PATH:= $(call my-dir)        
  2. include $(CLEAR_VARS)        
  3.         
  4. LOCAL_MODULE_TAGS := optional        
  5.         
  6. LOCAL_SRC_FILES := $(call all-subdir-java-files)        
  7.         
  8. LOCAL_PACKAGE_NAME := Broadcast        
  9.         
  10. include $(BUILD_PACKAGE)    
          接下来就要编译了。有关如何单独编译Android源代码工程的模块,以及如何打包system.img,请参考如何单独编译Android源代码中的模块一文。
          执行以下命令进行编译和打包:
  1. USER-NAME@MACHINE-NAME:~/Android$ mmm packages/experimental/Broadcast          
  2. USER-NAME@MACHINE-NAME:~/Android$ make snod     
         这样,打包好的Android系统镜像文件system.img就包含我们前面创建的Broadcast应用程序了。
         再接下来,就是运行模拟器来运行我们的例子了。关于如何在Android源代码工程中运行模拟器,请参考在Ubuntu上下载、编译和安装Android最新源代码一文。
         执行以下命令启动模拟器:
  1. USER-NAME@MACHINE-NAME:~/Android$ emulator  
        模拟器启动起,就可以App Launcher中找到Broadcast应用程序图标,接着把它启动起来,然后点击界面上的Start Counter按钮,就可以把计数器服务启动起来了,计数器服务又通过广播把计数值反馈给MainActivity,于是,我们就会在MainActivity界面看到计数器的值不断地增加了:

        这样,使用广播的例子就介绍完了。回顾一下,使用广播的两个步骤:

        1. 广播的接收者需要通过调用registerReceiver函数告诉系统,它对什么样的广播有兴趣,即指定IntentFilter,并且向系统注册广播接收器,即指定BroadcastReceiver:

  1. IntentFilter counterActionFilter = new IntentFilter(CounterService.BROADCAST_COUNTER_ACTION);  
  2. registerReceiver(counterActionReceiver, counterActionFilter);  
        这里,指定感兴趣的广播就是CounterService.BROADCAST_COUNTER_ACTION了,而指定的广播接收器就是counterActonReceiver,它是一个BroadcastReceiver类型的实例。
 2. 广播的发送者通过调用sendBroadcast函数来发送一个指定的广播,并且可以指定广播的相关参数:

  1. Intent intent = new Intent(BROADCAST_COUNTER_ACTION);  
  2. intent.putExtra(COUNTER_VALUE, counter);  
  3. sendBroadcast(intent)  
        这里,指定的广播为CounterService.BROADCAST_COUNTER_ACTION,并且附带的带参数当前的计数器值counter。调用了sendBroadcast函数之后,所有注册了CounterService.BROADCAST_COUNTER_ACTION广播的接收者便可以收到这个广播了。

        在第1步中,广播的接收者把广播接收器注册到ActivityManagerService中;在第2步中,广播的发送者同样是把广播发送到ActivityManagerService中,由ActivityManagerService去查找注册了这个广播的接收者,然后把广播分发给它们。

        在第2步的分发的过程,其实就是把这个广播转换成一个消息,然后放入到接收器所在的线程消息队列中去,最后就可以在消息循环中调用接收器的onReceive函数了。这里有一个要非常注意的地方是,由于ActivityManagerService把这个广播放进接收器所在的线程消息队列后,就返回了,它不关心这个消息什么时候会被处理,因此,对广播的处理是异步的,即调用sendBroadcast时,这个函数不会等待这个广播被处理完后才返回。

            下面,我们以一个序列图来总结一下,广播的注册和发送的过程:


        虚线上面Step 1到Step 4步是注册广播接收器的过程,其中Step 2通过LoadedApk.getReceiverDispatcher在LoadedApk内部创建了一个IIntentReceiver接口,并且传递给ActivityManagerService;虚线下面的Step 5到Step 11是发送广播的过程,在Step 8中,ActivityManagerService利用上面得到的IIntentReceiver远程接口,调用LoadedApk.performReceiver接口,LoadedApk.performReceiver接口通过ActivityThread.H接口的post函数将这个广播消息放入到ActivityThread的消息队列中去,最后这个消息在LoadedApk的Args.run函数中处理,LoadedApk.Args.run函数接着调用MainActivity.BroadcastReceiver的onReceive函数来最终处理这个广播。

原博客链接:http://blog.csdn.net/luoshengyang/article/details/6730748

本文节选自《Android系统源代码情景分析》

电子工业出版社出版

罗升阳 著

        

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/13164110/viewspace-748090/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-02-22

  • 博文量
    1029
  • 访问量
    1730605