如何接收USB连接状态广播?
How to receive USB connection status broadcast?
我正在尝试在我的应用程序中检测 USB 连接,即 USB 是否已连接到设备。
它正在 Marshmallow 6.0.1 (sdk23) 上进行测试
但是我无法接收广播操作ACTION_USB_DEVICE_ATTACHED或ACTION_USB_DEVICE_DETACHED..
我尝试使用动态方式和 AndroidManifest.xml 方式,都没有用..
这是我的代码:
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gokulnc.blah_blah"
android:installLocation="auto"
android:versionCode="15"
android:versionName="1.5.1">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<android:uses-permission android:name="android.permission.USB_PERMISSION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:vmSafeMode="false">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/DrawerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<receiver android:name="mUsbReceiver">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</receiver>
</activity>
</application>
</manifest>
MainActivity.java :
public class MainActivity extends AppCompatActivity {
BroadcastReceiver mUsbReceiver;
public void onCreate(Bundle savedInstanceState) {
.....
setBroadcastReceivers();
}
void setBroadcastReceivers() {
//Reference: http://www.codepool.biz/how-to-monitor-usb-events-on-android.html
mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
updateUSBstatus();
Log.d(LOG_TAG, "USB Connected..");
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
updateUSBstatus();
}
Log.d(LOG_TAG, "USB Disconnected..");
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver , filter);
Log.d(LOG_TAG, "mUsbReceiver Registered");
}
@Override
public void onResume() {
super.onResume();
Log.d(LOG_TAG, "App Resumed..");
//Refernce:
Intent intent = getIntent();
if (intent != null) {
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
Toast.makeText(getApplicationContext(), "Attached", Toast.LENGTH_SHORT).show();
} else if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
Toast.makeText(getApplicationContext(), "Detached", Toast.LENGTH_SHORT).show();
}
}
}
}
我也检查了这个答案:Can't receive broadcast Intent of UsbManager.ACTION_USB_DEVICE_ATTACHED/UsbManager.ACTION_USB_DEVICE_DETACHED,但没有帮助..
谁能指出我哪里错了??
也许它不起作用的原因是自 Android 6.0 以来,默认的 USB 模式是充电,并且在该模式下连接时可能 ACTION_USB_DEVICE_ATTACHED
不会启动..
相反,现在我有 另一个解决方案:
String usbStateChangeAction = "android.hardware.usb.action.USB_STATE";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if(action.equalsIgnoreCase(usbStateChangeAction)) { //Check if change in USB state
if(intent.getExtras().getBoolean("connected")) {
// USB was connected
} else {
// USB was disconnected
}
}
}
也就是说,只要 USB 状态发生切换,就会发送广播 android.hardware.usb.action.USB_STATE
。
与仅在启用 MTP 模式之类的东西时才广播的 android.hardware.usb.action.USB_DEVICE_ATTACHED
不同,只要检测到能够连接到主机(例如计算机)的 USB 连接,就会广播 android.hardware.usb.action.USB_STATE
,无论其当前的 USB 模式,如充电、MTP 或其他...(更准确地说,它称为 USB 配置)
这里是检查外部 USB 连接是否发生的完美步骤 android activity。一步一步来就好了。
在 Android 清单文件中:
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
检查你的 USB 内部 Activity 标签:
<activity android:name=".USBEnabled">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
在您的连接检查 USBEnabled class :
public class USBEnabled extends AppCompatActivity {
private static final String TAG = "UsbHost";
TextView mDeviceText;
Button mConnectButton;
UsbManager mUsbManager;
UsbDevice mDevice;
PendingIntent mPermissionIntent;
private static final int REQUEST_TYPE = 0x80;
private static final int REQUEST = 0x06;
private static final int REQ_VALUE = 0x200;
private static final int REQ_INDEX = 0x00;
private static final int LENGTH = 64;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_usbenabled);
mDeviceText = (TextView) findViewById(R.id.text_status);
mConnectButton = (Button) findViewById(R.id.button_connect);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
@Override
protected void onRestart() {
super.onRestart();
recreate();
}
@Override
protected void onResume() {
super.onResume();
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
updateDeviceList();
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
}
public void onConnectClick(View v) {
if (mDevice == null) {
return;
}
mUsbManager.requestPermission(mDevice, mPermissionIntent);
}
private static final String ACTION_USB_PERMISSION = "com.android.recipes.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
&& device != null) {
getDeviceStatus(device);
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
};
private void getDeviceStatus(UsbDevice device) {
UsbDeviceConnection connection = mUsbManager.openDevice(device);
byte[] buffer = new byte[LENGTH];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, LENGTH, 2000);
connection.close();
}
private void updateDeviceList() {
HashMap<String, UsbDevice> connectedDevices = mUsbManager
.getDeviceList();
if (connectedDevices.isEmpty()) {
mDevice = null;
mDeviceText.setText("No Devices Currently Connected");
mConnectButton.setEnabled(false);
} else {
for (UsbDevice device : connectedDevices.values()) {
mDevice = device;
}
mDeviceText.setText("USB Device connected");
mConnectButton.setEnabled(true);
}
}}
在您的 class xml 文件中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button_connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onConnectClick"
android:text="Connect" />
<TextView
android:id="@+id/text_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
<TextView
android:id="@+id/text_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
</LinearLayout>
现在创建一个名为 xml 的新资源目录,并使用以下代码创建名为 device_filter.xml 的新 xml 文件。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device />
</resources>
调试和运行应用程序,它将显示外部USB设备连接状态,没有任何错误。我希望你会得到你的场景的输出。
尽情享受!!
我正在尝试在我的应用程序中检测 USB 连接,即 USB 是否已连接到设备。
它正在 Marshmallow 6.0.1 (sdk23) 上进行测试
但是我无法接收广播操作ACTION_USB_DEVICE_ATTACHED或ACTION_USB_DEVICE_DETACHED..
我尝试使用动态方式和 AndroidManifest.xml 方式,都没有用..
这是我的代码:
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.gokulnc.blah_blah"
android:installLocation="auto"
android:versionCode="15"
android:versionName="1.5.1">
<uses-feature android:name="android.hardware.usb.host" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<android:uses-permission android:name="android.permission.USB_PERMISSION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:vmSafeMode="false">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/DrawerTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<receiver android:name="mUsbReceiver">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
</intent-filter>
</receiver>
</activity>
</application>
</manifest>
MainActivity.java :
public class MainActivity extends AppCompatActivity {
BroadcastReceiver mUsbReceiver;
public void onCreate(Bundle savedInstanceState) {
.....
setBroadcastReceivers();
}
void setBroadcastReceivers() {
//Reference: http://www.codepool.biz/how-to-monitor-usb-events-on-android.html
mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
updateUSBstatus();
Log.d(LOG_TAG, "USB Connected..");
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
updateUSBstatus();
}
Log.d(LOG_TAG, "USB Disconnected..");
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
//filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
registerReceiver(mUsbReceiver , filter);
Log.d(LOG_TAG, "mUsbReceiver Registered");
}
@Override
public void onResume() {
super.onResume();
Log.d(LOG_TAG, "App Resumed..");
//Refernce:
Intent intent = getIntent();
if (intent != null) {
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
Toast.makeText(getApplicationContext(), "Attached", Toast.LENGTH_SHORT).show();
} else if(intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
Toast.makeText(getApplicationContext(), "Detached", Toast.LENGTH_SHORT).show();
}
}
}
}
我也检查了这个答案:Can't receive broadcast Intent of UsbManager.ACTION_USB_DEVICE_ATTACHED/UsbManager.ACTION_USB_DEVICE_DETACHED,但没有帮助..
谁能指出我哪里错了??
也许它不起作用的原因是自 Android 6.0 以来,默认的 USB 模式是充电,并且在该模式下连接时可能 ACTION_USB_DEVICE_ATTACHED
不会启动..
相反,现在我有 另一个解决方案:
String usbStateChangeAction = "android.hardware.usb.action.USB_STATE";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(LOG_TAG, "Received Broadcast: "+action);
if(action.equalsIgnoreCase(usbStateChangeAction)) { //Check if change in USB state
if(intent.getExtras().getBoolean("connected")) {
// USB was connected
} else {
// USB was disconnected
}
}
}
也就是说,只要 USB 状态发生切换,就会发送广播 android.hardware.usb.action.USB_STATE
。
与仅在启用 MTP 模式之类的东西时才广播的 android.hardware.usb.action.USB_DEVICE_ATTACHED
不同,只要检测到能够连接到主机(例如计算机)的 USB 连接,就会广播 android.hardware.usb.action.USB_STATE
,无论其当前的 USB 模式,如充电、MTP 或其他...(更准确地说,它称为 USB 配置)
这里是检查外部 USB 连接是否发生的完美步骤 android activity。一步一步来就好了。
在 Android 清单文件中:
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
检查你的 USB 内部 Activity 标签:
<activity android:name=".USBEnabled">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
在您的连接检查 USBEnabled class :
public class USBEnabled extends AppCompatActivity {
private static final String TAG = "UsbHost";
TextView mDeviceText;
Button mConnectButton;
UsbManager mUsbManager;
UsbDevice mDevice;
PendingIntent mPermissionIntent;
private static final int REQUEST_TYPE = 0x80;
private static final int REQUEST = 0x06;
private static final int REQ_VALUE = 0x200;
private static final int REQ_INDEX = 0x00;
private static final int LENGTH = 64;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_usbenabled);
mDeviceText = (TextView) findViewById(R.id.text_status);
mConnectButton = (Button) findViewById(R.id.button_connect);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
@Override
protected void onRestart() {
super.onRestart();
recreate();
}
@Override
protected void onResume() {
super.onResume();
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
updateDeviceList();
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
}
public void onConnectClick(View v) {
if (mDevice == null) {
return;
}
mUsbManager.requestPermission(mDevice, mPermissionIntent);
}
private static final String ACTION_USB_PERMISSION = "com.android.recipes.USB_PERMISSION";
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)
&& device != null) {
getDeviceStatus(device);
} else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
};
private void getDeviceStatus(UsbDevice device) {
UsbDeviceConnection connection = mUsbManager.openDevice(device);
byte[] buffer = new byte[LENGTH];
connection.controlTransfer(REQUEST_TYPE, REQUEST, REQ_VALUE, REQ_INDEX,
buffer, LENGTH, 2000);
connection.close();
}
private void updateDeviceList() {
HashMap<String, UsbDevice> connectedDevices = mUsbManager
.getDeviceList();
if (connectedDevices.isEmpty()) {
mDevice = null;
mDeviceText.setText("No Devices Currently Connected");
mConnectButton.setEnabled(false);
} else {
for (UsbDevice device : connectedDevices.values()) {
mDevice = device;
}
mDeviceText.setText("USB Device connected");
mConnectButton.setEnabled(true);
}
}}
在您的 class xml 文件中:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button_connect"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onConnectClick"
android:text="Connect" />
<TextView
android:id="@+id/text_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
<TextView
android:id="@+id/text_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="22dp" />
</LinearLayout>
现在创建一个名为 xml 的新资源目录,并使用以下代码创建名为 device_filter.xml 的新 xml 文件。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device />
</resources>
调试和运行应用程序,它将显示外部USB设备连接状态,没有任何错误。我希望你会得到你的场景的输出。
尽情享受!!