首页 > 代码库 > Android_ UEventObserver_监听USB插拔
Android_ UEventObserver_监听USB插拔
本博文为子墨原创,转载请注明出处!
http://blog.csdn.net/zimo2013/article/details/38950363
1.简介
最近做一个项目,主要通过usb完成pc与Android端的数据传输。但是根据api提供的无法监听usb的插拔,有解释为不同版本会存在BUG。本打算放弃跳过监听usb,改为在连上usb后pc点击按钮发出一个广播来主动打开Android端的应用程序,然后通过socket完成数据交互。这里主要通过UEventObserver,而该类位于/frameworks/base/core/java/android/os/UEventObserver.java中,位于framework框架。需要手动导入编译好的frameworks,下载frameworks.jar。
2.如何导入frameworks.jar
在工程的Build Path 中,Add External JARs中选择frameworks.jar,然后需要最好配置Order中将frameworks.jar置前,对于定制的frameworks也可以这样导入。
3.实现UEventObserver
public class MyService extends Service { private final static String TAG = SMSService.class.getSimpleName(); private UsbUEventObserver usbObserver = null; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); LogUtil.d(TAG, "onCreate()"); usbObserver = new UsbUEventObserver(); usbObserver.startObserving(USB_STATE_MATCH); usbObserver.startObserving(ACCESSORY_START_MATCH); } public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { // } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { LogUtil.d(TAG, "onDestroy()"); if (usbObserver != null) { usbObserver.stopObserving(); } super.onDestroy(); } private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0"; private static final String ACCESSORY_START_MATCH = "DEVPATH=/devices/virtual/misc/usb_accessory"; private class UsbUEventObserver extends UEventObserver { @Override public void onUEvent(final UEventObserver.UEvent event) { LogUtil.i(TAG, "usb:" + event.toString()); final String state = event.get("USB_STATE"); final String accessory = event.get("ACCESSORY"); if (state != null) { // mHandler.updateState(state); if (state.equalsIgnoreCase("CONNECTED")) { Intent intent2 = new Intent(getApplicationContext(), MainActivity.class); intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getApplicationContext().startActivity(intent2); BroadUtil.sendBroadcastConnected(getApplicationContext(), Constants.ConnectedType.USB_CONNECTED); } else if (state.toUpperCase().contains("DISCONNECTED")) { BroadUtil.sendBroadcastConnected(getApplicationContext(), Constants.ConnectedType.USB_DISCONNECTED); } } else if ("START".equals(accessory)) { // startAccessoryMode(); } } }; }
4.附UsbDeviceManager源码
/** * UsbDeviceManager manages USB state in device mode. */ public class UsbDeviceManager { private static final String TAG = UsbDeviceManager.class.getSimpleName(); private static final boolean DEBUG = false; private static final String USB_STATE_MATCH = "DEVPATH=/devices/virtual/android_usb/android0"; private static final String ACCESSORY_START_MATCH = "DEVPATH=/devices/virtual/misc/usb_accessory"; private static final String FUNCTIONS_PATH = "/sys/class/android_usb/android0/functions"; private static final String STATE_PATH = "/sys/class/android_usb/android0/state"; private static final String MASS_STORAGE_FILE_PATH = "/sys/class/android_usb/android0/f_mass_storage/lun/file"; private static final String RNDIS_ETH_ADDR_PATH = "/sys/class/android_usb/android0/f_rndis/ethaddr"; private static final int MSG_UPDATE_STATE = 0; private static final int MSG_ENABLE_ADB = 1; private static final int MSG_SET_CURRENT_FUNCTION = 2; private static final int MSG_SYSTEM_READY = 3; private static final int MSG_BOOT_COMPLETED = 4; // Delay for debouncing USB disconnects. // We often get rapid connect/disconnect events when enabling USB functions, // which need debouncing. private static final int UPDATE_DELAY = 1000; private UsbHandler mHandler; private boolean mBootCompleted; private final Context mContext; private final ContentResolver mContentResolver; private final UsbSettingsManager mSettingsManager; private NotificationManager mNotificationManager; private final boolean mHasUsbAccessory; private boolean mUseUsbNotification; private boolean mAdbEnabled; private class AdbSettingsObserver extends ContentObserver { public AdbSettingsObserver() { super(null); } @Override public void onChange(boolean selfChange) { boolean enable = (Settings.Secure.getInt(mContentResolver, Settings.Secure.ADB_ENABLED, 0) > 0); mHandler.sendMessage(MSG_ENABLE_ADB, enable); } } /* * Listens for uevent messages from the kernel to monitor the USB state */ private final UEventObserver mUEventObserver = new UEventObserver() { @Override public void onUEvent(UEventObserver.UEvent event) { if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); String state = event.get("USB_STATE"); String accessory = event.get("ACCESSORY"); if (state != null) { mHandler.updateState(state); } else if ("START".equals(accessory)) { if (DEBUG) Slog.d(TAG, "got accessory start"); setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false); } } }; public UsbDeviceManager(Context context, UsbSettingsManager settingsManager) { mContext = context; mContentResolver = context.getContentResolver(); mSettingsManager = settingsManager; PackageManager pm = mContext.getPackageManager(); mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); initRndisAddress(); // create a thread for our Handler HandlerThread thread = new HandlerThread("UsbDeviceManager", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mHandler = new UsbHandler(thread.getLooper()); if (nativeIsStartRequested()) { if (DEBUG) Slog.d(TAG, "accessory attached at boot"); setCurrentFunction(UsbManager.USB_FUNCTION_ACCESSORY, false); } } public void systemReady() { if (DEBUG) Slog.d(TAG, "systemReady"); mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); // We do not show the USB notification if the primary volume supports mass storage. // The legacy mass storage UI will be used instead. boolean massStorageSupported = false; StorageManager storageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE); StorageVolume[] volumes = storageManager.getVolumeList(); if (volumes.length > 0) { massStorageSupported = volumes[0].allowMassStorage(); } mUseUsbNotification = !massStorageSupported; // make sure the ADB_ENABLED setting value matches the current state Settings.Secure.putInt(mContentResolver, Settings.Secure.ADB_ENABLED, mAdbEnabled ? 1 : 0); mHandler.sendEmptyMessage(MSG_SYSTEM_READY); } private static void initRndisAddress() { // configure RNDIS ethernet address based on our serial number using the same algorithm // we had been previously using in kernel board files final int ETH_ALEN = 6; int address[] = new int[ETH_ALEN]; // first byte is 0x02 to signify a locally administered address address[0] = 0x02; String serial = SystemProperties.get("ro.serialno", "1234567890ABCDEF"); int serialLength = serial.length(); // XOR the USB serial across the remaining 5 bytes for (int i = 0; i < serialLength; i++) { address[i % (ETH_ALEN - 1) + 1] ^= (int)serial.charAt(i); } String addrString = String.format("%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2], address[3], address[4], address[5]); try { FileUtils.stringToFile(RNDIS_ETH_ADDR_PATH, addrString); } catch (IOException e) { Slog.e(TAG, "failed to write to " + RNDIS_ETH_ADDR_PATH); } } private static String addFunction(String functions, String function) { if (!containsFunction(functions, function)) { if (functions.length() > 0) { functions += ","; } functions += function; } return functions; } private static String removeFunction(String functions, String function) { String[] split = functions.split(","); for (int i = 0; i < split.length; i++) { if (function.equals(split[i])) { split[i] = null; } } StringBuilder builder = new StringBuilder(); for (int i = 0; i < split.length; i++) { String s = split[i]; if (s != null) { if (builder.length() > 0) { builder.append(","); } builder.append(s); } } return builder.toString(); } private static boolean containsFunction(String functions, String function) { int index = functions.indexOf(function); if (index < 0) return false; if (index > 0 && functions.charAt(index - 1) != ',') return false; int charAfter = index + function.length(); if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false; return true; } private final class UsbHandler extends Handler { // current USB state private boolean mConnected; private boolean mConfigured; private String mCurrentFunctions; private String mDefaultFunctions; private UsbAccessory mCurrentAccessory; private int mUsbNotificationId; private boolean mAdbNotificationShown; private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { if (DEBUG) Slog.d(TAG, "boot completed"); mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED); } }; public UsbHandler(Looper looper) { super(looper); try { // persist.sys.usb.config should never be unset. But if it is, set it to "adb" // so we have a chance of debugging what happened. mDefaultFunctions = SystemProperties.get("persist.sys.usb.config", "adb"); // sanity check the sys.usb.config system property // this may be necessary if we crashed while switching USB configurations String config = SystemProperties.get("sys.usb.config", "none"); if (!config.equals(mDefaultFunctions)) { Slog.w(TAG, "resetting config to persistent property: " + mDefaultFunctions); SystemProperties.set("sys.usb.config", mDefaultFunctions); } mCurrentFunctions = mDefaultFunctions; String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim(); updateState(state); mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB); // Upgrade step for previous versions that used persist.service.adb.enable String value = http://www.mamicode.com/SystemProperties.get("persist.service.adb.enable", "");>
Android_ UEventObserver_监听USB插拔
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。