I have a Garmin watch (Forerunner 25) which I use to connect with Garmin connect (Android app). For many reasons I would like to build my own custom app to track training. But I have not been able to do the following:
Connect android app with a bluetooth (Garmin) Watch for file transfer.
Retrieve a .fit file from the Watch via Bluetooth.
How would I be able to do this?
I have tried to connect the watch via a BluetoothSocket but have had no luck to connect it.
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //Standard SerialPortService ID
mSocket = mDevice.createRfcommSocketToServiceRecord(uuid);
mSocket.connect();
//Never reaches this part, the connection is unsuccessful
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
Not sure If any of this is correct but this is what I started with.
//Note: The device is not null before I try to connect.
// I can retrieve the name, the address ...
D/BluetoothUtils: isSocketAllowedBySecurityPolicy start : device null
W/BluetoothAdapter: getBluetoothService() called with no BluetoothManagerCallback
I know the .fit file is a bytefile so if anyone know how to convert it to a .csv file with all the information as: time, speed, length, elevation...
I have found the Fitparser for python but not anything for Android.
Is there any library for this?
Or how could I parse a .fit (bytefile) to .csv on my own?
Related
I have a working Bluetooth server running (Android app). I would like to set a specific Bluetooth port for it to listen to. The reason for that is that for the client to connect, it takes about 10-15 seconds because it needs to first discover the server (i do a scan ).
the code to create the server is the following:
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
UUID my_uuid = UUID.fromString("12345678-f6ff-4f6f-1f1f-f8f8f8fffff8");
try {
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myBluetoothServer", my_uuid);
sock1 = serverSocket.accept();
i_s = sock1.getInputStream();
o_s = new OutputStreamWriter(socket.getOutputStream());
new Thread(writter).start();
...
Question: how to specify a fixed port number for the server?
I have been looking here, of course, but it is not easy to find,:
https://developer.android.com/reference/android/bluetooth/BluetoothSocket?hl=ur
I am looking for something like serverSocket.setPort(myPortNumber) (pseudo - code)
The concept of port does not exist for Bluetooth Sockets since they are not regular TCP/IP sockets. They are just abstracted to behave like one.
As you figured out from your code, what you specify is a UUID which is a service identifier. The process to connect to a Bluetooth server goes like this:
Bluetooth Device scan: You can't skip this part, since you need a valid BluetoothDevice object
Service Discovery for a discovered Device: This is the part where you "check" if that Bluetooth Device is running the service that you are looking for (Your service UUID) So you shouldn't skip this part either, unless you want to connect to all surrounding Bluetooth devices.
My understanding is that the SDP is a list of UUIDs that other devices can fetch.
According to this PDF from MIT, "A more general way to think of
SDP is as an information database." Does this mean I can add multiple values to SDP? Since Android has BluetoothDevice.fetchUuidsWithSdp(), how do I set the UUIDs of a device?
Also, what does each section of an UUID mean? UUIDs look like 00000000-0000-1000-8000-00805F9B34FB, but what information does this convey?
An UUID identifies a service that is available on a particular device. So if you call BluetoothDevice.fetchUUidsWithSdp() your BroadcastReceiver will receive the relevant Intent ACTION_UUID containing the device and the service UUID.
The bluetooth specification defines some common UUIDs.
If you don't want to connect to one of these well known services but intent to implement your own bluetooth application, then you have to just generate your own UUID (use uuidgen from a unix console or an online generator) that identifies your application/service.
You can create an UUID instance in java like this UUID uuid = UUID.fromString("785da8ea-1220-11e5-9493-1697f925ec7b");.
So if you create the server side for your bluetooth application on Android you typically do this
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("YourHumanReadableServiceName", uuid);
And this is where you "set" your UUID. The Android bluetooth API creates the SDP-entry consisting of YOUR application's UUID and name for you. Other devices can now retrieve this entry. Androids bluetooth stack will now associate a bluetooth channel to your BluetoothServerSocket. If you want to connect to this ServerSocket, the connecting side usually connects doing this:
// you will most likely already have this instance from a discovery or paired device list
BluetoothDevice serverDevice = adapter.getRemoteDevice(bluetoothMacAddress);
// connect to your ServerSocket using the uuid
BluetoothSocket socket = serverDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
Android will again do the heavy lifting for you: It checks the SDP-Records on the remote device, looks up the bluetooth channel that corresponds to your service's UUID and connects using this information.
There is a common code snippet spooking around here on SO that advices you to use "reflection" to get to a hidden API looking similar to this code:
try {
// this is the way to go
socket = device.createRfcommSocketToServiceRecord(uuid);
socket.connect( );
} catch ( IOException exception ) {
// don't do that! You will bypass SDP and things will go sideways.
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
}
Most people try this and it "just works" in their dev environment but you should know what you do using this. You actively bypass the SDP lookup that retrieves the right bluetooth channel to be used with your service and you will end up connecting to channel 1. If you have more than one Service running on the device, things WILL go sideways in this cases and you will end up in debugging hell ;-)
I developed a small middleware called Blaubot to create small networks using bluetooth/wifi/nfc and experienced all sorts of problems on the devices I used to test with (12 models). It was often the case that the bluetooth stack was not fully functional anymore in cases where it got some load or after many connects/disconnects (which you usually will have, if you are developing your app). In these cases the device.createRfcommSocketToServiceRecord(uuid) would occasionally fail and only turning the bluetooth adapter off and on again helped to bring the bluetooth adapters back to life (in some cases only after a full power cycle). If this happens and you use the reflection method, you will probably not have much fun with bluetooth.
But if you know this and keep concurrent calls to the BluetoothAdapter within bounds, bluetooth connections and the adapters will be pretty stable.
I try to develop a simple android app with a ble device.
I found many source code from the Intenet. However, both of them were start from scanning a list of available ble device.
As I have MAC address of the device,UUID of service and characteristic.
How can I connect to the known device and read one specific characteristic directly??
To connect a specific Bluetooth Device which has details like MAC address of the device, UUID of service and characteristic etc. you already know. To do this you need a BluetoothDevice object to make a call like this:
yourBluetoothDevice.connectGatt(getApplicationContext(), false, bleGattCallback);
So for this (yourBluetoothDevice) you have to start the scan at first to get same device object to connect by comparing it's MAC address. However, you got that same device object in onLeScan callback just stop scanning and make a connection with the same device.
Note: Making a connection should be on UIThread(Either using Handler, runOnUIThread or mainlooperThread) otherwise it will give issue in some devices for 'Fail to register callback'
Here yourBluetoothDevice is the device object reference with you want to make a connection.
bleGattCallback is the registered new BluetoothGattCallback() callback for connection status, discovered services, characteristics read and write etc.
Take a look at createInsecureRfcommSocketToServiceRecord. Something like this:
UUID uuid = UUID.fromString("<Your UUID>");
BluetoothSocket socket = yourBLEDevice.createInsecureRfcommSocketToServiceRecord(uuid);
Method m = yourBLEDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
socket = (BluetoothSocket) m.invoke(yourBLEDevice, 1);
If you already know the mac address, you can try something like below:
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(mMacAddress);
final BluetoothGatt mGatt = device.connectGatt(getApplication(), false, gattCallback);
I have a requirement to make Pandaboard as Bluetooth Headset. Is it possible to achieve this?
I followed below URL to flash the source code into sdcard. Before flashing I modified system/etc/bluetooth/audio.conf file. In the audio.config file I enabled HFP=true.
URL: https://releases.linaro.org/13.04/android/panda/
After doing this I tried to connect to bluetooth device via following Android-java
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
m_oBluetoothSocket = btDevice.createRfcommSocketToServiceRecord(MY_UUID);
m_oBluetoothSocket.connect();
I also tried connecting without UUID like below
Method m = btDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
m_oBluetoothSocket = (BluetoothSocket) m.invoke(btDevice, Integer.valueOf(1));
m_oBluetoothSocket.connect();
I was unable to connect to device I see invalid argument exception.
If I try to run the code on Android mobile I am able to connect and send AT command.
But in mobile I am not able to make it as handsfree, I have done a related post for it
https://stackoverflow.com/questions/19246344/is-it-possible-to-make-my-old-phone-as-handsfree-and-establish-connection-betwee
Comming Back to Pandaboard is my approach correct? How to make Pandaboard Bluetooth has Headset??
Please share thoughts on this....
I use this code
luugiathuy.com/2011/02/android-java-bluetooth/
The server side is the PC
the client is the device, with the app based on bluetooth chat example
The device (galaxy tab 7.0) can establish connection with the PC.
However the PC server (written in java and bluecove) did nothing, as nothing is connected.
The loop for trying to find connected device is
while(true) {
try {
System.out.println("waiting for connection...");
connection = notifier.acceptAndOpen();
Thread processThread = new Thread(new ProcessConnectionThread(connection));
processThread.start();
} catch (Exception e) {
e.printStackTrace();
return;
}
Output on PC:
uuid: 0000110100001000800000805f9b34fb
waiting for connection...
EDIT: source downloadhttps://github.com/luugiathuy/Remote-Bluetooth-Android
Same issue I got when I was trying in linux. But the reason (still not sure) when you run the bluetooth android application without turning on the Java server using bluecove, It will try to connect with the already installed bluetooth software. You may see the bluetooth icon asking for granting access to the mobile device.
To solve this, I just changed the uuid in the server and application (say from 1103 to 1101 and vice versa) and then started the server first and then the android application. Java server part started listening.
The reason I think may be the uuid when it did not found the bluecove stack service server, it got connected to the device server listening on same uuid. So after changing the uuid and making sure that the server is running before launching the android application should solve the issue.
If you are getting connected to the bluetooth system application and not to the Java bluecove server,
1) First change the uuid both server and android application.
2) Second make sure your server is running and listening on same uuid.
3) Launch the android application which try to communicate on same rfcomm connection uuid.
Server part code I took from : http://www.jsr82.com/jsr-82-sample-spp-server-and-client/
Library : http://code.google.com/p/bluecove/downloads/list
Yes, it happens with me too, I suggest you to fire following commend on shell, when it shows waiting for connection.
hcitool cc 58:C3:8B:D7:FA:F4
here 58:C3:8B:D7:FA:F4 is my device's bluetooth address, which should be replaced by your device's bluetooth address.
To get your device's bluetooth address, just start bluetooth in your device with discoverable mode and execute hcitool scan command, it will display all the active device with their name and bluetooth address.
Well you may run the above hcitool cc 58:C3:8B:D7:FA:F4 command via Java code as follows,
try
{
Process p=Runtime.getRuntime().exec("hcitool cc 58:C3:8B:D7:FA:F4");
}
catch ( Exception e )
{
}
The output from your program says it listens on UUID 0x1101. Is that true? The sample you reference shows it listening on a different UUID. Its Service Class Id is 0x04c6093b and is set as follows:
34 UUID uuid = new UUID(80087355); // "04c6093b-0000-1000-8000-00805f9b34fb"
35 String url = "btspp://localhost:" + uuid.toString() + ";name=RemoteBluetooth";
36 notifier = (StreamConnectionNotifier)Connector.open(url);
The two need to match on client and server.