Hey I'm relatively new to Android programming (but not programming in general).
The Setup:
HTC Wildfire (running Android 2.1)
LM058 (RS232 Serial Cable Replacement)
LM058 will later on be attached to a MCU but for now it's connected to my laptop (terminal)
The Goal:
To connect Wildfire to LM058 to each other with a 'bidirectional-stream' (like: "Hello from Android", response: "Hey from LM058").
So far:
I've managed to connect the two devices (paired), I can tell by the LEDs on the LM058.
Problem:
I can't seem to send anything from my Wildfire to LM058, and can't write anything back. They are paired and Connected.
Code example:
String message = "Hello message from client to server.";
byte[] msgBuffer = message.getBytes();
try {
outStream.write(msgBuffer);
Log.e(TAG, "App was here!");
} catch (IOException e) {
Log.e(TAG, "ON RESUME: Exception during write.", e);
}
I have previously made a similar connection using a Windows Mobile succesfully, but Android seems to give me some trouble at this point.
If you can help me get passed this small hurdle I would be very gratefull!
Could it have anything to do with BaudRate, because when a link is established (paired and Connected) it should replace the two devices (as a simple RS232 cable), so my Terminal on the PC should be set to a certain BaudRate (since I can't seem to find Baud Rate in Android). But still I can't see anything, if Baudrate was wrong then I would be able to see something (even though it might be rubbish) or?
There isn't Baudrate for Bluetooth connection, only you have to configure the baudrate between your BT-RS232 device and your computer...
For the BluetoothConnection you could see the next example:
http://developer.android.com/resources/samples/BluetoothChat/index.html
or this:
http://developer.android.com/guide/topics/wireless/bluetooth.html
Related
I have written an app that connects to a BLE device. The app works OK on most devices; but some devices (most noticeably Huawei P8 Lite and Nexus 6P) refuse to connect after the Bluetooth adapter has been disabled.
This is the test sequence:
Make sure the app is NOT running.
Slide down from the top, disable BT for a couple of seconds, then re-enable bluetooth.
Start the app. The app automatically connects to a bluetooth address stored in the preferences.
Wait for connect. This is where nothing happens on Huawei phones, but other phones, such as Samsung, works like a charm.
Verify from another phone the device is advertising and you can
connect to it.
This is the code I use to connect:
private final Runnable mBeginConnectRunnable = new Runnable() {
#Override
public void run() {
synchronized (GattConnection.this) {
if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
try {
mBluetoothAdapter.cancelDiscovery();
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(mAddress);
mGatt = mBluetoothDevice.connectGatt(mContext, mBackgroundConnect, mGattCallback);
final boolean connectSuccess = mGatt.connect();
Log.d(TAG, String.format(Locale.ENGLISH, "mGatt.connect(%s, %s) %s",
mAddress,
mBackgroundConnect ? "background[slow]" : "foreground[fast]",
connectSuccess ? "success" : "failed"));
refreshDeviceCache(mGatt);
} catch (Exception ex) {
Log.e(TAG, "Create connection failed: " + ex.getMessage());
setState(State.Closed);
}
} else {
Log.d(TAG, "Can't create connection. Adapter is disabled");
setState(State.Closed);
}
}
}
};
All calls are posted via a Handler to the main thread. I can see it waits for a connect, gives up after 30 seconds at which I call BluetoothGatt.close() on the object and nulls it. It's like nothing is out there.
After some time, later in the day, it works again.
Help is highly appreciated :-)
Update September 14, 2018: After great explanation from Emil I've updated our app and as such don't have this problem on the Nexus. I've noticed the Huawei P8 Lite continues to scan in the background and it seems there is nothing you can do to stop it.
To demonstrate the problems I've made a very simple and clean app that exercise the Bluetooth LE functionality on a phone and used it to demonstrate this problem and also the P8 is broken. The app is available here: https://play.google.com/store/apps/details?id=eu.millibit.bluetootherror
Source is available here: https://bitbucket.org/millibit/eu.millibit.bluetootherror/src/master/
I hope I over time can extend this app to make it a test vehicle for Android documenting all the stange behavior from Android and collect it in a database. In case you are interested in contributing, don't hesitate to drop me a mail on bt.error#millibit.dk
The Android Bluetooth stack has a design flaw in its API. When you connect to a specific device by Bluetooth Device Address, there is no way to tell if you mean a Public address or Random address.
If you start to connect to a device with autoConnect=false which is not bonded and has not recently been seen in a Scan, it will assume you mean a Public address. So if you try to connect to a device having a static random address, it will fail.
To be sure you connect with the correct address type if the device is not bonded, you MUST perform a scan first, find the device and THEN start the connection attempt.
I am willing to create a server and client program on my android mobile devices.
The devices communicate with each other on the same wifi network, therefore, some simple scanning mechanism must be implemented - The client phones search for a server phone through some kind of broadcast.
What I did:
My protocol - the client phone broadcasts a message port p on the wifi, the server listens on port p. when the server gets the broadcast message it sends a message back, therefore discovering itself to the client.
My code -
I have opened a broadcast socket on my app, it sends a broadcast message.
Meanwhile there is a python script on my PC that listens and replies - I use python so that my testing will be easier - Wireshark on the PC and I can see everything.
What happens:
When I use one of my Galaxy S phones - it works and I get a response.
When I use the other Galaxy S phone - it doesn't work.
Now this is what I know:
The phone that works actually has Nexus ROM on it Ver. 4.1.1
The phone that doesn't work has 2.3.3 regular galaxy ROM
The python code says it receives both of the broadcasts sent from both phones, and replies to both of them without raising any exception.
So far I was thought the problem may be
1. the older version'd phone.
2. the windows firewall
3. the router firewall
So I have opened Wireshark, and Indeed I saw that both phones are sending their broadcasts - it was logged on Wireshark.
But the python script only responded to the first one.
So this is why 1 & 3 are irrelevant - if the router firewall was blocking my UDP I would have still seen the python server response, same with the older versioned phone.
To get rid of 2 i just disabled the windows firewall - still same problem.
Does anyone has a clue to why this effect might happen?
Thanks!
Edit
My python code:
def scan(data, addr, sock):
print "received scan message:", data, addr
name = u"name".encode("utf-16-le")
data = "DISC" + short2bytes(len(name)) + name
print "sending back %s to %s" % (data, addr)
sock.sendto(data, addr)
if __name__ == "__main__":
sock = socket(AF_INET, SOCK_DGRAM)
sock.bind(('', UDP_PORT))
while 1:
data, addr = sock.recvfrom(1500)
print "received packet " + data
if data.startswith("SCAN"):
scan(data, addr, sock)
edit 2:
Okay! Seems like my code and protocol DID work.
As it turns out the 2.3.3 phone had some severe ARP problems.
After some resets it works flawlessly!
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.
I am working on using the BT 4.0 API that Motorola has provided with the RAZR. In one of their documents it states to use the Android API to pair before connecting and using their framework. Per their instructions I have been pairing with OS Bluetooth settings application, but it never prompts me for a key. It will pair but doesn't appear to bond, and this is critical for me.
My question is, when they say "using the Android API" is this referring to simply using the OS Bluetooth utility to pair before hand (like I have been doing), or is there some way to do it with code in my application. They reference the "createBond()" function which, to my knowledge, is not an accessible function (at least not without some squirrely libraries or reflection).
Any advice is greatly appreciated, especially anyone who has used the API successfully, if they could give an account of their process. I'm just looking for some clarity at this point :)
Lloyd,
You are correct, follow the instructions in the link you posted.
Outside of coding, when they say use the standard android api for "non-le" operations, they mean go ahead and pair the ble device the same way you would any bluetooth classic devices inside android settings -> wireless & network -> bluetooth -> scan for devices.
If the device you are using is a motorola le compatible device the ble device will be paired but not connected.
Now, in the code, you can detect this paired device through the same method of
BluetoothAdapter.getDefaultAdapter().getBondedDevices()
To double check if your Android Phone is LE compatible, run this code:
public static boolean checkBLESupport() {
boolean deviceSupportsLE;
try {
#SuppressWarnings({ "unused", "rawtypes" })
Class object = Class.forName("android.server.BluetoothGattService");
deviceSupportsLE = true;
} catch (Exception e) {
deviceSupportsLE = false;
}
return deviceSupportsLE;
}
And to double check if the bluetooth device you paired is LE, when you are looping through the bonded devices.
Check the device with this code.
if (device.getBluetoothClass() == null) {
Log.i(TAG, "This device is BLE compatible");
b = true;
} else {
Log.i(TAG, "This device is not BLE");
b = false;
}
Now for establishing connection from your LE compatible phone to your LE compatible bluetooth device, follow the Gatt service instructions under the link you posted. http://developer.motorola.com/docs/bluetooth-low-energy-api/
Take note that under this example it is connecting to a bluetooth low energy heart rate monitor.
If you are not trying to connect to the heart rate monitor with LE heart rate profile, here is a link to another Motorola document that details creating your own LE Profile to use with the GATT framework. http://developer.motorola.com/docs/bluetooth-low-energy-gatt-framework-api/
If the instructions are not clear enough at any point in either of these documents, motorola offers sample android applications using the frameworks in those documents.
I guess motorola stack has BLE support. But what i feel is that it does not pair with the devices that require bonding though It does work some sensors. I have tried with a proximity sensor that require bonding. It never gets paired though the devices is discovered with Razr which even does not with S3.
There's a helpful video here.
Late to the game, but can confirm -
If your BLE Peripheral requires bonding, Moto X - and some other older Motorola devices - MUST be paired via Bluetooth Settings prior to programmatic connection via the Android GATT interface.
If you bond via the createBond method, or reading of an encrypted characteristic, your connection will be dropped typically in under 60 seconds, despite DDMS logs that show a good bond may be established.
My goal is to write an app that allows me to control my Motorola Xoom with a Playstation 3 Bluetooth Remote Control.
The device is able to be discovered by the native bluetooth app & classified as being a joystick. However, I cannot pair via the native bluetooth app because the app requires a PIN & the device does not have a pin that I am aware of.
So far I am able to programmatically discover the device & create a socket, however all attempts to connect to the device fail.
In both cases:
UUID u = UUID.fromString("00001124-0000-1000-8000-00805f9b34fb");
This is supposed to be the UUID used by HID devices. I also used the method described on another site to verify the UUID is available on the device.
Method1 (many people seem to have issues with this):
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(u);
socket.connect();
Result: IOException "Service discovery failed"
Method2 (the accepted workaround to Method1. I also tried ports 1-100):
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
BluetoothSocket socket = (BluetoothSocket) m.invoke(device, 1);
socket.connect();
Result: IOException "Connection refused"
I have tried this code using 3 devices (plus their UUIDs):
Playstation Remote
00001124-0000-1000-8000-00805f9b34fb
00001200-0000-1000-8000-00805f9b34fb
Nintento Wiimote
00001000-0000-1000-8000-00805f9b34fb
00001124-0000-1000-8000-00805f9b34fb
00001200-0000-1000-8000-00805f9b34fb
Microsoft Bluetooth Number Pad
(which sucessfully pairs, with a pin, via the natvie bluetooth app)
00001000-0000-1000-8000-00805f9b34fb
00001124-0000-1000-8000-00805f9b34fb
00001200-0000-1000-8000-00805f9b34fb
To be able to connect to the devices you have to connect over the HID profile, what you are trying is connecting over SPP (Serial Port Profile) to the UUID for HID etc, this will not work.
In addition these devices have some "custom" HID protocol descriptors that allow it to work with this pre-paired gaming consoles, you will need to get access to those to be able to control the Xoom with these controllers