现在的位置: 首页 > 综合 > 正文

增加 addDataScheme(“file”) 才能收到SD卡插拔事件的原因分析 — 浅析android事件过滤策略

2013年03月05日 ⁄ 综合 ⁄ 共 3812字 ⁄ 字号 评论关闭

http://blog.csdn.net/silenceburn/article/details/6083375

===========================================



如有错漏请不吝拍砖指正,转载请注明出处,非常感谢

 


 

有一个问题,在网上被频繁的问到,就是为什么自定义的Receiver总是无法接收到SD卡插拔的事件。

而此问题大部分情况下可以通过增加一句代码解决: filter.addDataScheme("file");  // filter是IntentFilter对象

 

那么为什么增加这句代码就可以解决了呢?这个问题尽管有人问到,但是却没有太好的回答。

可能是因为对于精通IntentFilter策略的高手们来说,这根本算不上问题,是一个再明显不过的事实而已。

而对于不太了解IntentFilter策略的我们初学者来说,这个问题又暂时有点太难以理解吧。

 

因此,本文试着通过对android的事件过滤策略进行介绍和分析,结合示例程序进行验证,

来解答此问题,并浅显的介绍android事件过滤策略。

 


1. 编写示例程序,创建一个自定义的BroadcastReceiver

首先我们创建一个android工程起名为SdCardTester,作为示例程序。

为了方便在后续步骤中模拟SD卡插拔,建议将目标平台设定为2.3版本,使用2.3版本的模拟器。

此外务必注意,运行此示例程序的AVD模拟器需要增加SD卡功能支持。

 

然后为SdCardTester类增加一个BroadcastReceiver类型的成员变量 mReceiver。

在onCreate中,使用匿名类的技巧,为 mReceiver 赋值一个BroadcastReceiver子类实例。

[java] view
plain
copy

  1.      mReceiver = new BroadcastReceiver() {  
  2. @Override  
  3. public void onReceive(Context context, Intent intent) {  
  4.         Log.i("myLoger"," Receive SDCard Mount/UnMount!");  
  5. }  
  6. ;  

注意代码中重写的onRecevie函数里只有一句代码,用于记录日志。以证明我们确实收到了事件。

 

然后创建一个IntentFilter,用于过滤SD卡插拔事件。

最后把我们自定义的Receiver和编写好的IntentFilter注册到系统中

[java] view
plain
copy

  1. IntentFilter filter = new IntentFilter();  
  2. filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  3. filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  4. registerReceiver(mReceiver, filter);  

 

最后的最后不要忘了在onDestory中注销我们的自定义Receiver,

至此完成了示例程序的代码编写,SdCardTester的完整代码如下:

[java] view
plain
copy

  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10.   
  11. public class SdCardTester extends Activity {  
  12.       
  13.     BroadcastReceiver mReceiver;  
  14.       
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         mReceiver = new BroadcastReceiver() {  
  22.             @Override  
  23.             public void onReceive(Context context, Intent intent) {  
  24.                     Log.i("myLoger"," Receive SDCard Mount/UnMount!");  
  25.             }  
  26.         };  
  27.           
  28.         IntentFilter filter = new IntentFilter();  
  29.         filter.addAction(Intent.ACTION_MEDIA_MOUNTED);  
  30.         filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);  
  31.         registerReceiver(mReceiver, filter);  
  32.          
  33.     }  
  34.       
  35.     @Override  
  36.     protected void onDestroy() {  
  37.         // TODO Auto-generated method stub  
  38.         super.onDestroy();  
  39.         unregisterReceiver(mReceiver);  
  40.     }  
  41. }  

 


2. 测试示例程序

运行SdCardTester,等看到hello World 字样,说明onCreate完成,也就意味着我们自定义的Receiver也已经启动了。

 

之后,不要用BACK退出,按HOME按钮返回主屏幕,(也就是要保证我们的自定义Receiver仍然在运行)

进入手机设定,选择Storage (如果系统语言选择为中文了是“存储”),

选择 Unmount SD card / mount SD card 选项,就可以模拟SD卡插拔的动作了。如下图所示:

 

如果我们的自定义Receiver收到了相关事件,按照代码实现,就会使用 TAG "myLoger" 输出日志到logCat。

因此我们通过观察logCat输出确定是否有相关事件发生,在cmd窗口中运行 " adb logcat -s myLoger:i " ,即可持续监控日志输出。

或者使用Eclipse ADT插件增加的DDMS视图,在logCat 的View中增加一个filter,如下图所示:

 

注意,按照我们当前的代码实现,无论我们如何插拔SD卡,都不会看到日志窗口监控到事件发生。

 

OK,我们现在增加那行神奇的代码:“   filter.addDataScheme("file");   ”,

并在onCreate中增加一个日志输出监控程序进入。修改之后的代码如下:

[java] view
plain
copy

  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.BroadcastReceiver;  
  5. import android.content.Context;  
  6. import android.content.Intent;  
  7. import android.content.IntentFilter;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10.   
  11. public class SdCardTester extends Activity {  
  12.       
  13.     BroadcastReceiver mReceiver;  
  14.       
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.         Log.i("myLoger"," onCreate ......");  
  21.           
  22.         mReceiver = new BroadcastReceiver() {  
  23.             @Override  

抱歉!评论已关闭.