android - 蓝牙:程序卡在 connect() 方法

标签 android multithreading bluetooth connect

我正在编写一个简单的蓝牙客户端,通过 RFCOMM 作为串行端口发送和接收文本消息。我查看了 Android SDK 教程并以相同的方式完成了它:一个 Activity 调用一个线程来建立连接,完成后,另一个线程负责消息接收。

我正在尝试连接到 Parallax EasyBluetooth。计算机和 EasyBT 之间以及基于 Java 的移动设备和 EasyBT 之间的连接都可以正常工作。所以问题一定出在代码上,或者我希望不是在 Android 移动蓝牙芯片上。无论如何它会打开和关闭,并在扫描时检测到其他设备,所以我想问题只是我的编码。

问题是代码卡在了 connect() 方法处。那么让我们看看是否有人知道原因。

Activity 的 XML 很简单:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<Button 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/boton"
    android:id="@+id/boton_enviar"
    />
</LinearLayout>

当然我已经给Manifiest添加了蓝牙权限:

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

代码如下:

package uniovi.PFC;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;

public class PruebaBTActivity extends Activity {
    private String TAG = "pruebaBT";
    private BluetoothAdapter mBluetoothAdapter;
    private Map<String, BluetoothDevice> mArrayAdapter;
    private ConnectedThread hiloEscuchas;
    private ConnectThread hiloConectando;
    private Handler mHandler;
    private Button botonEnviar;
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    private static final int REQUEST_ENABLE_BT = 1;
    private static final int MESSAGE_READ = 1;
    private byte bytes_enviar[];
    private String cmd;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.d(TAG, "On create abriendo");

        mArrayAdapter = new HashMap<String, BluetoothDevice>();

        botonEnviar = (Button)findViewById(R.id.boton_enviar);
        botonEnviar.setEnabled(false);
        botonEnviar.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                 cmd = "A";
                 bytes_enviar = cmd.getBytes();
                 hiloEscuchas.write(bytes_enviar);
            }
        });
        Log.d(TAG, "On create cerrando");
    }

    @Override

    public void onResume() {
        super.onResume();
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Log.d(TAG, "Device does not support Bluetooth");
        }
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
        }

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.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
                 mArrayAdapter.put(device.getName(), device);
             }
         }

         BluetoothDevice device = mArrayAdapter.get("EasyBT");
         hiloConectando = new ConnectThread(device);
         hiloConectando.run();
         //while(hiloEscuchas.isConnected()==false);
         //botonEnviar.setEnabled(true);
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) { }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            mBluetoothAdapter.cancelDiscovery();

            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and get out
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }

            // Do work to manage the connection (in a separate thread)
            hiloEscuchas = new ConnectedThread(mmSocket);
            hiloEscuchas.run();
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private boolean conectado;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            conectado = false;
            mHandler = new Handler();

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            conectado = true;
        }

        public boolean isConnected(){
            return conectado;
        }

        public void run() {
            byte[] buffer = new byte[1024];  // buffer store for the stream
            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {

                    cmd = "A";
                    bytes_enviar = cmd.getBytes();
                    hiloEscuchas.write(bytes_enviar);
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI Activity
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();

                } catch (IOException e) {
                    break;
                }
            }
        }

        /* Call this from the main Activity to send data to the remote device */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) { }
        }

        /* Call this from the main Activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }


         }
        }
    }

有一些代码可以对设备进行蓝牙扫描,但为了在它工作之前让事情变得简单,我将 MAC 地址手动写入一个变量。评论解释了这一点,并显示了它卡在什么地方。

谢谢

最佳答案

我认为这些至少导致了您的部分问题:

hiloConectando = new ConnectThread(device);
hiloConectando.run();

hiloEscuchas = new ConnectedThread(mmSocket);
hiloEscuchas.run();

您应该调用 start(),而不是 run(),例如:

hiloConectando = new ConnectThread(device);
hiloConectando.start();

关于android - 蓝牙:程序卡在 connect() 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7603221/

相关文章:

c# - 无法从后台运行的进程中读取 STDOut

iOS 7 蓝牙输出不适用于 AVAudioSessionCategoryPlayAndRecord

android - Google Play 的隐私政策链接

java - Android给ImageView添加边框图片

android - 获取用于从 Android 设备连接到 Firebase 的 IP 地址

java - 在java中使用多线程调用同一类的不同方法

java - 安卓应用程序: How do I create a directory in the internal storage

Java 同步块(synchronized block)和匿名类

java - reduce 操作中并行流的同步问题

android - 读取 .NET 流 : high CPU usage - how to read wihtout while (true)?