How to receive USB connection status broadcast?
Solution 1
Maybe the reason it doesn't work is that since Android 6.0, the default USB mode is Charging and, maybe ACTION_USB_DEVICE_ATTACHED
doesn't get fired up when connected in that mode..
Instead, now I have another solution:
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
}
}
}
That is, the broadcast android.hardware.usb.action.USB_STATE
is sent whenever there is a toggle in the USB state.
Unlike android.hardware.usb.action.USB_DEVICE_ATTACHED
which is broadcasted only when something like a MTP mode is enable, android.hardware.usb.action.USB_STATE
is broadcasted whenever it detects an USB connection that's capable of connecting to a host (say computer), irrespective of its current USB Mode like Charging, MTP or whatever.. (it's called USB config to be more precise)
Solution 2
Here the perfect steps to check that external usb connection occur or not in android activity. Just Follow the steps one by one.
In Android Manifest file:
<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />
Inside your USB checking Activity Tag:
<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>
Inside your connectivity checking 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);
}
}}
Inside your class xml file :
<?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>
Now create a new resource directory called xml and create new xml file called device_filter.xml with the following code.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device />
</resources>
Debug and run the application, it will show external usb device connectivity status without any error. I hope you will get output for your scenario.
Enjoy!!
Gokul NC
A Computer Science Student aspiring to learn everything..
Updated on June 23, 2022Comments
-
Gokul NC almost 2 years
I am trying to detect USB connection in my app, that is, whether or not USB is connected to device.
It's being tested on Marshmallow 6.0.1 (sdk23)
But I'm unable to receive the broadcast actions ACTION_USB_DEVICE_ATTACHED or ACTION_USB_DEVICE_DETACHED..
I tried using both the dynamic way and the AndroidManifest.xml way, neither worked..
Here's my code:
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: https://stackoverflow.com/questions/18015656/cant-receive-broadcast-intent-of-usbmanager-action-usb-device-attached-usbmanag 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(); } } } }
I also checked this answer: Can't receive broadcast Intent of UsbManager.ACTION_USB_DEVICE_ATTACHED/UsbManager.ACTION_USB_DEVICE_DETACHED, but it didn't help..
Can someone please point out where I'm wrong??
-
Onik over 7 yearsYou use both dynamically and manifest defined receivers. Leave the dynamic one and let me know the result.
-
Gokul NC over 7 yearsI commented out the
setBroadcastReceivers();
call (as in code snippet above), still doesn't work.. -
Onik over 7 yearsYou just did the opposite of what I said!)) Use
setBroadcastReceivers()
and comment out the receiver in the manifest file. Perhaps, I confused you, I meant "Leave untouched". -
Gokul NC over 7 yearsThanks for the response @Onik, I tried that, didn't help :(
-
-
Nikhil Kumar almost 7 yearsHey, a working answer to detect when a USB is connected. Any idea how to get device details? Using
UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
in the receiver returns null -
Octopus over 5 yearsWell, this code is alright. What it does though is it detects a global broadcast that a device is inserted and launches the app. The app itself though, still does not respond to broadcast actions ACTION_USB_DEVICE_ATTACHED or ACTION_USB_DEVICE_DETACHED as was asked in the OP, so it doesn't actually answer the question asked.
-
user149408 about 5 yearsActually,
USB_STATE
reports the state of connections where the Android device connects to a host (phone to PC), not of USB peripherals to the device via USB OTG. -
Chetan Joshi over 3 yearshow to connect another android device through above code.