java 在 pc 上初始化蓝牙连接 android(client) 到 python(server)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10922319/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 03:05:36  来源:igfitidea点击:

Initializing bluetooth connection android(client) to python(server) on pc

javaandroidpython

提问by Simen Andresen

I am trying to send a "helloWorld" (just a string) from my android phone(samsung galaxy s2) to a python script on my pc running linux. But I cant get it to work. Below are the code for the android app(client) and the python script(server). The bluetooth are working fine on the pc and phone(e.g. I can send photos from the phone via BT). When I call btSocket.connect(); in the java code below it just wont connect. Do I have to specify a port to connect to, since I have specified a port for the serverSocket? Any help would be very appreciated.

我正在尝试将“helloWorld”(只是一个字符串)从我的 android 手机(三星 Galaxy s2)发送到我运行 linux 的电脑上的 python 脚本。但我无法让它工作。下面是 android 应用程序(客户端)和 python 脚本(服务器)的代码。蓝牙在 PC 和手机上工作正常(例如,我可以通过 BT 从手机发送照片)。当我调用 btSocket.connect(); 在下面的java代码中,它只是无法连接。我是否必须指定要连接的端口,因为我已经为 serverSocket 指定了一个端口?任何帮助将不胜感激。

public class BlueTooth_testActivity extends Activity {
    TextView header;
    Button discoverDevicesBtn;
    Button sendMsgBtn;
    Button closeBtn;
    EditText sendTxt;
    BluetoothAdapter btAdapter;
    BluetoothSocket btSocket;
    private static String btAdress = "00:10:60:D1:95:CD";
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private OutputStream out;
    public BluetoothDevice device;
    private Boolean CONNECTED = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //init layout parameters        
        header = (TextView) findViewById(R.id.text1);
        discoverDevicesBtn = (Button) findViewById(R.id.discBtn);
        sendMsgBtn = (Button) findViewById(R.id.sendButton);
        closeBtn = (Button) findViewById(R.id.closeButton);
        sendTxt = (EditText) findViewById(R.id.editText1);
        discoverDevicesBtn.setOnClickListener(discoverDeviceListener);
        sendMsgBtn.setOnClickListener(sendMsgListener);
        closeBtn.setOnClickListener(closeBtnListener);
        //init bluetooth
        btAdapter = BluetoothAdapter.getDefaultAdapter();
        if (btAdapter.isEnabled()) {
            Toast.makeText(this, "Bluetooth state:" + btAdapter.getState() + " Ok!", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Bluetooth state:" + btAdapter.getState() + " Not ok!", Toast.LENGTH_LONG).show();
        }

    }

    private Button.OnClickListener discoverDeviceListener = new Button.OnClickListener() {@Override
        public void onClick(View v) {
            if (!CONNECTED) {
                device = btAdapter.getRemoteDevice(btAdress);
                header.append("\nRemote device: " + device.getName());
                try {
                    btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
                } catch (Exception e) {
                                    }
                header.append("\n createRfcommsockettoservice! ");
                btAdapter.cancelDiscovery();
                try {
                    btSocket.connect();
                    CONNECTED = true;
                    header.append("\n btSocket Created!");
                } catch (IOException e) {
                    Toast.makeText(getApplicationContext(), "Could not connect to socket", Toast.LENGTH_LONG);
                    try {
                        btSocket.close();
                    } catch (Exception b) {}
                }
            }

        }
    };


    private Button.OnClickListener sendMsgListener = new Button.OnClickListener() {@Override
        public void onClick(View v) {
            if (CONNECTED) {
                try {
                    out = btSocket.getOutputStream();
                    String msg = sendTxt.getText().toString();
                    byte[] msgBffr = msg.getBytes();
                    out.write(msgBffr);
                    Toast.makeText(getApplicationContext(), "Message sent", Toast.LENGTH_LONG).show();
                } catch (Exception a) {
                    Toast.makeText(getApplicationContext(), "Could not send msg", Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(getApplicationContext(), "cant send msg, not connected", Toast.LENGTH_LONG).show();
            }

        }
    };


}  

(I havnt bothered to include the rest of the java code as the problem is somewhere in the connection setup)

(我没有费心包含其余的 java 代码,因为问题出在连接设置的某个地方)

import bluetooth

name="bt_server"
target_name="siggen"
uuid="00001101-0000-1000-8000-00805F9B34FB"

def runServer():
serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
    port=bluetooth.PORT_ANY
    serverSocket.bind(("",port))
    print "Listening for connections on port: ", port   
    serverSocket.listen(1)
    port=serverSocket.getsockname()[1]
    inputSocket, address=serverSocket.accept()
    print "Got connection with" , address
    data=inputSocket.recv("1024")
    print "received [%s] \n " % data    
    inputSocket.close()
    serverSocket.close()  

runServer()  

.

.

回答by trevor-e

You don't need to specify a port, it should just connect you to the first open RFComm channel. One thing I found for the Bluetooth app I've made is that in order for it to work on my phone, I have to manually connect to the computer that the server is running on BEFORE trying to connect in the app. That is, I go through Settings -> Wireless/Networks -> Bluetooth Settings -> <Find/Pair to Computer>and do all of that until the notification pops up in my system tray. Then, when I try to make the socket connection through my app it works. I find this strange because I only have to jump through these hoops on my phone and not tablet, so maybe it depends on the device.

您不需要指定端口,它应该只是将您连接到第一个打开的 RFComm 通道。我为我制作的蓝牙应用程序发现的一件事是,为了让它在我的手机上运行,​​我必须在尝试连接应用程序之前手动连接到运行服务器的计算机。也就是说,我会Settings -> Wireless/Networks -> Bluetooth Settings -> <Find/Pair to Computer>完成所有这些操作,直到通知在我的系统托盘中弹出。然后,当我尝试通过我的应用程序建立套接字连接时,它可以工作。我觉得这很奇怪,因为我只需要在手机上而不是平板电脑上跳过这些箍,所以也许这取决于设备。

Also, you are going to want to do the connection stuff in a separate Thread.

此外,您将希望在单独的Thread.

回答by NobodyMan

The Server Piece

服务器部分

I'm out of my depth when it comes to python, but it looks like your python snippet doesn't use the uuid anywhere. For example, the pybluez repo has an example serverwhere they use the uuid when calling advertise_service, which you don't appear to have in your snippet. If you were to do something similar, your snippit might look like:

当涉及到 python 时,我超出了我的深度,但看起来你的 python 代码段没有在任何地方使用 uuid。例如,pybluez 存储库有一个 示例服务器,它们在调用 时使用 uuid advertise_service,而您的代码段中似​​乎没有。如果您要执行类似的操作,您的代码段可能如下所示:

import bluetooth

name="bt_server"
target_name="siggen"
uuid="00001101-0000-1000-8000-00805F9B34FB"

def runServer():
serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
    port=bluetooth.PORT_ANY
    serverSocket.bind(("",port))
    print "Listening for connections on port: ", port   
    serverSocket.listen(1)
    port=serverSocket.getsockname()[1]

    #the missing piece
    advertise_service( server_sock, "SampleServer",
                       service_id = uuid,
                       service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ],
                       profiles = [ bluetooth.SERIAL_PORT_PROFILE ] 
                        )

    inputSocket, address=serverSocket.accept()
    print "Got connection with" , address
    data=inputSocket.recv("1024")
    print "received [%s] \n " % data    
    inputSocket.close()
    serverSocket.close()  

runServer()  

The Client

客户端

BluetoothDevice.createRfcommSocketToServiceRecord() is for creating "secure communication sockets". Is this what your server is doing? If not, perhaps BluetoothDevice.createInsecureRfcommSocketToServiceRecord() is the appropriate call?

BluetoothDevice.createRfcommSocketToServiceRecord() 用于创建“安全通信套接字”。这是您的服务器正在做的事情吗?如果不是,也许 BluetoothDevice.createInsecureRfcommSocketToServiceRecord() 是合适的调用?

回答by ecoe

Following the recommendations already posted, here is how I was able to get your code working as I expect you wanted it to:

按照已经发布的建议,以下是我如何让您的代码按照您希望的方式工作:

? ?

? ?

import bluetooth
? ? 
? ? name="bt_server"
? ? target_name="test"
? ? # some random uuid, generated by https://www.famkruithof.net/uuid/uuidgen
? ? uuid="0fee0450-e95f-11e5-a837-0800200c9a66"
? ? 
? ? def runServer():
? ? ? ? # you had indentation problems on this line:
? ? ? ? serverSocket=bluetooth.BluetoothSocket(bluetooth.RFCOMM )
? ? ? ? port=bluetooth.PORT_ANY
? ? ? ? serverSocket.bind(("",port))
? ? ? ? print "Listening for connections on port: ", port???

? ? ? ? # wait for a message to be sent to this socket only once
? ? ? ? serverSocket.listen(1)
? ? ? ? port=serverSocket.getsockname()[1]
? ? 
? ? ? ? # you were 90% there, just needed to use the pyBluez command:
? ? ? ? bluetooth.advertise_service( serverSocket, "SampleServer",
? ? ? ? ? ? ? ? ? ? ? ? ???service_id = uuid,
? ? ? ? ? ? ? ? ? ? ? ? ???service_classes = [ uuid, bluetooth.SERIAL_PORT_CLASS ],
? ? ? ? ? ? ? ? ? ? ? ? ???profiles = [ bluetooth.SERIAL_PORT_PROFILE ] 
? ? ? ? ? ? ? ? ? ? ? ? ? ? )
? ? 
? ? ? ? inputSocket, address=serverSocket.accept()
? ? ? ? print "Got connection with" , address
? ? ? ? data=inputSocket.recv(1024)
? ? ? ? print "received [%s] \n " % data? ? 
? ? ? ? inputSocket.close()
? ? ? ? serverSocket.close()? 
? ? 
? ? runServer()? 

Run from the command line, that code will wait forever until a message is sent via bluetooth. So, with that code running, all you have to do is connect your Android device via bluetooth, and then have the device send data (with reference to the same uuid as above) via either the Android app method you were developing or something like this gist (that I used): https://gist.github.com/tito/7432757

从命令行运行,该代码将永远等待,直到通过蓝牙发送消息。因此,运行该代码后,您所要做的就是通过蓝牙连接您的 Android 设备,然后让设备通过您正在开发的 Android 应用程序方法或类似的方法发送数据(参考与上述相同的 uuid)要点(我用过的):https: //gist.github.com/tito/7432757