1

我有两个要连接的 Android 设备,使用蓝牙并通过 RFCOMM 通道传输数据。我只有一个设备接收数据,而另一个设备发送它......

使用此代码,我可以连接到其他设备并开始收听 RFCOMM 频道:

Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket) m.invoke(device, 2);
socket.connect();

class BasicThread implements Runnable{    

        public void run() {
            try {
                InputStream stream = socket.getInputStream();
                BufferedReader r = new BufferedReader(new InputStreamReader(stream));
                while (true){
                    Log.d("myapp", "now listening...");
                    latestLine = r.readLine();
                    Log.d("myapp", latestLine);
                }
            } catch (IOException e) {

            }
        } 
    }

    new Thread(new BasicThread()).run();

使用另一个设备,我实现了一个监听套接字,如下所示:

Method m = blue.getClass().getMethod("listenUsingRfcommOn", new Class[] { int.class });
BluetoothServerSocket socket = (BluetoothServerSocket) m.invoke(blue, 2);

BluetoothSocket sock = socket.accept();

Log.d("myapp", "Connected...\n\n\n\n\n\n\n\n");

OutputStream s = sock.getOutputStream();
final PrintWriter out = new PrintWriter(s);

它们都连接在 RFCOMM 通道 2 上,并且都互相看到对方,但是,第二个设备始终在BluetoothSocket sock = socket.accept();

有什么帮助吗?

4

1 回答 1

3

好的,我是新手,但我可以尝试提供帮助。所以这是我的经验,我设法使用反射连接了两个设备。我的 Android 手机是使用方法接收数据listenUsingInsecureRfcommOn,而其他设备是通信主机,通过 BT SPP 发送数据。我对这种方法有问题,因为它没有可见的 SDP 记录,所以我无法用其他设备检测到它。因此,我使用 Bluecove 和 Java SE 制作了小型嗅探器,它试图连接到给定范围内的每个端口。这是代码:

package application.test;

import static java.lang.System.out;

import java.io.InputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

public class RfCommClient {

    public static void main(String args[]) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        String add = "btspp://8C71F894A36D:";
        String par = ";authenticate=false;encrypt=false;master=true";
        String url = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd;HH-mm-ss-SSS");
        for (int i = 1; i < 15; ++i) {
            try {
                url = add + i + par;
                out.format("Time: %s, port = %d\n", sdf.format(System.currentTimeMillis()), i);
                StreamConnection conn = (StreamConnection) Connector.open(url);
                PrintStream ops = new PrintStream(conn.openOutputStream());
                ops.println("Hi there...");

                // response
                Thread.sleep(1000);

                InputStream is = conn.openInputStream();
                byte[] resp = new byte[5];
                int r = is.read(resp);

                out.println("r = " + r + ", response = " + new String(resp, "US-ASCII"));

                Thread.sleep(10 * 1000);
                conn.close();
            } catch (Exception e) {
                out.println("Exception occured, time = " + sdf.format(System.currentTimeMillis()) + ", i = " + i);
                //e.printStackTrace();
            }
        }

    }
}

我了解到,某些端口被占用,而某些端口无法使用(如文档所述,例如端口 0)。例如,我认为端口 2 已被占用,因为当我向其发送一些数据时,我会收到 5 个以 ERR 开头的字符 :)。

而另一方面,我的线程仍在等待?!:) 这导致我们注意到我注意到的另一件事,端口(或通道)并不总是映射到所需的数字。例如,对我来说经常发生我想在端口 15 上发送一些东西,但是在 Android 上,等待端口 9 的线程收到了数据:) 所以我建议,检查哪个端口是真正分配的!您可以使用我发布的代码来实现这一点。还有一点,这里有一个函数的链接channelPicker在使用普通API时选择频道,如果我没记错的话,里面的一些常量应该代表保留频道。

我刚刚注意到一些事情,我注册端口的代码略有不同,这是我的做法:

        Method m = cba.getDeclaredMethod("listenUsingInsecureRfcommOn", int.class);
        ss = (BluetoothServerSocket) m.invoke(BluetoothAdapter.getDefaultAdapter(), port);

无论如何,我知道这可能为时已晚,但是,也许将来有人会有类似的问题。

于 2012-05-30T12:18:54.567 回答