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子类实例。
- mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i("myLoger"," Receive SDCard Mount/UnMount!");
- }
- ;
注意代码中重写的onRecevie函数里只有一句代码,用于记录日志。以证明我们确实收到了事件。
然后创建一个IntentFilter,用于过滤SD卡插拔事件。
最后把我们自定义的Receiver和编写好的IntentFilter注册到系统中
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- registerReceiver(mReceiver, filter);
最后的最后不要忘了在onDestory中注销我们的自定义Receiver,
至此完成了示例程序的代码编写,SdCardTester的完整代码如下:
- package com.silenceburn;
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.util.Log;
- public class SdCardTester extends Activity {
- BroadcastReceiver mReceiver;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.i("myLoger"," Receive SDCard Mount/UnMount!");
- }
- };
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
- filter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- registerReceiver(mReceiver, filter);
- }
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- super.onDestroy();
- unregisterReceiver(mReceiver);
- }
- }
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中增加一个日志输出监控程序进入。修改之后的代码如下:
- package com.silenceburn;
- import android.app.Activity;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.os.Bundle;
- import android.util.Log;
- public class SdCardTester extends Activity {
- BroadcastReceiver mReceiver;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- Log.i("myLoger"," onCreate ......");
- mReceiver = new BroadcastReceiver() {
- @Override