How to prevent Android bluetooth RFCOMM connection from dying immediately after .connect()?

北城余情 提交于 2019-11-26 12:42:35

Try to change your code for creating RfcommSocket:

sock = zee.createRfcommSocketToServiceRecord(
                      UUID.fromString("8e1f0cf7-508f-4875-b62c-fbb67fd34812"));

for this code:

Method m = zee.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
sock = (BluetoothSocket) m.invoke(device, 1);

Also try to change argument value in range 1-3 in this m.invoke(device, 1); When connection will be Connected, but aborted when you try reading, call in some loop your method test() again. As simple:

for(int i=0;i<3;i++){  if(!testDone) test(); }

I merged code I had written and code from [android-beginners] Re: Serial over Bluetooth by XCaffeinated]1 and the above post.

To create the simplest bluetooth program possible.

The main addition for this code is add better handling on the exceptions thrown by connect().

Search for '@todo' to customize for your needs.

I hope this saves you some time!

package com.xxx; // @todo Change to your package.   

import java.io.IOException;
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;

/**
 * This is the simplest bluetooth program. It sends one message to one bluetooth
 * device. The message and the bluetooth hardware id for the device are hard
 * coded. <br>
 * <br>
 * It does <b>not</b> receive any data. It does not do any thread processing. <br>
 * <br>
 * 
 * This application will be useful to communicate with a bluetooth hardware
 * device such as a bar code reader, Lego Mindstorm, a PC with a com port
 * application, a PC with a terminal program with 'listening' to a com port, a
 * second android device with a terminal program such as <a href=
 * "http://www.tec-it.com/en/software/data-acquisition/getblue/android-smartphone/Default.aspx"
 * >GetBlue</a>. It is not a full android bluetooth application but more a proof
 * of concept that the bluetooth works.
 * 
 * <br>
 * <br>
 * 
 * This code should cut and paste into the <a
 * href="http://developer.android.com/resources/tutorials/hello-world.html>
 * 'HelloAndroid' example</a>. It does not use any screen io.
 * 
 * Add to your Android Manifest.xml file: <uses-permission
 * android:name="android.permission.BLUETOOTH" /> <uses-permission
 * android:name="android.permission.BLUETOOTH_ADMIN" />
 * 
 * For a proper bluetooth example with threading and receiving data see: <a
 * href=
 * "http://developer.android.com/resources/samples/BluetoothChat/index.html"
 * >http://developer.android.com/resources/samples/BluetoothChat/index.html</a>
 * 
 * @see <a
 *      href="http://developer.android.com/guide/topics/wireless/bluetooth.html">
 *      http://developer.android.com/guide/topics/wireless/bluetooth.html</a>
 * 
 */
public class BlueToothTesterActivity extends Activity {

    /** The BluetoothAdapter is the gateway to all bluetooth functions **/
    protected BluetoothAdapter bluetoothAdapter = null;

    /** We will write our message to the socket **/
    protected BluetoothSocket socket = null;

    /** The Bluetooth is an external device, which will receive our message **/
    BluetoothDevice blueToothDevice = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Grab the BlueToothAdapter. The first line of most bluetooth programs.
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // if the BluetoothAdapter.getDefaultAdapter(); returns null then the
        // device does not have bluetooth hardware. Currently the emulator
        // does not support bluetooth so this will this condition will be true.
        // i.e. This code only runs on a hardware device an not on the emulator.
        if (bluetoothAdapter == null) {
            Log.e(this.toString(), "Bluetooth Not Available.");
            return;
        }

        // This will find the remote device given the bluetooth hardware
        // address.
        // @todo: Change the address to the your device address
        blueToothDevice = bluetoothAdapter.getRemoteDevice("00:00:00:00:00:00");

        for (Integer port = 1; port <= 3; port++) {
            simpleComm(Integer.valueOf(port));
        }
    }

    protected void simpleComm(Integer port) {
        // byte [] inputBytes = null;

        // The documents tell us to cancel the discovery process.
        bluetoothAdapter.cancelDiscovery();

        Log.d(this.toString(), "Port = " + port);
        try {
            // This is a hack to access "createRfcommSocket which is does not
            // have public access in the current api.
            // Note: BlueToothDevice.createRfcommSocketToServiceRecord (UUID
            // uuid) does not work in this type of application. .
            Method m = blueToothDevice.getClass().getMethod(
                    "createRfcommSocket", new Class[] { int.class });
            socket = (BluetoothSocket) m.invoke(blueToothDevice, port);

            // debug check to ensure socket was set.
            assert (socket != null) : "Socket is Null";

            // attempt to connect to device
            socket.connect();
            try {
                Log.d(this.toString(),
                        "************ CONNECTION SUCCEES! *************");

                // Grab the outputStream. This stream will send bytes to the
                // external/second device. i.e it will sent it out.
                // Note: this is a Java.io.OutputStream which is used in several
                // types of Java programs such as file io, so you may be
                // familiar with it.
                OutputStream outputStream = socket.getOutputStream();

                // Create the String to send to the second device.
                // Most devices require a '\r' or '\n' or both at the end of the
                // string.
                // @todo set your message
                String message = "Data from Android and tester program!\r";

                // Convert the message to bytes and blast it through the
                // bluetooth
                // to the second device. You may want to use:
                // public byte[] getBytes (Charset charset) for proper String to
                // byte conversion.
                outputStream.write(message.getBytes());

            } finally {
                // close the socket and we are done.
                socket.close();
            }
            // IOExcecption is thrown if connect fails.
        } catch (IOException ex) {
            Log.e(this.toString(), "IOException " + ex.getMessage());
            // NoSuchMethodException IllegalAccessException
            // InvocationTargetException
            // are reflection exceptions.
        } catch (NoSuchMethodException ex) {
            Log.e(this.toString(), "NoSuchMethodException " + ex.getMessage());
        } catch (IllegalAccessException ex) {
            Log.e(this.toString(), "IllegalAccessException " + ex.getMessage());
        } catch (InvocationTargetException ex) {
            Log.e(this.toString(),
                    "InvocationTargetException " + ex.getMessage());
        }
    }

}

If I understand correctly, your app is unable to see any data from the device whatsoever?

One small thing: try your UUID without hiphens. In my RFCOMM apps I actually define the UUID as a long integer constant.

Also, the way your test() method is written leads me to believe the test() is making the connection, defining a thread, telling it to start and immediately returning. In other words, your thread is referencing a variable from outside of the thread which is part of the test() method but when test() dies, so does its variables.

In short, try your testing outside of a thread and get it working there first. One easy way to do this would be to use Thread.run() instead of thread.start(). .run() runs it in the foreground (and thus blocks test() so it doesn't return before the thread finished).

For a longer term solution you may wish to define your Bluetooth variables as gloibal/member variables so they don't go out of scope and are always available to your thread.

Try the well known UUID:00001101-0000-1000-8000-00805F9B34FB

Code above not worked on Samsung Galaxy tab 2 with 4.0.4. BTSocket.connect always fired bluetooth pairing dialog and then failed, even if correct pin was typed. Changing from "createRfcommSocket" to "createInsecureRfcommSocket" solved the problem. Hope this will help, I struggled with this issue for more than 3 hours.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!