I'm using the Android development sample project BluetoothChat.
http://developer.android.com/resources/samples/BluetoothChat/index.html
I'm running it on an Archos 43 and trying to communicate with a serial to bluetooth adapter.
To communicate with the adapter I need to use UUID 00001101-0000-1000-8000-00805F9B34FB.
However, when I do that, I get a Null Pointer Exception at this line:
socket = mmServerSocket.accept();
If I use a different UUID I do not have this problem, however I cannot connect to the serial adapter.
If I use a Motorola Droid instead of the Archos 43, I do not have this problem.
From some error messages, I think the Archos is using the bluez stack.
Any ideas why the combination of this UUID and stack would cause an exception when calling the accept() function?
Here's the surrounding code (you can get the whole source from the link above)
public void run() {
if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
break;
}
Some error messsages from the log:
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): listen() failed
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): java.io.IOException: Not able to register SDP record for BluetoothChat
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): at android.bluetooth.BluetoothAdapter.listenUsingRfcommWithServiceRecord(BluetoothAdapter.java:778)
Did you change the constructor of "class AcceptThread" , where you use this function "listenUsingRfcommWithServiceRecord()" ?
I'm using the same UUID on archos 70 and i dont get any bluetooth connection errors.( Try restarting the archos if its intermittent.) I wanted to add this as comments for some reasons i dont see a comment !
It ends up the problem was solved with a firmware update from Archos.
Related
I'm trying to establish a bluetoothconnection to another phoner. Later on, it'll be a board with a HC5 module, but for debugging I'm just using a phone.
The problem is, that connect fails and throws an IO Exception:
" read failed, socket might closed or timeout, read ret: -1"
A quick google-search shows a lot having this problem. The only way I can see it solved, is by using a method not public in the API
Method m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
mmSocket = (BluetoothSocket) m.invoke(mmDevice, 1);
The problem just is, that createRfcommSocket has been removed, and the result from getMethod will be null.
My code is from the example: https://github.com/xamarin/monodroid-samples/tree/master/BluetoothChat which for connecting is:
public ConnectThread(BluetoothDevice device, BluetoothChatService service)
{
UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805f9b34fb");
mmDevice = device;
_service = service;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try
{
if ((int)Android.OS.Build.VERSION.SdkInt >= 10) // Gingerbread 2.3.3 2.3.4
tmp = device.CreateInsecureRfcommSocketToServiceRecord(MY_UUID);
else
tmp = device.CreateRfcommSocketToServiceRecord(MY_UUID);
}
catch (Java.IO.IOException e)
{
Log.Error(TAG, "create() failed", e);
}
mmSocket = tmp;
}
Since the 'original hack' doesn't work, and I haven't found any other solution, I'm hoping somebody here knows how to fix this.
Best regards!
This is the issue I and others in my company have come across when working with Bluetooth devices from Android phones. It is well described on SO here: Service Discovery Failed Exception Using Bluetooth On Android
The method you describe as being removed is, in fact, still operational. And it is the one we have successfully used. We attempt connection using the
tmp = device.CreateRfcommSocketToServiceRecord(MY_UUID);
method you show above.
Use a try...catch block around tmp.Connect() (your code does not show the Connect call)
In the catch block "re-create" the BluetoothSocket using the createRfcommSocket method. I used a small method to do this:
private BluetoothSocket CreateRfcommSocket(BluetoothDevice bTdevice)
{ // This is an "undocumented" call that is needed to (mostly) avoid a Bluetooth Connection error
// introduced in Android v4.2 and higher. It is used as a "fallback" connection.
// Full paths version of code!
//Java.Lang.Reflect.Method mi = device.Class.GetMethod("createRfcommSocket", new Java.Lang.Class[] { Java.Lang.Integer.Type });
//_bluetoothSocket = (BluetoothSocket)mi.Invoke(device, 1);
// Compact version of above
var mi = bTdevice.Class.GetMethod("createRfcommSocket", Integer.Type);
return (BluetoothSocket)mi.Invoke(bTdevice, 1);
}
This is the method indicated here: Xamarin Forum Post
I have tested this on Android 4.4.2 and Android 8.0 and it works on these systems. Another person in the company has tested the Java equivalent code on Android: 4.2.2, 4.4.2, 7.0 and 8.0 and it works in every case.
I'm having a little trouble here, on one hand I have a server listening on port 23000 and on the other an Android App acting as the client. While connection seems to work in the Emulator (this is built for 2.3.3 by the way) using the typical 10.2....IP, when trying on a Samsung Galaxy Tab I keep on getting the famous:
"Address family not supported by protocol exception"
Eventually, code looks like this:
InetSocketAddress inetAddress;
//this is done to keep backward compatibility prior 2.0.4 release
if(host == null || host.equals("")) {
//check if defaultIp is also empty
if (defaultIPAddress == null || defaultIPAddress.equals(""))
throw new UnknownHostException();
//otherwise start listening on defaultIp
else
{
inetAddress = new InetSocketAddress(defaultIPAddress, port);
}
}
//start listening on host
else
{
inetAddress = new InetSocketAddress(host, port);
}
// open the socket channel
this.channel = SocketChannel.open(inetAddress);
this.channel.configureBlocking(false);
this.channel.socket().setTcpNoDelay(true);
It fails when trying to open the socket at
this.channel = SocketChannel.open(inetAddress);
Needless to say, I have the required permissions in my Manifest, as said previously, this is working fine in the Emulator.
Besides, this is no network issue, both machines are connected to a Wireless Wifi created using a router I have at hand, with no firewalls, proxys, completely open, to put it that way...
Any ideas?
Thanks!
Alex
If anybody lands on this question and is having the same issue, this was caused because I was trying to open the Socket in the same thread of the main Activity. Looks like this is a) not advisable and b) not permitter any longer. Thus, move your connecting code to a separate thread and you should be safe.
I want to check whether the BluetoothSocket is open for operation or not.....
Here is what I do:
First of all I get an InputStream from my BluetoothSocket, I want to perform some operation with that InputStream, if an IOException occurs my program can determine that socket is disconnected..... And after making sure that socket is connected I want to read some data from it.
For making sure I am calling available() which by default returns 0 or a number of bytes.... if return value is 0 my reading operation throws IOException.
Here are my questions.
Is available() blocking I/O call or an asynchronous one?
Return value >0 only when I give some input from my device while connecting, which will not always be the case. Am I doing any mistake allowing to read if there are 0 available bytes? How to avert this?
First u have to connect with a Bluetooth server. Use connect() to connect, this method will block until a connection is made or the connection fails (resulting in an exception). So make sure to run this on a separate thread.
public void run() {
try {
socket.connect();
InputStream in = socket.getInputStream();
//socket connected, inputStream can be used
//Bluetooth
} catch (IOException e) {
//Socket is refused connection with the server.
}
}
I have been strugling with a Bluetooth project on Android for weeks. Does anyone know where I can go to see the actual code that's used by Google to make their Bluetooth pairing and connection logic work?
I have been through all the documentaiton, the BluetoothChat application (which doesn't work as advertised ... tried it on 3 different handsets), as well as a bunch of other sites on the net, but still no luck. I need to get an app up and running on 2.1 or higher.
Any advice or help is greatly appreciated.
Yes the Bluetooth project didn't work for me also because the code for socket connection is not working
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
this is not working ...
replace this by the following code
BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
Method m;
m = hxm.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1));
Ah, if you're having issues with application level code I'm not sure staring at the Bluetooth manager source will be much help, but here you go: https://android.googlesource.com/platform/packages/apps/Bluetooth the Bluetooth manager app code.
I'll re-iterate it: this is honestly probably not going to be helpful for what you want. You should be able to get a reasonably working Bluetooth app without having to look at this.
EDIT: if you want the code that implements the Bluetooth packages (android.bluetooth), see https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth for that.
You can browse all the android.bluetooth package around here:
http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/bluetooth/BluetoothClass.java#BluetoothClass
Is there a way, using the Android SDK, to programmatically connect to an already-paired Bluetooth device?
In other words: I can go into Settings -> Wireless & networks -> Bluetooth settings, and tap the device (listed as "Paired but not connected"), at which point it will connect. I'd like to be able to do this programmatically, but don't see a way to do this.
I see the options to create an RFCOMM socket, and for a SPP device, I'm assuming that'll do the connection part as well, but for an A2DP device, where the actual data transfer will be handled by the OS rather than by my app, I think that's not applicable?
Okay, since this was driving me crazy, I did some digging into the source code and I've found a 100% reliable (at least on my Nexus 4, Android 4.3) solution to connect to a paired A2DP device (such as a headset or Bluetooth audio device). I've published a fully working sample project (easily built with Android Studio) that you can find here on Github.
Essentially, what you need to do is:
Get an instance of the BluetoothAdapter
Using this instance, get a profile proxy for A2DP:
adapter.getProfileProxy (context, listener, BluetoothProfile.A2DP);
where listener is a ServiceListener that will receive a BluetoothProfile in its onServiceConnected() callback (which can be cast to a BluetoothA2dp instance)
Use reflection to acquire the connect(BluetoothDevice) method on the proxy:
Method connect = BluetoothA2dp.class.getDeclaredMethod("connect", BluetoothDevice.class);
Find your BluetoothDevice:
String deviceName = "My_Device_Name";
BluetoothDevice result = null;
Set<BluetoothDevice> devices = adapter.getBondedDevices();
if (devices != null) {
for (BluetoothDevice device : devices) {
if (deviceName.equals(device.getName())) {
result = device;
break;
}
}
}
And invoke the connect() method:
connect.invoke(proxy, result);
Which, at least for me, caused an immediate connection of the device.
the best way I found to solve my problem was finding out that I can create a button that brings up the Bluetooth Settings screen. I didn't realize you could do this, or I would have from the beginning.
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
if the device is already paired , then you can use
if(device.getBondState()==device.BOND_BONDED){
Log.d(TAG,device.getName());
//BluetoothSocket mSocket=null;
try {
mSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e1) {
// TODO Auto-generated catch block
Log.d(TAG,"socket not created");
e1.printStackTrace();
}
try{
mSocket.connect();
}
catch(IOException e){
try {
mSocket.close();
Log.d(TAG,"Cannot connect");
} catch (IOException e1) {
Log.d(TAG,"Socket not closed");
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
for the MY_UUID use
private static final UUID MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
the above code snippet is just to connect your device to an A2DP supported device.
I hope it will work.
I used the code here as a starting point for this functionality in my app: http://developer.android.com/guide/topics/wireless/bluetooth.html#ConnectingDevices
Once the device is paired, the app has no problem connecting the two devices together programmtically.