RenniePet
RenniePet

Reputation: 11658

How to monitor all input from a Bluetooth HID gadget

I'm trying to implement an app that (mis-) uses a Bluetooth camera shutter release gadget for a completely different purpose. Here's the gadget in question:

http://www.amazon.co.uk/iPazzPort-Bluetooth-Shutter-Android-Smartphones/dp/B00MRTFB4M

As far as I can determine this uses Bluetooth v3 and is an HID device. It apparently fires the camera app shutter by simulating "volume up" (or maybe "volume down"?). Anyway, it does seem to work quite well, although sometimes you have to press the button twice - I think that maybe the first press reestablishes Bluetooth connection and the second, and subsequent, presses then just work.

I've tested it with two different devices running Android 2.3. I do want to be backwards-compatible to that version of Android.

What I want to do is to monitor all input from this device somehow, so my app can detect when the button has been pressed and then do what it wants to use the device for. (It's a kind of panic alarm system so you can press the button to indicate you need help.)

I don't want to get involved in trying to communicate with the device via Bluetooth. Android is already doing that, and it's working, and what I've read about Bluetooth and the HID protocol makes me want to avoid it if at all possible.)

I've tried overriding onKeyDown() and onKeyUp() and dispatchKeyEvent(). Sometimes they get called, sometimes they don't. And when they get called I'm seeing unexpected keyCodes like 66 (Enter) and 8 ("1").

What I'm asking is, is there some way to monitor all input from this Bluetooth HID device, without having to get involved in Bluetooth HID protocol support?

Upvotes: 2

Views: 2801

Answers (1)

RenniePet
RenniePet

Reputation: 11658

I never found a real answer to my question as such, but fortunately I found a work-around.

This particular Bluetooth gadget always connects to the paired device, sends some text, and then disconnects. So what I'm doing is creating a BroadcastReceiver to get Bluetooth connection (and disconnect) events, and using that to activate the alarm.

   // Class used to receive Bluetooth connection and disconnect events. This checks the action is as
   // expected (probably unnecessary) and that a request type has been selected, and sends the
   // activation message to OutBack Server if so. (Monitoring the disconnect events is probably
   // unnecessary, but is done just in case that saves a situation where a connection has been
   // missed, or something.)
   public class BluetoothReceiver extends BroadcastReceiver {

      @Override
      public void onReceive(Context androidContext, Intent androidIntent) {

         String actionOrNull = androidIntent.getAction();
         if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(actionOrNull) ||
             BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(actionOrNull)) {
            Log.d(TAG, "BluetoothReceiver.onReceive() " + actionOrNull);
            if (_btnActivate.isEnabled()) {
               sendRequestActivationToServer();
            }
         }
      }
   }

...

   // Reference to the object used to monitor Bluetooth connections and disconnections
   private BluetoothReceiver _bluetoothReceiver = null;

...

   // Last lifecycle method called before fragment becomes active. This is apparently the
   // recommended place to register a receiver object, and is used to register a receiver object to
   // monitor Bluetooth connections and disconnections.
   @Override
   public void onResume() {
      super.onResume();

      _bluetoothReceiver = new BluetoothReceiver();

      IntentFilter intentFilter = new IntentFilter();
      intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
      intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);

      getActivity().registerReceiver(_bluetoothReceiver, intentFilter);
   }

...

   // First lifecycle method called when a fragment is on its way to being paused or destroyed. This
   // is apparently the recommended place to unregister a receiver object, and is used to unregister
   // the receiver object that monitors Bluetooth connections and disconnections.
   @Override
   public void onPause() {
      super.onPause();

      if (_bluetoothReceiver != null) {
         getActivity().unregisterReceiver(_bluetoothReceiver);
         _bluetoothReceiver = null;
      }
   }

This was inspired by this question and answer: How to receive intents for Bluetooth devices working?

Upvotes: 2

Related Questions