Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1570926
  • 博文数量: 113
  • 博客积分: 3526
  • 博客等级: 中校
  • 技术积分: 1815
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-08 09:46
个人简介

记录总结自己的工作

文章分类

全部博文(113)

文章存档

2015年(19)

2014年(10)

2013年(6)

2012年(16)

2011年(24)

2010年(21)

2009年(17)

分类: 嵌入式

2011-05-09 13:36:43

    安装和卸载SD卡,通过usb和电脑建立或者断开连接,手机开机这些情况都是系统中比较重要的事件,我们很可能在这些事件发生的时候需要做某些事情。比如说在手机开机的时候自动运行某个服务,安装SD卡的时候删除一些没有的文件等等。那怎么样才能获取到这些事件呢?我们知道在android系统中很多信息的传输是通过broadcast来实现的,那么能不能也用BroadCastReceiver来获取到这些事件呢?答案是肯定的。
    
    1.对于开机事件,可以通过接收Intent.ACTION_BOOT_COMPLETED广播来获取。手机在启动完毕后,会发出这个广播,这也是这个广播唯一的发送方。但是需要注意的是要接收这个广播必须在Manifest文件中注册权限。

    2.对于安装和卸载SD卡的事件,可以通过接收Intent.ACTION_MEDIA_MOUNTED和Intent.ACTION_MEDIA_UNMOUNTED广播来获取。这个在网上已经有不少的相关文章了,需要注意的就是需要加入DataScheme才能正确地接收广播。

    3.对于USB的连接事件,我在网上找了找,发现基本没有这方面的文章。通过分析USB连接时的log文件,我发现在这个事件发生的时候会出来相应的log信息,分别是01-09 02:50:07.308: DEBUG/Vold(104): USB disconnected和01-09 02:50:07.589: DEBUG/Vold(104): USB connected。但是在源码中搜索“Vold”这个关键词却并没有结果,进入adb shell后使用ps命令查看运行的进程,104号进程是system/bin/vold进程,属于底层的服务,想要参考这部分代码的实现恐怕就没那么容易了。查看了一下Intent的成员中并没有这方面的内容,那这个事件到底要怎么获取才行呢?最后我发现原来在android系统中已经有了一个USB.java的类,可以处理相关的事件,但是这个类好像是比较新的SDK才会有。
 
   现在知道如果获取这些事件了,那实现上就简单得多了,我实现了一个简单的例子,可以做一下参考。

   1.首先创建android工程BroadCastReceverTest,包名为com.test。这个工程并不需要创建Activity。

   2.创建新类BootReceiver.java,用于接收手机的启动广播。前面已经说过了,接收这个广播需要注册权限,具体见Manifest文件。

  1. package com.test;

  2. import android.content.BroadcastReceiver;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.util.Log;

  6. /**
  7.  * Receiver for receiving boot event. When boot completed, it will start the
  8.  * service for receiving Usb connect and SDcard events.
  9.  *
  10.  */
  11. public class BootReceiver extends BroadcastReceiver {
  12.     private static final String TAG = "BroadCastTest";
  13.     public void onReceive(Context context, Intent intent) {
  14. // Log.d(TAG, intent.getAction());
  15.         if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
  16.             Log.d(TAG, "Received phone Boot Event!");
  17.             Intent mintent=new Intent("com.test.dirStartService");
  18.             Log.d(TAG,"auto startservice");
  19.             context.startService(mintent);
  20.         }
  21.     }

  22. }
     我们可以看到这个类继承了BroadcastReceiver,在收到Intent.ACTION_BOOT_COMPLETED广播后会输出log信息,并启动一个服务,在这个服务中将接收SD卡和USB的事件。

    2.创建服务类dirtStartService.java。在这个服务中创建了一个BroadcastReceiver,并为其注册SD卡和USB的事件。在收到这些事件后,会输出log信息。

  1. package com.test;

  2. import android.app.Service;
  3. import android.content.BroadcastReceiver;
  4. import android.content.Context;
  5. import android.content.Intent;
  6. import android.content.IntentFilter;
  7. import android.hardware.Usb;
  8. import android.os.IBinder;
  9. import android.util.Log;

  10. /**
  11.  * Service for receiving Usb connect and SDcard events.
  12.  *
  13.  */

  14. public class dirtStartService extends Service {
  15.     private static final String TAG = "BroadCastTest";

  16.     BroadcastReceiver mReceiver;

  17.     @Override
  18.     public IBinder onBind(Intent intent) {
  19.         return null;
  20.     }

  21.     public void onCreate() {
  22.         super.onCreate();
  23.         Log.d(TAG, "oncreate");
  24.     }

  25.     public void onStart(Intent intent, int startId) {
  26.         Log.d(TAG, "onstart");
  27.         mReceiver = new BroadcastReceiver() {
  28.             public void onReceive(Context context, Intent intent) {
  29. // Log.d(TAG, intent.getAction());
  30.                 if (intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
  31.                     Log.d(TAG, "Received SDCard Mount Event!");
  32.                 } else if (intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
  33.                     Log.d(TAG, "Received SDCard UnMount Event!");
  34.                 }else if (intent.getAction().equals(Usb.ACTION_USB_STATE)) {
  35.                     boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
  36.                     Log.d(TAG,"Received Usb event, Usb connect status is:"+connected);
  37.                 }
  38.             }
  39.         };
  40.         // Fileter for SDCard mounted and unmounted
  41.         IntentFilter filterSDCard = new IntentFilter();
  42.         filterSDCard.addAction(Intent.ACTION_MEDIA_MOUNTED);
  43.         filterSDCard.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
  44.         // must add so the receiver can receive the SD card mount and unmount
  45.         // event
  46.         filterSDCard.addDataScheme("file");
  47.         registerReceiver(mReceiver, filterSDCard);

  48.         //Filter for usb connect
  49.         IntentFilter filter = new IntentFilter();
  50.         filter.addAction(Usb.ACTION_USB_STATE);
  51.         registerReceiver(mReceiver, filter);

  52.     }
  53. }
    3. 此外就是Manifest文件,对于手机启动的广播也是在Manifest文件中注册的。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest
  3.     xmlns:android=""
  4.     package="com.test"
  5.     android:versionCode="1"
  6.     android:versionName="1.0">
  7.     <application
  8.         android:icon="@drawable/icon"
  9.         android:label="@string/app_name">

  10.         <service
  11.             android:enabled="true"
  12.             android:name=".dirtStartService">
  13.             <intent-filter>
  14.                 <action
  15.                     android:name="com.test.dirStartService"></action>
  16.             </intent-filter>
  17.         </service>

  18.         <receiver
  19.             android:name="com.test.BootReceiver">
  20.             <intent-filter>
  21.                 <action
  22.                     android:name="android.intent.action.BOOT_COMPLETED">
  23.                 </action>
  24.                 <category
  25.                     android:name="android.intent.category.HOME">
  26.                 </category>
  27.             </intent-filter>
  28.         </receiver>
  29.     </application>
  30.     <uses-sdk
  31.         android:minSdkVersion="7" />
  32. </manifest>
    需要注意的是USB.java类是不包含在android.jar中的,需要为工程引入外部包framework.jar才能正确运行程序。

    对于程序的运行要首先将程序安装到手机上,然后重新启动手机,重启后程序会收到的启动事件并启动服务,这个时候如果进行USB的连接和断开以及SD卡的加载和卸载操作服务都会收到广播,并输出log信息。输出的信息如下图所示:

阅读(19337) | 评论(14) | 转发(0) |
给主人留下些什么吧!~~

云少嘎嘎嘎2015-05-04 09:26:09

imores:园主,如果监听外设的状态都可以用service和广播吗?求指导

应该是可以的,不过先得确认一下是否会发送相应的广播

回复 | 举报

imores2015-05-03 09:22:39

园主,如果监听外设的状态都可以用service和广播吗?求指导

云少嘎嘎嘎2012-03-28 16:35:27

aaajayaaa: 大哥~非常感謝你熱心的幫忙~
現在已經可以正常執行~也可以抓到usb connection 的event
但有另一問題想請教,在你的例子public static final String USB_CONNE.....
我看了一下我这里用ICS也会出现多个event的情况,这应该是系统的问题,发了多个broadcast, 我看手机里的USB管理程序也输出了多个connected的情况。

至于这个configured,如果为真好像是表示手机和电脑之间可以传输数据了。

aaajayaaa2012-03-26 19:18:47

云少嘎嘎嘎: 行阿。你打个包发我邮箱里吧,我有空就帮你看看。qqliys@126.com。.....
大哥~非常感謝你熱心的幫忙~
現在已經可以正常執行~也可以抓到usb connection 的event
但有另一問題想請教,在你的例子public static final String USB_CONNECTED = "connected";
是回傳一boolean值,回傳的ture表示 usb connect, false表示 usb disconnect,
我在ICS 4.0和 3.2上进行USB的连接和断开,在进行USB的连接時總會接收到2個回傳"true"的even
想請問你知道原因嗎??
另外我在android 4.0.1 上看到另一變量public static final String USB_CONFIGURED = "conf

云少嘎嘎嘎2012-03-26 09:53:43

aaajayaaa: 大哥~~我現在連接收android.intent.action.BOOT_COMPLETED的事件都發生問題,不知道哪裡被我改壞掉了?
方便我寄sourcecode給你  幫我稍微看一下嗎??感謝.....
行阿。你打个包发我邮箱里吧,我有空就帮你看看。qqliys@126.com。