First off, I AM able to programmatically connect to a device via bluetooth if I have manually paired it beforehand. However, I haven't found a (user-friendly) way to connect with unpaired devices (that are discoverable, obviously), even using the unchanged sample Android Bluetooth code.
I would like to pop up the pairing dialog box that requests the user to input a passkey for the device. What happens with my code, and the sample Android Bluetooth code, is that making a socket with a discoverable bluetooth device
device.createRfcommSocketToServiceRecord(MY_UUID);
will add a notification to the notification bar at the top of the screen; however, it is pretty unlikely that the user will even notice a new notification (I know I didn't).
How would I pop up that pairing dialog box, prompting the user to enter the passkey - or better yet, supply a passkey for a particularly device automatically?
You can use BlueCove library to do that. However, it may be a bit heavier than you'd want as it requires a native component but in return gives you real access to Bluetooth on your phone.
Tim: I can see how a rogue app could abuse this mechanism but there are devices out there which don't support traditional PIN-based authentication method at all (for example the WiiMote).
I've seen a few threads on this but haven't really found a good
answer.
I am connecting my nexus 1 to a bluetooth spp server device to read
and write data.
After some experimentation I have found the following
If I offload the establishment of the connection from the UI thread
(which I would consider a good idea) the pairing dialog (enter pin) is
not displayed - rather a notification item appears which the user must
click to pair the devices.
If I establish the connection from within the UI thread then the
paring dialog will come to the foreground but obviously there is a
small ugly UI pause while waiting for this.
In either case the request to establish the connection is timing out
before the user (me) can enter the pin with an IOException Service
discovery failed.
My ideal would be that the pairing dialog comes to the front (without
have to block my UI thread) and that the connection attempt would not
time out while waiting on pairing entry.
Has anyone else come up with a way to make this work?
Related
I'm new in Android BLE so my question may be uncorrect or naive in some way. If this is the case please explain me where I'm wrong and kindly show me the correct way to manage this scenario.
Scenario is the following: my Android app communicates with a BLE device sending commands and getting answers from device using BLE characteristics.
Sequence is:
Device wakes up the app (the onConnectionStateChange method is called)
My app writes a command in a characteristic (I call writeCharacteristic putting the command in value parameter).
Device sends back the answer to command to my app (the onCharacteristicChanged method is triggered and value parameter contains the answer)
After waking up the app, the device doesn't do anything until a command is sent via writeCharacteristic. The device accepts different commands.
All good so far, but recently I developed a second different app to communicate with same device.
When I run both apps on same Android phone, one app sends a command to the device and the response is received by both apps! Of course the app that didn't sent the command receives an unexpected answer and goes to an unexpected status.
Ok, knowing the problem I can modify both my apps to handle this situation, but the question is: Is this behavior normal when two apps in same device communicate with same BLE device?
Is there a way for an app to establish a communication channel with a BLE device to avoid sending answer to specific commands to any other app except the one that sent the request?
My guess is that writeCharacteristic and onNotificationChanged aren't the right functions for such kind of communication, but in this case which are the alternatives?
The Bluetooth standard itself doesn't define anything how multiple apps would behave if both have a GATT connection to the same device. In the standard there is just one "GATT client".
Now both iOS and Android have taken one step further in a way that might seem unintuitive. Instead of only allowing one app at a time to communicate, multiple apps can be connected over the same GATT client to a device. The OS "multiplexes" the communication from/to the apps. The behaviour is that responses to read and write requests can only be seen by the app that made the request. So if you do readCharacteristic only that app will get the onCharacteristicRead callback. Notifications however will be delivered to both apps to the onCharacteristicChanged callback, since it wouldn't make any sense to send the notification to only one.
When you say that the "response" to a write request is the notification, that's not correct in terms of GATT terminology. The response to a write request is always empty per specification (or an error). If your peripheral emits a notification, then in your case that might be the "answer" according to your own logic, but it's not a response or any way related to your write request per the GATT specification. That's why Android can't (and shouldn't) send the notification to only one device.
I suggest that you simply ignore notifications you are not expecting. If you want to associate an "answer" to a write request, you can change your protocol to include a transaction id in both packets so they can be matched.
When I write "app" above, I really mean BluetoothGatt objects. You can call connectGatt twice with the same remote device in the same app, which will behave the same as if you connected from two different apps.
I'm building a simple motivational quote app that generates a random quote from a MySQL database. The app works fine on mobile and I want to sync the quote message to a Wear device. I'm using MessageApi to do so and used this tutorial to set it up: http://android-wear-docs.readthedocs.org/en/latest/sync.html.
However, the message functionality only works when the app is running on the host device. I need to launch the app on Wear alone and still be able to receive the message from the mobile device. I thought of running the same application on the Wear device where it will run an httpconnection on it's own but from what I understand this is not possible with Android Wear.
So my question is, is there a way to open an app on a Wear device that will trigger the mobile app to open in the background and hence receive the message that way?
Your mobile app can implement WearableListenerService. In that service implementation, you can listen to messages that are sent to your phone from your companion app on a wear device (when such message is sent to your phone, the framework on your phone starts up your service and passes the message to it). You can then implement the logic you need in that service (fetch a quote, etc) and respond back to your wear's message; when its work is done, that service will go away on its own. For this to work, your wear app needs to send such message to your phone app upon start up (or whenever you see appropriate in your app). This approach should work and probably is the most appropriate approach for your use case.
I am new to blackberry-7. In my application when I plug my phone into the cable (by means of the USB cable) I want to find if my blackberry connected with USB is in charging mode or transfer mode. How is it possible?
The USB can be detected asynchronously using SystemListener2 and also synchronously using DeviceInfo.getBatteryStatus.
For what you need the battery status won't work because it probably charges in both normal and transfer modes, and then there's the problem of detecting the cable when the battery is full. So I'd try registering a SystemListener2 instance and hopefully the callback usbConnectionStateChange will be passed the flag SystemListener2.USB_STATE_CABLE_CONNECTED as argument. When it is transferring, I'd expect the flags USB_STATE_ENUMERATED and USB_STATE_MS_INTERFACE_ENUMERATED to be received in the callback as well, but I've never tested it on a real device.
And I don't know what would happen if the device is already connected when the listener is registered.
To register the listener, call
Application.getApplication().addSystemListener(mySysListener2);
I am writing an app which monitors the volume setting of the notification stream (using a broadcast receiver for android.media.VOLUME_CHANGED_ACTION - kind of a hack I know) and when it is set to silent I would like to stop my Bluetooth headset from ringing but without disconnecting it, so that if I choose to answer the call (it vibrates or I see it ringing) I can do so from my Bluetooth headset.
So far I've tried muting the voice stream, the Bluetooth stream (by providing the int 6), setting setBluetoothScoOn(false), using stopBluetoothSco() and muting the previously mentioned streams but nothing seems to work. I've got the modify audio permission so I'm beginning to think it isn't possible.
Does anyone have an idea?
When connected on bluetooth headset, call notifications are send using HFP protocol , this protocol only internally sends certain AT commands(phone to headset) which lets headset know about the call , settings SCO ON/OFF will turn call audio to headset/phone, ringing is internal to bluetooth headset
I am developing an application which uses Bluetooth to connect to a device and send/receive data. I am doing all of my testing with a Nexus One phone.
I have never been able to establish a SPP (serial port) connection from my phone to any device. However, I have been able to connect from a device (my laptop) to my phone using a Mac equivalent of PuTTY (The only exception to this is the "Bluetooth File Transfer" app from the Marketplace seems to work, but I don't think that uses RFCOM/SPP...).
I keep seeing this message in my LogCat logs:
ERROR/BluetoothService.cpp(78): stopDiscoveryNative: D-Bus error in StopDiscovery: org.bluez.Error.Failed (Invalid discovery session)
as well as these:
java.io.IOException: Operation Canceled
java.io.IOException: Software caused connection abort
I have tried using the UUID of "00001101-0000-1000-8000-00805F9B34FB" and I have also tried using the:
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
sock = (BluetoothSocket) m.invoke(device, Integer.valueOf(1));
method instead of device.createRfcommSocketToServiceRecord(UUID); as well--with no luck.
I am using the BluetoothChat example and variations of that code to do all of my testing...
Solutions or suggestions would be great...or even a better/less complex example of some testing code I can run on the phone, or a python script or something I can run on my computer to help debug?
Thanks! I hope this isn't a bug with the Android OS, but if it is I hope to find a workaround.
EDIT: I should also note that most devices show up as "paired, but not connected" in the Bluetooth settings.
EDIT 2: The solution seems to be simply disabling any Bluetooth listening. See my answer post for more information.
The solution, as it turns out, was to disable the server functionality of the Bluetooth service. By only using createRfcommSocketToServiceRecord and never calling listenUsingRfcommWithServiceRecord (in the BluetoothChat example this means never starting the "AcceptThread") the problem was fixed.
Even though these two calls are supposed to be totally separated and have no affect on each other (according to the Android docs), simply commenting out listenUsingRfcommWithServiceRecord fixed my supposedly unrelated issue.
I can take the Bluetooth Chat program unedited and it will not be able to establish an outgoing connection to ANY bluetooth device I have tested (laptops, desktops, headsets, etc.), but if I remove that one thing it works flawlessly as a client.
Anyway, I hope this will help someone else if they come across the same issue. This must be a bug with the Android OS, or possibly the firmware on the Nexus One.
I would ignore the stopDiscovery error - its good that you're cancelling discovery before making your connection. Per the SDK docs:
Because discovery is a heavyweight
precedure for the Bluetooth adapter,
this method should always be called
before attempting to connect to a
remote device with connect().
Discovery is not managed by the
Activity, but is run as a system
service, so an application should
always call cancel discovery even if
it did not directly request a
discovery, just to be sure.
So with that said, were you able to get the Bluetooth Chat example to work before you made any modifications to the code?
The UUID you want for SPP/RFCOMM is:
static UUID UUID_RFCOMM_GENERIC = new UUID(0x0000110100001000L,0x800000805F9B34FBL);
or defined another way (both accomplish the same thing).
static final UUID UUID_RFCOMM_GENERIC = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");