Socket closed android bluetooth

Disconnect a bluetooth socket in Android

I’m developing a program in which, from an Android Phone, I have to connect as a client to a Bluetooth medical sensor. I’m using the official Bluetooth API and no problem during connection (SPP profile), but when I end the socket, the sensor is still connected to my phone (although I have close the connection). Are there any way to make a Bluetooth disconnection? I think there is an intent called ACTION_ACL_CONNECTED, which does that. Can anyone explain me how to use this? Thanks in advance. EDITED: Here is the code, if anyone needs additional info, it’s a Nonin 4100 medical sensor.

Set pairedDevices = Activa.myBluetoothAdapter.getBondedDevices(); // If there are paired devices if (pairedDevices.size() > 0) < // Loop through paired devices for (BluetoothDevice device : pairedDevices) < // Add the name and address to an array adapter to show in a ListView String name = device.getName(); if (name.contains("Nonin")) < try < found = true; // socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); // handler.sendEmptyMessage(5); // Activa.myBluetoothAdapter.cancelDiscovery(); // socket.connect(); BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress()); Method m; try < m = hxm.getClass().getMethod("createRfcommSocket", new Class[]); socket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1)); handler.sendEmptyMessage(5); socket.connect(); > catch (Exception e) < handler.sendEmptyMessage(7); e.printStackTrace(); break; >handler.sendEmptyMessage(6); InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); byte[] retrieve = < 0x44, 0x31>; out.write(retrieve); byte [] ack = new byte [1]; in.read(ack); if (ack[0] == 0x15) < cancelMeasurement(); return; >byte [] data = new byte [3]; long timeStart = System.currentTimeMillis(); this.timePassed = System.currentTimeMillis() - timeStart; while ((this.timePassed < (this.time))&&(this.finished)) < try < in.read(data); processData(data); Thread.sleep(1000); this.timePassed = System.currentTimeMillis() - timeStart; >catch (Exception e) < e.printStackTrace(); >> in.close(); out.close(); socket.close(); > catch (IOException e) < e.printStackTrace(); >> > > > 

6 Answers 6

Please remember to close your Input/output streams first, then close the socket.

By closing the streams, you kick off the disconnect process. After you close the socket, the connection should be fully broken down.

If you close the socket before the streams, you may be bypassing certain shutdown steps, such as the (proper) closing of the physical layer connection.

Here’s the method I use when its time to breakdown the connection.

/** * Reset input and output streams and make sure socket is closed. * This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown. * @return */ private void resetConnection() < if (mBTInputStream != null) < try catch (Exception e) <> mBTInputStream = null; > if (mBTOutputStream != null) < try catch (Exception e) <> mBTOutputStream = null; > if (mBTSocket != null) < try catch (Exception e) <> mBTSocket = null; > > 

EDIT: Adding code for connect():

// bluetooth adapter which provides access to bluetooth functionality. BluetoothAdapter mBTAdapter = null; // socket represents the open connection. BluetoothSocket mBTSocket = null; // device represents the peer BluetoothDevice mBTDevice = null; // streams InputStream mBTInputStream = null; OutputStream mBTOutputStream = null; static final UUID UUID_RFCOMM_GENERIC = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); /** * Try to establish a connection with the peer. * This method runs synchronously and blocks for one or more seconds while it does its thing * SO CALL IT FROM A NON-UI THREAD! * @return - returns true if the connection has been established and is ready for use. False otherwise. */ private boolean connect() < // Reset all streams and socket. resetConnection(); // make sure peer is defined as a valid device based on their MAC. If not then do it. if (mBTDevice == null) mBTDevice = mBTAdapter.getRemoteDevice(mPeerMAC); // Make an RFCOMM binding. try catch (Exception e1) < msg ("connect(): Failed to bind to RFCOMM by UUID. msg=" + e1.getMessage()); return false; >msg ("connect(): Trying to connect."); try < mBTSocket.connect(); >catch (Exception e) < msg ("connect(): Exception thrown during connect: " + e.getMessage()); return false; >msg ("connect(): CONNECTED!"); try < mBTOutputStream = mBTSocket.getOutputStream(); mBTInputStream = mBTSocket.getInputStream(); >catch (Exception e) < msg ("connect(): Error attaching i/o streams to socket. msg mt24">
)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f2.5%2f" data-se-share-sheet-license-name="CC BY-SA 2.5" data-s-popover-placement="bottom-start">Share
)" title="">Improve this answer
)">edited Jun 16, 2010 at 12:46
answered Jun 14, 2010 at 18:26
12
    1
    Hi, First of all, thansk for your reply, but It doesn't solve me the problem. I was doing something similar (that is, first closing the streams and then the socket) and so I disconnect the connection from the Android side, but the medical sensor I was using is not advertised of the disconnection and keeps on connected, so I can't connect again to it unless I reset it.
    – user365610
    Jun 15, 2010 at 10:44
    Please post your code. At this point we're just guessing. I've seen the problem you're reporting but there can be many causes so before I waste more of my time guessing, please post your code.
    – Brad Hein
    Jun 15, 2010 at 14:26
    I have edited the original post with the code. I have replaced the part of closing the streams and the socket with the one you passed me, but it remains equal. Thanks in advance.
    – user365610
    Jun 16, 2010 at 12:05
    Thanks for posting the code it is very helpful. 1. Missing RFCOMM Binding. 2. try-catch is trying too many things - if one thing fails then the code that follows it never executes. Specifically, put the two stream closes in a try-catch, and the socket.close in another. 3. why the getClass() and getMethod() approach? I'm not familiar with this approach but it feels risky. 4. What are you doing the sendEmptyMessage() stuff for? It seems superfluous 5. Why Integer.valueOf(1) instead of just 1? 6. When reading, just use in.read() to read a single byte as an integer, much simpler than a byte[]..
    – Brad Hein
    Jun 16, 2010 at 12:42
    1
    Brad, I am trying to learn Bluetooth SPP for an app I am working on at work. In addition to helping solve a frustrating disconnection problem I was having, your code (with comments) is one of the most concise explanations I have seen of trying to connect with SPP. Do you have any post or articles anywhere that expound on this? I think this is the beginnings of a solid tutorial.
    – jaredkwright
    Mar 15, 2016 at 3:31
|Show 7 more comments
19

I found that if I call socket.close() too soon after a recent communication via the OutputStream, then the close fails and I cannot reconnect. I added a Thread.sleep(1000) just prior to the call to close() and this seems to solve it.

)" data-controller="se-share-sheet" data-se-share-sheet-title="Share a link to this answer" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="answer" data-se-share-sheet-social="facebook twitter devto" data-se-share-sheet-location="2" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Share
)" title="">Improve this answer
answered Mar 31, 2014 at 18:23
1
    solution from djilk works for me !, adding the Thread.sleep(1000) before reseting the conection it releases the bluetooth. Tested on 3 SPP devices included the CsR 417 Thanks.
    – user3523720
    Apr 11, 2014 at 15:11
Add a comment|
11

HI,

I've seen the exact same problem (HTC Desire). Despite closing the socket by the book (as Brad suggests), the next connect() blocks forever - until ended by close() by another thread.

I circumvented the problem by always calling BluetoothAdapter.disable()/.enable() before connecting. Awful, unfriendly hack, I know.

I suspect that some of the present BT issues are manufacturer specific, as some app implementors seem to live happily with createRfcommSocketToServiceRecord(), which definitely fails on my HTC Desire (Android 2.1 update 1).

I have seen indications (sorry, don't have references) that HTC Desire's BT stack differs from the Nexus One, although they seem to be very similar devices.

BR Per

(addition) Here's a very simple activity to reproduce the problem (without my disable/enable 'cure'):

package com.care2wear.BtTest; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.os.Bundle; import android.util.Log; import android.widget.TextView; public class BtTestActivity extends Activity < private static final String TAG="BtTest"; BluetoothAdapter mBtAdapter = null; BluetoothDevice mBtDev = null; BluetoothSocket mBtSocket = null; InputStream isBt; OutputStream osBt; String mAddress = "00:18:E4:1C:A4:66"; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); connect(); // ok disconnect(); // ok connect(); // this invariably fails - blocked until BT is switched off by someone else, or the peer device turns off/goes out of range disconnect(); >private void init() < Log.d(TAG, "initializing"); mBtAdapter = BluetoothAdapter.getDefaultAdapter(); mBtDev = mBtAdapter.getRemoteDevice(mAddress); Log.d(TAG, "initialized"); >private void connect() < try < Log.d(TAG, "connecting"); Method m = mBtDev.getClass().getMethod("createRfcommSocket", new Class[] < int.class >); mBtSocket = (BluetoothSocket) m.invoke(mBtDev, 1); mBtSocket.connect(); Log.d(TAG, "connected"); > catch (SecurityException e) < Log.e(TAG, "SecEx", e); >catch (NoSuchMethodException e) < Log.e(TAG, "NsmEx", e); >catch (IllegalArgumentException e) < Log.e(TAG, "IArgEx", e); >catch (IllegalAccessException e) < Log.e(TAG, "IAccEx", e); >catch (InvocationTargetException e) < Log.e(TAG, "ItEx", e); >catch (IOException e) < Log.e(TAG, "IOEx", e); >> private void disconnect() < Log.d(TAG, "closing"); if (isBt != null) < try < isBt.close(); >catch (IOException e) < Log.e(TAG, "isBt IOE", e); >isBt = null; > if (osBt != null) < try < osBt.close(); >catch (IOException e) < Log.e(TAG, "osBt IOE", e); >osBt = null; > if (mBtSocket != null) < try < mBtSocket.close(); >catch (IOException e) < Log.e(TAG, "socket IOE", e); >mBtSocket = null; > Log.d(TAG, "closed"); > >

If anyone can spot if I'm doing it wrongly, feel free to comment 🙂

(addition 2) I think I got it to work now:

  1. The official method of connecting RFCOMM (via SDP) now actually seems to work (HTC Desire, 2.1 update 1), BUT I had to remove and re-pair the BT device. Go figure..
  2. Reconnection may still fail (service discovery failure) if I reconnect 'too quickly' (quit app, then immediately restart). Guess the connection is not completely down yet..
  3. If I always end the (last) activity not only with finish(), but also with Runtime.getRuntime().exit(0);, it works a lot better. Go figure again.

If anyone can explain this, I'll happily learn. /Per

(addition 3) Finally got the Froyo (2.2) update for my Desire, and as far as I can see, SPP now works 🙂 /Per

Источник

Android: Bluetooth Socket closed

I have been working on a Bluetooth device and am creating an app for it. I should be able to turn on or off this devices LED by sending it the code 0 or 1. I have some error catching in place to help me with the issue, and after staring at it for ages cannot see where the problem lies. I find devices correctly, and have checked the MAC address returned of the device, that is all fine. From what I can see with logs I also appear to open all the sockets correctly. The error occurs on the final stage of the process with sending byte data to the device. Can anyone spot something I can't? Perhaps the connection is not being made successfully? To clarify the exception triggered is in the sendData() method. If you find the error I will love you forever haha. The error message: Fatal Error, In onResume() and an exception occurred during write:socket closed. So what the socket is closing before the data sends or is never successfully opened? Anyway, a lot of code inbound:

public class ScanFragment extends Fragment < ArrayListscannedList; Button scanningButton; TextView scanningText; ListView scannedListView; BluetoothAdapter mBluetoothAdapter; DeviceItem item; DeviceCustomAdapter adapter; BluetoothDevice device; String TAG = "TEST"; private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private OutputStream outStream = null; // Intent request codes private static final int REQUEST_CONNECT_DEVICE_SECURE = 1; private static final int REQUEST_ENABLE_BT = 3; // Well known SPP UUID private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // Insert your bluetooth devices MAC address private static String address = "00:00:00:00:00:00"; public ScanFragment() < // Required empty public constructor >@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) < return inflater.inflate(R.layout.fragment_scan, container, false); >@Override public void onDestroy() < getActivity().unregisterReceiver(mReceiver); super.onDestroy(); >private final BroadcastReceiver mReceiver = new BroadcastReceiver() < public void onReceive(Context context, Intent intent) < Log.i("found", "hello" + ""); String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) < device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); item = new DeviceItem(); item.setDeviceName(device.getName()); item.setDeviceCode(device.getAddress()); item.setDeviceId(MY_UUID); scannedList.add(item); Log.i("BT", device.getName() + "\n" + device.getAddress()); >else < Log.i("BT", "none" + ""); >adapter = new DeviceCustomAdapter( getActivity().getApplicationContext(), scannedList); scannedListView.setAdapter(adapter); > >; @Override public void onActivityCreated(Bundle savedInstanceState) < // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState); scannedList = new ArrayList<>(); scanningButton = (Button) getActivity().findViewById(R.id.scanningButton); scanningText = (TextView) getActivity().findViewById(R.id.scanningText); scannedListView = (ListView) getActivity().findViewById(R.id.scannedListView); scannedListView.setVisibility(View.VISIBLE); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (Build.VERSION.SDK_INT >= 15 && ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) < ActivityCompat.requestPermissions(getActivity(), new String[], 1); > if (mBluetoothAdapter == null) < scanningText.setText("Your device does not support Bluetooth, Sorry!"); >else if (!mBluetoothAdapter.isEnabled()) < scanningText.setText("You need to enable bluetooth to use this app.."); Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); >scanningButton.setOnClickListener(new View.OnClickListener() < @Override public void onClick(View view) < scanningText.setText("Scanning. "); mBluetoothAdapter.startDiscovery(); mBluetoothAdapter.isDiscovering(); scanningText.setText("Click on a device to connect"); >>); // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); getActivity().registerReceiver(mReceiver, filter); scannedListView.setOnItemClickListener(new AdapterView.OnItemClickListener() < @Override public void onItemClick(AdapterViewparent, View view, int position, long id) < item = scannedList.get(position); String name= scannedList.get(position).getDeviceName(); Toast toast = Toast.makeText(getActivity().getApplicationContext(), "Connecting to " + item.getDeviceCode() + "" + name, Toast.LENGTH_SHORT); toast.show(); scanningText.setText(item.getDeviceCode()); mBluetoothAdapter.cancelDiscovery(); address = item.getDeviceCode(); // Create the result Intent and include the MAC address connectDevice(address, true); ledOff(view); >>); > public void ledOn(View v) < sendData("1"); Toast msg = Toast.makeText(getActivity().getApplicationContext(), "LED is ON", Toast.LENGTH_SHORT); msg.show(); >public void ledOff(View v) < sendData("0"); Toast msg = Toast.makeText(getActivity().getApplicationContext(), "LED is OFF", Toast.LENGTH_SHORT); msg.show(); >public void connectToDevice(String adr) < super.onResume(); //enable buttons once connection established. // btnOn.setEnabled(true); // btnOff.setEnabled(true); // Set up a pointer to the remote node using it's address. btAdapter = mBluetoothAdapter; BluetoothDevice device = btAdapter.getRemoteDevice(adr); // Two things are needed to make a connection: // A MAC address, which we got above. // A Service ID or UUID. In this case we are using the // UUID for SPP. try < btSocket = device.createRfcommSocketToServiceRecord(MY_UUID); >catch (IOException e) < errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + "."); >// Discovery is resource intensive. Make sure it isn't going on // when you attempt to connect and pass your message. btAdapter.cancelDiscovery(); // Establish the connection. This will block until it connects. try < btSocket.connect(); >catch (IOException e) < try < btSocket.close(); >catch (IOException e2) < errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + "."); >> // Create a data stream so we can talk to server. try < outStream = btSocket.getOutputStream(); >catch (IOException e) < errorExit("Fatal Error", "In onResume() and output stream creation failed:" + e.getMessage() + "."); >> private void errorExit(String title, String message) < Toast msg = Toast.makeText(getActivity().getApplicationContext(), title + " - " + message, Toast.LENGTH_SHORT); msg.show(); // finish(); >private void sendData(String message) < byte[] msgBuffer = message.getBytes(); try < outStream.write(msgBuffer); >catch (IOException e) < String msg = "In onResume() and an exception occurred during write: " + e.getMessage(); errorExit("Fatal Error", msg); >> private void connectDevice(String address, boolean secure) < // Get the device MAC address connectToDevice(address); // Get the BluetoothDevice object BluetoothDevice device = btAdapter.getRemoteDevice(address); >> 

Источник

Читайте также:  Bluetooth гарнитура huawei am07
Оцените статью
Adblock
detector