Important implementation hints
(Perhaps some of those hints aren't necessary anymore due to Android OS updates.)
- Some devices like Nexus 4 with Android 4.3 take 45+ seconds to connect using an existing gatt instance. Work around: Always close gatt instances on disconnect and create a fresh instance of gatt on each connect.
- Don't forget to call
android.bluetooth.BluetoothGatt#close()
- Start a new thread inside
onLeScan(..)
and then connect. Reason: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)
always fails, if called inside LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
in the same thread on Samsung Galaxy S3 with Android 4.3 (at least for build JSS15J.I9300XXUGMK6)
- Most devices filter advertising
- Better not use
android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback)
with the parameter to filter for certain service UUIDs because this is broken completely in Samsung Galaxy S3 with Android 4.3 and doesn't work for 128bit UUIDs in general.
- Gatt always can process one command at a time. If several commands get called short after another, the first one gets cancelled due to the synchronous nature of the gatt implementation.
- I often see even on modern devices with Android 5, that Wifi interferes withs bluetooth and vice versa. As a last resort, turn off wifi to stabilize bluetooth.
Tutorial for beginners
A pretty OK entry point for newcomers could be this video tutorial: Developing Bluetooth Smart Applications for Android http://youtu.be/x1y4tEHDwk0
The issue and work around described below is probably fixed now by OS updates
Work around: I could "stabilize" my app doing that...
- I provide the user a setting "Restart Bluetooth". If that setting is enabled, I restart Bluetooth at some points that indicate the begin of BLE stack becoming unstable. E.g. if startScan returns false. A good point may also be if serviceDiscovery failes. I just turn Bluetooth off and on.
- I provide another setting "Turn off WiFi". If that setting is enabled, my app turns off Wifi when the app is running (and turns it back on afterwards)
This work around is based on follwoing experiences...
- Restarting Bluetooth helps to fix problems with BLE in most cases
- If you turn off Wifi, the BLE stack gets much more stable. However, it also works fine on most devices with wifi turned on.
- If you turn off Wifi, restarting Bluetooth fully recovers the BLE stack without the need to reboot the device in most cases.
First of all your code it's not a service it's a Server that uses uses RFCOMM sockets.
It's very similar to the use of python socket programming (you can read more here)
I'll use a simple example from the PyBluez documentation:
Server part:
from bluetooth import *
server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)
port = server_sock.getsockname()[1]
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
advertise_service( server_sock, "SampleServer",
service_id = uuid,
service_classes = [ uuid, SERIAL_PORT_CLASS ],
profiles = [ SERIAL_PORT_PROFILE ])
print("Waiting for connection on RFCOMM channel %d" % port)
client_sock, client_info = server_sock.accept()
print("Accepted connection from ", client_info)
#this part will try to get something form the client
# you are missing this part - please see it's an endlees loop!!
try:
while True:
data = client_sock.recv(1024)
if len(data) == 0: break
print("received [%s]" % data)
# raise an exception if there was any error
except IOError:
pass
print("disconnected")
client_sock.close()
server_sock.close()
Client Part (copy paste for the docs):
from bluetooth import *
import sys
if sys.version < '3':
input = raw_input
addr = None
if len(sys.argv) < 2:
print("no device specified. Searching all nearby bluetooth devices for")
print("the SampleServer service")
else:
addr = sys.argv[1]
print("Searching for SampleServer on %s" % addr)
# search for the SampleServer service
uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
service_matches = find_service( uuid = uuid, address = addr )
if len(service_matches) == 0:
print("couldn't find the SampleServer service =(")
sys.exit(0)
first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]
print("connecting to \"%s\" on %s" % (name, host))
# Create the client socket
sock=BluetoothSocket( RFCOMM )
sock.connect((host, port))
print("connected. type stuff")
while True:
data = input()
if len(data) == 0: break
sock.send(data)
sock.close()
Your Problem:
I can't see any client code, you need to create a client and to connect the server.
You need to change it just like above, run the Server and then the Client.
Then you will see at the server the client connection.
Another useful link is here it really helped me.
Edit:
Since my current desktop doesn't have BT it's a bit tricky.
There's a great example for BlueZ server-client here at the bottom.
It is using MAC address:
Server Code: change the hostMACAddress
param - it's your adapter mac address
Client Code: change serverMACAddress
to what you wrote at 'hostMACAddress'
Best Answer
As far as I know, there is nothing in the API to directly do "remote service discovery", but I found this, which I think is about that: