Android 通过广播监听USB连接状态的改变

网友投稿 1539 2022-05-28

一、原理讲解

Android通过广播监听USB连接状态的改变的动作在UsbManager.java文件里,为ACTION_USB_STATE。然而在UsbManager中,该常量的注释中包含{@hide},该注释是控制该API是否开放用的。未开发的API意味着google可以随时调整该API的定义或实现方式,而不用保证向下兼容。

所以尽量避免调用未开发的API,因为一旦系统升级导致其实现方式改变,程序很有可能就直接崩溃了。

注意:

目前仍未发现 ACTION_USB_ACCESSORY_XXX 这种广播

插拔手机与电脑之间的USB线:ACTION_USB_STATE(主要参数是 Boolean connected)

插拔U盘发送的是OTG广播:ACTION_USB_DEVICE_XXX,XXX代表了ATTACH 或 DETACH,这种情况是手机是主,u盘是从,手机给U盘供电。

二、代码如下

1、MyUsbManager.java

package com.example.testapp; public class MyUsbManager { /** * Broadcast Action: A sticky broadcast for USB state change events when in device mode. * This is a sticky broadcast for clients that includes USB connected/disconnected state, *

    *
  • {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected. *
  • {@link #USB_CONFIGURED} boolean indicating whether USB is configured. currently zero if not configured, one for configured. *
  • {@link #USB_FUNCTION_ADB} boolean extra indicating whether the adb function is enabled *
  • {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the RNDIS ethernet function is enabled *
  • {@link #USB_FUNCTION_MTP} boolean extra indicating whether the MTP function is enabled *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the PTP function is enabled *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the accessory function is enabled *
  • {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the audio source function is enabled *
  • {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the MIDI function is enabled *
*/ public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; /** * Boolean extra indicating whether USB is connected or disconnected. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. */ public static final String USB_CONNECTED = "connected"; /** * Boolean extra indicating whether USB is configured. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. */ public static final String USB_CONFIGURED = "configured"; /** * Boolean extra indicating whether confidential user data, such as photos, should be * made available on the USB connection. This variable will only be set when the user * has explicitly asked for this data to be unlocked. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. */ public static final String USB_DATA_UNLOCKED = "unlocked"; /** * A placeholder indicating that no USB function is being specified. * Used to distinguish between selecting no function vs. the default function in {@link #setCurrentFunction(String)}. */ public static final String USB_FUNCTION_NONE = "none"; /** * Name of the adb USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_ADB = "adb"; /** * Name of the RNDIS ethernet USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_RNDIS = "rndis"; /** * Name of the MTP USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_MTP = "mtp"; /** * Name of the PTP USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_PTP = "ptp"; /** * Name of the audio source USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source"; /** * Name of the MIDI USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast */ public static final String USB_FUNCTION_MIDI = "midi"; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

Android 通过广播监听USB连接状态的改变

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

2、UsbActivity.java

package com.example.testapp; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; public class UsbActivity extends Activity { private TextView textView; private UsbManager usbManager; private BroadcastReceiver receiver; private IntentFilter intentFilter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ScrollView scrollView = new ScrollView(this); LinearLayout linearLayout = new LinearLayout(this); linearLayout.setOrientation(LinearLayout.VERTICAL); textView = new TextView(this); scrollView.addView(linearLayout); linearLayout.addView(textView); setContentView(scrollView); usbManager = (UsbManager) getSystemService(Context.USB_SERVICE); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); addText("action : " + action); if(intent.hasExtra(UsbManager.EXTRA_PERMISSION_GRANTED)) { boolean permissionGranted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false); addText("permissionGranted : " + permissionGranted); } switch(action) { case UsbManager.ACTION_USB_ACCESSORY_ATTACHED: case UsbManager.ACTION_USB_ACCESSORY_DETACHED: //Name of extra for ACTION_USB_ACCESSORY_ATTACHED and ACTION_USB_ACCESSORY_DETACHED broadcasts containing the UsbAccessory object for the accessory. UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); addText(accessory.toString()); break; case UsbManager.ACTION_USB_DEVICE_ATTACHED: case UsbManager.ACTION_USB_DEVICE_DETACHED: //Name of extra for ACTION_USB_DEVICE_ATTACHED and ACTION_USB_DEVICE_DETACHED broadcasts containing the UsbDevice object for the device. UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); addText(device.toString()); break; case MyUsbManager.ACTION_USB_STATE: /* *

  • {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected. *
  • {@link #USB_CONFIGURED} boolean indicating whether USB is configured. * currently zero if not configured, one for configured. *
  • {@link #USB_FUNCTION_ADB} boolean extra indicating whether the * adb function is enabled *
  • {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the * RNDIS ethernet function is enabled *
  • {@link #USB_FUNCTION_MTP} boolean extra indicating whether the * MTP function is enabled *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the * PTP function is enabled *
  • {@link #USB_FUNCTION_PTP} boolean extra indicating whether the * accessory function is enabled *
  • {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the * audio source function is enabled *
  • {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the * MIDI function is enabled * */ boolean connected = intent.getBooleanExtra(MyUsbManager.USB_CONNECTED, false); addText("connected : " + connected); boolean configured = intent.getBooleanExtra(MyUsbManager.USB_CONFIGURED, false); addText("configured : " + configured); boolean function_adb = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_ADB, false); addText("function_adb : " + function_adb); boolean function_rndis = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_RNDIS, false); addText("function_rndis : " + function_rndis); boolean function_mtp = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_MTP, false); addText("function_mtp : " + function_mtp); boolean function_ptp = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_PTP, false); addText("usb_function_ptp : " + function_ptp); boolean function_audio_source = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_AUDIO_SOURCE, false); addText("function_audio_source : " + function_audio_source); boolean function_midi = intent.getBooleanExtra(MyUsbManager.USB_FUNCTION_MIDI, false); addText("function_midi : " + function_midi); break; } } }; intentFilter = new IntentFilter(); intentFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); intentFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED); intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); intentFilter.addAction(MyUsbManager.ACTION_USB_STATE); registerReceiver(receiver, intentFilter); boolean hasUsbHost = getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST); boolean hasUsbAccessory = getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); addText("hasUsbHost : " + hasUsbHost); addText("hasUsbAccessory : " + hasUsbAccessory); } @Override protected void onDestroy() { unregisterReceiver(receiver); super.onDestroy(); } private void addText(String str) { textView.setText(textView.getText().toString() + str + "\n"); } }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    三、运行截图

    四、ACTION_USB_DEVICE_ATTACHED 和 ACTION_USB_DEVICE_DETACHED的缺点

    广播是去监测U盘插入和拔出的,也就意味着,你只要一插入或者一拔出U盘,就是收到这两个广播。它不会管你的设备有没有准备好,有没有mounted或者unmounted。

    因此就需要引入一个新的广播 android.os.storage.extra.VOLUME_STATE。

    这个广播就是用来监听Volume状态的。当外置Usb设备在Mounted或者UnMounted的时候则就可以用来做监听 int 类型的 VolumeInfo.EXTRA_VOLUME_STATE。

    注意:android.os.storage.extra.VOLUME_STATE 一定要声明读写权限,否则是收不到的。

    1

    2

    Android API

    版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

  • 上一篇:分享我的第一个Web作品——纯静态网站
    下一篇:C++奥赛一本通递推题解
    相关文章