如何接收USB连接状态广播?

时间:2016-10-09 10:19:20

标签: android android-intent android-broadcast android-broadcastreceiver

我正在尝试在我的应用中检测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: 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();
                }
            }
        }
}

我也检查了这个答案:Can't receive broadcast Intent of UsbManager.ACTION_USB_DEVICE_ATTACHED/UsbManager.ACTION_USB_DEVICE_DETACHED,但它没有帮助..

有人可以指出我错在哪里吗?

2 个答案:

答案 0 :(得分:4)

也许它不起作用的原因是,自从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配置更精确)

答案 1 :(得分:2)

这里是在android活动中检查外部USB连接是否发生的完美步骤。只需按照步骤逐一进行。

在Android清单文件中

<uses-feature android:name="android.hardware.usb.host" />
<uses-permission android:name="android.permission.USB_PERMISSION" />

在USB检查活动代码中

 <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类:

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);
    }
}}

在您的课程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设备连接状态,没有任何错误。我希望你能为你的场景获得输出。

<强>享受!!