自动连接到 Android 上的配对蓝牙设备

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10732252/
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-08-20 04:47:40  来源:igfitidea点击:

Auto connecting to Paired Bluetooth devices on Android

androidbluetooth

提问by zmashiah

I want to connect my Android Phone (2.3.6 Samsung Note) to an embedded Bluetooth device (RN-42 BT UART module on Arduino). Started with BluetoothChat example and have the embedded device paired with the phone. So far all seems to work fine, the devices get connected and data is passed from Android to embedded device. What I am still missing is to make the devices connect automatically once the two are in range.

我想将我的 Android 手机(2.3.6 三星 Note)连接到嵌入式蓝牙设备(Arduino 上的 RN-42 BT UART 模块)。从 BluetoothChat 示例开始,并将嵌入式设备与手机配对。到目前为止,一切似乎都运行良好,设备已连接并且数据从 Android 传递到嵌入式设备。我仍然缺少的是一旦两者在范围内就使设备自动连接。

Using the debugger I see the embedded device is "Host" or in it's term "Slave" and the Android being a client, as the Android issuing a connect request.

使用调试器,我看到嵌入式设备是“主机”或术语“从设备”,而 Android 是客户端,因为 Android 发出连接请求。

回答by Avi

I have a similar configuration (Android Galaxy S3 phone 4.0 and RN-42 BT connected to Arduino Uno) I am able to pair the Android and the bluetooth and to connect from the Android to the RN-42 BT (I am using the BlueTerm app to test that) However, I'm unable to connect from the RN-42 BT to the Android phone. I followed the innstructions and the code example in: http://www.instructables.com/id/Missed-calls-and-SMS-Notifier-Accessory/

我有一个类似的配置(Android Galaxy S3 手机 4.0 和 RN-42 BT 连接到 Arduino Uno)我能够将 Android 和蓝牙配对并从 Android 连接到 RN-42 BT(我正在使用 BlueTerm 应用程序来测试)但是,我无法从 RN-42 BT 连接到 Android 手机。我按照以下说明和代码示例进行操作:http: //www.instructables.com/id/Missed-calls-and-SMS-Notifier-Accessory/

I programmed the 42 BT to serve as a client and set it to Auto connect mode (SR,3). In my Android code, the BluetoothSerialService (equivalent to the PhoneInfoServer example code) is stuck in the AcceptThread on: socket = mmServerSocket.accept(); I'm attaching the following pieces of codes that are related to the connection problem:

我将 42 BT 编程为客户端并将其设置为自动连接模式 (SR,3)。在我的Android代码中,BluetoothSerialService(相当于PhoneInfoServer示例代码)卡在了AcceptThread上:socket = mmServerSocket.accept(); 我附上了以下与连接问题相关的代码:

  1. Arduino code that sets the connection mode to auto and initiates a connection with the Android phone
  2. Android BluetoothSerialService AcceptThread code that listens to incoming connection
  3. logcat messages that show that the code is stuck waiting for incoming connection
  1. 将连接模式设置为自动并启动与 Android 手机连接的 Arduino 代码
  2. Android BluetoothSerialService AcceptThread 侦听传入连接的代码
  3. 显示代码卡在等待传入连接的 logcat 消息

In Google's BluetoothChat demo app there is an option to make the phone discoverable so that another phone can connect to it. I am looking for something similar for bluetooth serial connection. I looked for an app on Google Play that will test listenning to an incoming connection request from a bluetooth serial device, but didn't find such an app. Does someone know of such an app?

在 Google 的 BluetoothChat 演示应用程序中,有一个选项可以让手机被发现,以便另一部手机可以连接到它。我正在寻找类似于蓝牙串行连接的东西。我在 Google Play 上寻找了一个应用程序,该应用程序将测试侦听来自蓝牙串行设备的传入连接请求,但没有找到这样的应用程序。有人知道这样的应用程序吗?

Regards, Avner

问候, 阿夫纳

  1. Arduino code that sets the connection mode to auto and initiates a connection with the Android phone

    void setup() {        
      Serial.begin(115200);
    
      Serial.println("BEG setup");
    
      static const char *initString0 = "$$$SR,04FE3144A0A4\r";
    
      // R,1 Forces a complete reboot of the device (similar to a power cycle).
      static const char initString1a[] = "$$$";
      static const char initString1b[] = "R,1\r";
    
      // auto
      static const char initString2a[] = "$$$";
      static const char initString2b[] = "SM,3\rSO,Z\r---\r";
      static const char *initVector[] = { initString0, initString1a, initString1b, initString2a, initString2b, NULL };
    
      int i;
    
      for (i=0; initVector[i] != NULL; i++) {
          Serial.print(initVector[i]);
          delay(500);
      }
    
      Serial.println("Setup completed");        
    }
    
  2. Android BluetoothSerialService AcceptThreadcode that listens to incoming connection

    // ...
        private class AcceptThread extends Thread
        {
            // The local server socket
        static private final String TAG = "BluetoothSerialServiceAcceptThread";
            private final BluetoothServerSocket mmServerSocket;
            private String mSocketType;
    
    
            /** Creates an thread for accepting incoming Bluetooth connections
             * @param secure    Currently ignored, but suppose to represent the mode of socket.
             * All communication is currently done over insecure socket 
             */
            public AcceptThread(boolean secure) {
                Log.i(TAG, "BEG AcceptThread::AcceptThread");
    
                BluetoothServerSocket tmp = null;
                mSocketType = secure ? "Secure":"Insecure";
    
                // Create a new listening server socket
                try {
                Log.i(TAG, "AcceptThread constructor trying to create listening socket");
    
                    if (!secure) {
                        // This is for Android 2.2
                        // tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_INSECURE, BT_SPP_UUID);
    
                        // This is for Android 2.3 but testing the above on 2.3 device showed it to be working.
                        tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, BT_SPP_UUID);
                    }
    
                    Log.d(TAG, "AcceptThread: Listening BT Socket " + mSocketType + " created");
                }
                catch (IOException e)
                {
                    Log.e(TAG, "AcceptThread: Listening BT Socket Type: " + mSocketType + " listen() failed " + e.getMessage());
                    acceptProblem();
                }
                mmServerSocket = tmp;
    
                Log.d(TAG, "mmServerSocket: " + mmServerSocket);
    
            } // public AcceptThread
    
    
            public void run() {             
                Log.i(TAG, "BEG BluetoothSerialService::run");
    
                if (mmServerSocket == null)
                {
                Log.e(TAG, "AcceptThread.run: No server socket");
                return;
                }
    
                Log.d(TAG, "AcceptThread.run: socket type:" + mSocketType);
                setName("AcceptThread" + mSocketType);
    
                BluetoothSocket socket = null;
    
                Log.i(TAG, "mState: " + mState);
    
                // Listen to the server socket if we're not connected
                while (mState != STATE_CONNECTED)
                {
                    Log.i(TAG, "socket before mmServerSocket.accept(): " + socket);
    
                    try
                    {
                        // This is a blocking call and will only return on a
                        // successful connection or an exception
                        socket = mmServerSocket.accept();
                        Log.d(TAG, "AcceptThread.run: returned from accept");
                    }
                    catch (IOException e)
                    {
                        Log.e(TAG, "AcceptThread.run: Socket Type: " + mSocketType + "accept() failed " + e.getMessage());
                        break;
                    }
    
                    Log.i(TAG, "socket after mmServerSocket.accept(): " + socket);
    //...
    
  3. logcat messages that show that the code is stuck waiting for incoming connection

        // ...
    12-09 01:04:38.765: I/BluetoothSerialServiceAcceptThread(16175): BEG AcceptThread::AcceptThread
    12-09 01:04:38.765: I/BluetoothSerialServiceAcceptThread(16175): AcceptThread constructor trying to create listening socket
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): initSocketNative
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): ...fd 49 created (RFCOMM, lm = 0)
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): initSocketFromFdNative
    12-09 01:04:38.775: D/BluetoothUtils(16175): isSocketAllowedBySecurityPolicy start : device null
    12-09 01:04:38.775: V/BluetoothSocket.cpp(16175): bindListenNative
    12-09 01:04:38.775: V/BluetoothSocket.cpp(16175): ...bindListenNative(49) success
    12-09 01:04:38.785: D/BluetoothSerialServiceAcceptThread(16175): AcceptThread: Listening BT Socket Insecure created
    12-09 01:04:38.785: D/BluetoothSerialServiceAcceptThread(16175): mmServerSocket: android.bluetooth.BluetoothServerSocket@41af72c8
    12-09 01:04:38.785: D/BluetoothReadService(16175): END start
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): BEG BluetoothSerialService::run
    12-09 01:04:38.795: D/BluetoothSerialServiceAcceptThread(16175): AcceptThread.run: socket type:Insecure
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): mState: 1
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): socket before mmServerSocket.accept(): null
    12-09 01:04:38.795: V/BluetoothSocket.cpp(16175): acceptNative
    12-09 01:04:38.855: I/MainActivity(16175): mBtStatus: android.widget.ImageView@41adc698
    12-09 01:04:38.855: I/MainActivity(16175): In case: BluetoothSerialService.STATE_LISTEN
    12-09 01:04:38.855: D/MainActivity(16175): Beg onCreateOptionsMenu
    12-09 01:04:38.885: D/memalloc(16175): ion: Mapped buffer base:0x5d760000 size:3768320 offset:0 fd:57
    12-09 01:04:38.925: D/CLIPBOARD(16175): Hide Clipboard dialog at Starting input: finished by someone else... !
    // ...
    
  1. 将连接模式设置为自动并启动与 Android 手机连接的 Arduino 代码

    void setup() {        
      Serial.begin(115200);
    
      Serial.println("BEG setup");
    
      static const char *initString0 = "$$$SR,04FE3144A0A4\r";
    
      // R,1 Forces a complete reboot of the device (similar to a power cycle).
      static const char initString1a[] = "$$$";
      static const char initString1b[] = "R,1\r";
    
      // auto
      static const char initString2a[] = "$$$";
      static const char initString2b[] = "SM,3\rSO,Z\r---\r";
      static const char *initVector[] = { initString0, initString1a, initString1b, initString2a, initString2b, NULL };
    
      int i;
    
      for (i=0; initVector[i] != NULL; i++) {
          Serial.print(initVector[i]);
          delay(500);
      }
    
      Serial.println("Setup completed");        
    }
    
  2. BluetoothSerialService AcceptThread侦听传入连接的Android代码

    // ...
        private class AcceptThread extends Thread
        {
            // The local server socket
        static private final String TAG = "BluetoothSerialServiceAcceptThread";
            private final BluetoothServerSocket mmServerSocket;
            private String mSocketType;
    
    
            /** Creates an thread for accepting incoming Bluetooth connections
             * @param secure    Currently ignored, but suppose to represent the mode of socket.
             * All communication is currently done over insecure socket 
             */
            public AcceptThread(boolean secure) {
                Log.i(TAG, "BEG AcceptThread::AcceptThread");
    
                BluetoothServerSocket tmp = null;
                mSocketType = secure ? "Secure":"Insecure";
    
                // Create a new listening server socket
                try {
                Log.i(TAG, "AcceptThread constructor trying to create listening socket");
    
                    if (!secure) {
                        // This is for Android 2.2
                        // tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_INSECURE, BT_SPP_UUID);
    
                        // This is for Android 2.3 but testing the above on 2.3 device showed it to be working.
                        tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, BT_SPP_UUID);
                    }
    
                    Log.d(TAG, "AcceptThread: Listening BT Socket " + mSocketType + " created");
                }
                catch (IOException e)
                {
                    Log.e(TAG, "AcceptThread: Listening BT Socket Type: " + mSocketType + " listen() failed " + e.getMessage());
                    acceptProblem();
                }
                mmServerSocket = tmp;
    
                Log.d(TAG, "mmServerSocket: " + mmServerSocket);
    
            } // public AcceptThread
    
    
            public void run() {             
                Log.i(TAG, "BEG BluetoothSerialService::run");
    
                if (mmServerSocket == null)
                {
                Log.e(TAG, "AcceptThread.run: No server socket");
                return;
                }
    
                Log.d(TAG, "AcceptThread.run: socket type:" + mSocketType);
                setName("AcceptThread" + mSocketType);
    
                BluetoothSocket socket = null;
    
                Log.i(TAG, "mState: " + mState);
    
                // Listen to the server socket if we're not connected
                while (mState != STATE_CONNECTED)
                {
                    Log.i(TAG, "socket before mmServerSocket.accept(): " + socket);
    
                    try
                    {
                        // This is a blocking call and will only return on a
                        // successful connection or an exception
                        socket = mmServerSocket.accept();
                        Log.d(TAG, "AcceptThread.run: returned from accept");
                    }
                    catch (IOException e)
                    {
                        Log.e(TAG, "AcceptThread.run: Socket Type: " + mSocketType + "accept() failed " + e.getMessage());
                        break;
                    }
    
                    Log.i(TAG, "socket after mmServerSocket.accept(): " + socket);
    //...
    
  3. 显示代码卡在等待传入连接的 logcat 消息

        // ...
    12-09 01:04:38.765: I/BluetoothSerialServiceAcceptThread(16175): BEG AcceptThread::AcceptThread
    12-09 01:04:38.765: I/BluetoothSerialServiceAcceptThread(16175): AcceptThread constructor trying to create listening socket
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): initSocketNative
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): ...fd 49 created (RFCOMM, lm = 0)
    12-09 01:04:38.765: V/BluetoothSocket.cpp(16175): initSocketFromFdNative
    12-09 01:04:38.775: D/BluetoothUtils(16175): isSocketAllowedBySecurityPolicy start : device null
    12-09 01:04:38.775: V/BluetoothSocket.cpp(16175): bindListenNative
    12-09 01:04:38.775: V/BluetoothSocket.cpp(16175): ...bindListenNative(49) success
    12-09 01:04:38.785: D/BluetoothSerialServiceAcceptThread(16175): AcceptThread: Listening BT Socket Insecure created
    12-09 01:04:38.785: D/BluetoothSerialServiceAcceptThread(16175): mmServerSocket: android.bluetooth.BluetoothServerSocket@41af72c8
    12-09 01:04:38.785: D/BluetoothReadService(16175): END start
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): BEG BluetoothSerialService::run
    12-09 01:04:38.795: D/BluetoothSerialServiceAcceptThread(16175): AcceptThread.run: socket type:Insecure
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): mState: 1
    12-09 01:04:38.795: I/BluetoothSerialServiceAcceptThread(16175): socket before mmServerSocket.accept(): null
    12-09 01:04:38.795: V/BluetoothSocket.cpp(16175): acceptNative
    12-09 01:04:38.855: I/MainActivity(16175): mBtStatus: android.widget.ImageView@41adc698
    12-09 01:04:38.855: I/MainActivity(16175): In case: BluetoothSerialService.STATE_LISTEN
    12-09 01:04:38.855: D/MainActivity(16175): Beg onCreateOptionsMenu
    12-09 01:04:38.885: D/memalloc(16175): ion: Mapped buffer base:0x5d760000 size:3768320 offset:0 fd:57
    12-09 01:04:38.925: D/CLIPBOARD(16175): Hide Clipboard dialog at Starting input: finished by someone else... !
    // ...
    

I further discovered that the RN-42 BT is getting into auto-connect mode but tries to connect to another non-android LG phone at the house.

我进一步发现 RN-42 BT 正在进入自动连接模式,但尝试连接到家里的另一部非安卓 LG 手机。

I discovered this by reseting the RN-42 BT to the factory defaults. Using the BlueTerm app I successfully connect from the Android phone to the RN-42 BT. When I perform an inquiry scan ($$$I\r) I get the mac address and the name of the LG phone. This phone has a bluetooth with a different mac address (0026e25d8a91) - I don't know what causes the RN-42 BT to try and connect with this device.

我通过将 RN-42 BT 重置为出厂默认设置发现了这一点。使用 BlueTerm 应用程序,我成功地从 Android 手机连接到 RN-42 BT。当我执行查询扫描 ($$$I\r) 时,我会得到 LG 手机的 mac 地址和名称。这款手机的蓝牙具有不同的 mac 地址 (0026e25d8a91) - 我不知道是什么导致 RN-42 BT 尝试与此设备连接。

This means that the auto connect mode does work but the connection is directed to the wrong phone. I'm pazzled because I'm specifying the mac address of the Android phone using the following commands (with delays between them)

这意味着自动连接模式确实有效,但连接被定向到错误的手机。我很困惑,因为我正在使用以下命令指定 Android 手机的 mac 地址(它们之间有延迟)

// The mac address of the android phone
$$$SR,04FE3144A0A4\r

// Force a complete reboot of the device (similar to a power cycle).
$$$R,1\r

// SM,3 - mode=auto
// SO,Z - Extended Status String, Setting this string enables status messages to be sent to the local serial port.
// --- - exit command mode (three minus signs).
$$$SM,3\rSO,Z\r---\r

I am now thinking that the connection initiation from the RN-42 BT is Ok but that the BluetoothServerSocket on the android code is not set up properly.
I have tried setting the BluetoothServerSocket to listen using listenUsingInsecureRfcommWithServiceRecord and listenUsingRfcommWithServiceRecord. I notice that there is a command createInsecureRfcommSocketToServiceRecord. Should I use it instead?

我现在认为从 RN-42 BT 发起的连接是好的,但是 android 代码上的 BluetoothServerSocket 设置不正确。
我曾尝试使用 listenUsingInsecureRfcommWithServiceRecord 和 listenUsingRfcommWithServiceRecord 设置 BluetoothServerSocket 进行侦听。我注意到有一个命令 createInsecureRfcommSocketToServiceRecord。我应该改用它吗?

Any advice would be greatly appreciated.

任何建议将不胜感激。

Thanks, Avner

谢谢,阿夫纳

回答by zmashiah

So I figured out the "trick". First the mobile phone is set to only Accept connections and the embedded device which has line power to auto-connect. The change was to set the embedded device from "Host" mode to "Client" mode with auto-connect.

所以我想出了“技巧”。首先将手机设置为仅接受连接和具有线路电源的嵌入式设备自动连接。更改是将嵌入式设备从“主机”模式设置为具有自动连接的“客户端”模式。

Next obstacle was the Android had to have the Accept code in a service otherwise that connection would only work if the application was made active. With putting the Accept piece of code into a service the application can be non-active and the embedded accessory would auto connect. Code will be shared in Instructable: enter link description here

下一个障碍是 Android 必须在服务中包含 Accept 代码,否则只有在应用程序处于活动状态时该连接才能工作。通过将 Accept 代码段放入服务中,应用程序可以处于非活动状态,嵌入式附件将自动连接。代码将在 Instructable 中共享:在此处输入链接描述

回答by zmashiah

Complete code and instructions in: http://www.instructables.com/id/Missed-calls-and-SMS-Notifier-Accessory/

完整代码和说明位于:http: //www.instructables.com/id/Missed-calls-and-SMS-Notifier-Accessory/

It includes not only the code but also explanation on how it works and assembly description.

它不仅包括代码,还包括它如何工作的解释和程序集描述。