Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to receive USB connection status broadcast?

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??

like image 894
Gokul NC Avatar asked Oct 09 '16 10:10

Gokul NC


People also ask

How do I get USB permissions on Android?

To do this, your application has to: Discover connected USB devices by using an intent filter to be notified when the user connects a USB device or by enumerating USB devices that are already connected. Ask the user for permission to connect to the USB device, if not already obtained.

What is USB host support?

In USB host mode, the Android-powered device acts as the host. Examples of devices include digital cameras, keyboards, mice, and game controllers. USB devices that are designed for a wide range of applications and environments can still interact with Android applications that can correctly communicate with the device.

What is Android accessory mode?

USB accessory mode allows users to connect USB host hardware specifically designed for Android-powered devices. The accessories must adhere to the Android accessory protocol outlined in the Android Accessory Development Kit documentation.


1 Answers

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)

like image 103
Gokul NC Avatar answered Oct 09 '22 13:10

Gokul NC