Android BlueTooth蓝牙通信

来源:互联网 发布:淘宝新品上架装修 编辑:程序博客网 时间:2024/06/10 08:53

最近在做蓝牙有关的项目,参考了下系统的Demo,分享一下学习笔记和心得。

1、想用蓝牙首先Manifest申请个权限

      第一行是 发现去他设备权限

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


2、用BluetoothChatService.java封装蓝牙用到的方法,连接、接收数据,

       线程AcceptThread线程用于接收socket

               ConnectThread用于连接设备

               ConnectedThread用于连接后数据的收发

       系统自带的模式很好,按照这个拓展就可以了,直接把UUID修改一下,生成一个对象就可以使用了。

public class BluetoothChatService {    // Debugging    private static final String TAG = "DeviceListActivity";    private static final boolean D = true;    // Name for the SDP record when creating server socket    private static final String NAME = "BluetoothChat";    // Unique UUID for this application //    // private static final UUID MY_UUID =    // UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");    private static final UUID MY_UUID = UUID    .fromString("
12c3b3d2-afac-11de-8a39-0822130c2366
"); // SerialPortService // Member fields private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int mState; // Constants that indicate the current connection state public static final int STATE_NONE = 0; // we're doing nothing public static final int STATE_LISTEN = 1; // now listening for incoming connections public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection public static final int STATE_CONNECTED = 3; // now connected to a remote device /** * Constructor. Prepares a new BluetoothChat session. * @param context The UI Activity Context * @param handler A Handler to send messages back to the UI Activity */ public BluetoothChatService(Context context, Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } /** * Set the current state of the chat connection * @param state An integer defining the current connection state */ private synchronized void setState(int state) { if (D) Log.d(TAG, "setState() " + mState + " -> " + state); mState = state; // Give the new state to the Handler so the UI Activity can update mHandler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } /** * Return the current connection state. */ public synchronized int getState() { return mState; } /** * Start the chat service. Specifically start AcceptThread to begin a * session in listening (server) mode. Called by the Activity onResume() */ public synchronized void start() { if (D) Log.d(TAG, "start"); // Cancel any thread attempting to make a connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Start the thread to listen on a BluetoothServerSocket if (mAcceptThread == null) { mAcceptThread = new AcceptThread(); mAcceptThread.start(); } setState(STATE_LISTEN); } /** * Start the ConnectThread to initiate a connection to a remote device. * @param device The BluetoothDevice to connect */ public synchronized void connect(BluetoothDevice device) { if (D) Log.d(TAG, "connect to: " + device); // Cancel any thread attempting to make a connection if (mState == STATE_CONNECTING) { if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} } // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Start the thread to connect with the given device mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(STATE_CONNECTING); } /** * Start the ConnectedThread to begin managing a Bluetooth connection * @param socket The BluetoothSocket on which the connection was made * @param device The BluetoothDevice that has been connected */ public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { if (D) Log.d(TAG, "connected"); // Cancel the thread that completed the connection if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} // Cancel any thread currently running a connection if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} // Cancel the accept thread because we only want to connect to one device if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} // Start the thread to manage the connection and perform transmissions mConnectedThread = new ConnectedThread(socket); mConnectedThread.start(); // Send the name of the connected device back to the UI Activity Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME); Bundle bundle = new Bundle(); bundle.putString(MainActivity.DEVICE_NAME, device.getName()); msg.setData(bundle); mHandler.sendMessage(msg); setState(STATE_CONNECTED); } /** * Stop all threads */ public synchronized void stop() { if (D) Log.d(TAG, "stop"); if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} setState(STATE_NONE); } /** * Write to the ConnectedThread in an unsynchronized manner * @param out The bytes to write * @see ConnectedThread#write(byte[]) */ public void write(byte[] out) { // Create temporary object ConnectedThread r; // Synchronize a copy of the ConnectedThread synchronized (this) { if (mState != STATE_CONNECTED) return; r = mConnectedThread; } // Perform the write unsynchronized r.write(out); } /** * Indicate that the connection attempt failed and notify the UI Activity. */ private void connectionFailed() { setState(STATE_LISTEN); // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); Bundle bundle = new Bundle();// bundle.putString(BluetoothChat.TOAST, "Unable to connect device"); bundle.putString(MainActivity.TOAST, "�豸����ʧ��"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * Indicate that the connection was lost and notify the UI Activity. */ private void connectionLost() { setState(STATE_LISTEN); // Send a failure message back to the Activity Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); Bundle bundle = new Bundle();// bundle.putString(BluetoothChat.TOAST, "Device connection was lost"); msg.setData(bundle); mHandler.sendMessage(msg); } /** * This thread runs while listening for incoming connections. It behaves * like a server-side client. It runs until a connection is accepted * (or until cancelled). */ private class AcceptThread extends Thread { // The local server socket private final BluetoothServerSocket mmServerSocket; public AcceptThread() { BluetoothServerSocket tmp = null; // Create a new listening server socket try { tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { Log.e(TAG, "listen() failed", e); } mmServerSocket = tmp; } public void run() { if (D) Log.d(TAG, "BEGIN mAcceptThread" + this); setName("AcceptThread"); BluetoothSocket socket = null; // Listen to the server socket if we're not connected while (mState != STATE_CONNECTED) { try { // This is a blocking call and will only return on a // successful connection or an exception socket = mmServerSocket.accept(); } catch (IOException e) { Log.e(TAG, "accept() failed", e); break; } // If a connection was accepted if (socket != null) { synchronized (BluetoothChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: // Situation normal. Start the connected thread. connected(socket, socket.getRemoteDevice()); break; case STATE_NONE: case STATE_CONNECTED: // Either not ready or already connected. Terminate new socket. try { socket.close(); } catch (IOException e) { Log.e(TAG, "Could not close unwanted socket", e); } break; } } } } if (D) Log.i(TAG, "END mAcceptThread"); } public void cancel() { if (D) Log.d(TAG, "cancel " + this); try { mmServerSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of server failed", e); } } } /** * This thread runs while attempting to make an outgoing connection * with a device. It runs straight through; the connection either * succeeds or fails. */ private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null; // Get a BluetoothSocket for a connection with the // given BluetoothDevice try { tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { Log.e(TAG, "create() failed", e); } mmSocket = tmp; } public void run() { Log.i(TAG, "BEGIN mConnectThread"); setName("ConnectThread"); // Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery(); // Make a connection to the BluetoothSocket try { // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); } catch (IOException e) { connectionFailed(); // Close the socket try { mmSocket.close(); } catch (IOException e2) { Log.e(TAG, "unable to close() socket during connection failure", e2); } // Start the service over to restart listening mode BluetoothChatService.this.start(); return; } // Reset the ConnectThread because we're done synchronized (BluetoothChatService.this) { mConnectThread = null; } // Start the connected thread connected(mmSocket, mmDevice); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } } /** * This thread runs during a connection with a remote device. * It handles all incoming and outgoing transmissions. */ private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { Log.d(TAG, "create ConnectedThread"); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the BluetoothSocket input and output streams try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "temp sockets not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; // Keep listening to the InputStream while connected while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI Activity mHandler.obtainMessage(MainActivity.MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "disconnected", e); connectionLost(); break; } } } /** * Write to the connected OutStream. * @param buffer The bytes to write */ public void write(byte[] buffer) { try { mmOutStream.write(buffer); // Share the sent message back to the UI Activity mHandler.obtainMessage(MainActivity.MESSAGE_WRITE, -1, -1, buffer) .sendToTarget(); } catch (IOException e) { Log.e(TAG, "Exception during write", e); } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } } }

3、发现设备很简单,去查看API文档BluetoothAdapter.getBondedDevices(),获取Device之后把名字MAC用List写出来就好了,不罗嗦,上代码
public class DeviceListActivity extends Activity {    // Debugging    private static final String TAG = "DeviceListActivity";    private static final boolean D = true;    // Return Intent extra    public static String EXTRA_DEVICE_ADDRESS = "device_address";    // Member fields    private BluetoothAdapter mBtAdapter;    private ArrayAdapter<String> mPairedDevicesArrayAdapter;    private ArrayAdapter<String> mNewDevicesArrayAdapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // Setup the window        requestWindowFeature(Window.FEATURE_NO_TITLE);        setContentView(R.layout.device_list);        // Set result CANCELED incase the user backs out        setResult(Activity.RESULT_CANCELED);/**  wpx delete  for: del scan device        // Initialize the button to perform device discovery        Button scanButton = (Button) findViewById(R.id.button_scan);        scanButton.setOnClickListener(new OnClickListener() {            public void onClick(View v) {                doDiscovery();                v.setVisibility(View.GONE);            }        });*/        // Initialize array adapters. One for already paired devices and        // one for newly discovered devices        mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);        mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);        // Find and set up the ListView for paired devices        ListView pairedListView = (ListView) findViewById(R.id.paired_devices);        pairedListView.setAdapter(mPairedDevicesArrayAdapter);        pairedListView.setOnItemClickListener(mDeviceClickListener);        // Find and set up the ListView for newly discovered devices        ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);        newDevicesListView.setAdapter(mNewDevicesArrayAdapter);        newDevicesListView.setOnItemClickListener(mDeviceClickListener);        // Register for broadcasts when a device is discovered        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);        this.registerReceiver(mReceiver, filter);        // Register for broadcasts when discovery has finished        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);        this.registerReceiver(mReceiver, filter);        // Get the local Bluetooth adapter        mBtAdapter = BluetoothAdapter.getDefaultAdapter();        // Get a set of currently paired devices        Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();        // If there are paired devices, add each one to the ArrayAdapter        if (pairedDevices.size() > 0) {            findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);            for (BluetoothDevice device : pairedDevices) {                mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());            }        } else {            String noDevices = getResources().getText(R.string.none_paired).toString();            mPairedDevicesArrayAdapter.add(noDevices);        }    }    @Override    protected void onDestroy() {        super.onDestroy();        // Make sure we're not doing discovery anymore        if (mBtAdapter != null) {            mBtAdapter.cancelDiscovery();        }        // Unregister broadcast listeners        this.unregisterReceiver(mReceiver);    }    /**     * Start device discover with the BluetoothAdapter     */    private void doDiscovery() {        if (D) Log.d(TAG, "doDiscovery()");        // Indicate scanning in the title        setProgressBarIndeterminateVisibility(true);        //setTitle(R.string.scanning);        // Turn on sub-title for new devices        findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);        // If we're already discovering, stop it        if (mBtAdapter.isDiscovering()) {            mBtAdapter.cancelDiscovery();        }        // Request discover from BluetoothAdapter        mBtAdapter.startDiscovery();    }    // The on-click listener for all devices in the ListViews    private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {        public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) {            // Cancel discovery because it's costly and we're about to connect            mBtAdapter.cancelDiscovery();            // Get the device MAC address, which is the last 17 chars in the View            String info = ((TextView) v).getText().toString();            String address = info.substring(info.length() - 17);            String devicename = info.substring(0,info.length() - 18);            if(devicename.equals("BlackBoxs")){            // Create the result Intent and include the MAC address            Intent intent = new Intent();            Log.e("wpx---DeviceListActivity", "wpx===="+address);            intent.putExtra(EXTRA_DEVICE_ADDRESS, address);            // Set result and finish this Activity            setResult(Activity.RESULT_OK, intent);            finish();            }else {         //ֻ��BlackBox�豸��������        Toast.makeText(getApplicationContext(),"����ʧ��", Toast.LENGTH_SHORT).show();        Toast.makeText(getApplicationContext(),"������BlackBoxs�豸", Toast.LENGTH_LONG).show();            }        }    };    // The BroadcastReceiver that listens for discovered devices and    // changes the title when discovery is finished    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            // When discovery finds a device            if (BluetoothDevice.ACTION_FOUND.equals(action)) {                // Get the BluetoothDevice object from the Intent                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);                // If it's already paired, skip it, because it's been listed already                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {                    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());                }            // When discovery is finished, change the Activity title            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {                setProgressBarIndeterminateVisibility(false);                //setTitle(R.string.select_device);                if (mNewDevicesArrayAdapter.getCount() == 0) {                    String noDevices = getResources().getText(R.string.none_found).toString();                    mNewDevicesArrayAdapter.add(noDevices);                }            }        }    };


4、剩下的就是使用过了,在UI线程中实例化一个BluetoothChatService 的实例判断一下蓝牙的状态,就可以使用了

注意问题:(1)如果需要持续读取数据,需要写一个Service

                    (2)蓝牙需要先配对,如果是跟硬件连接需要注意数据格式

                      (3)在连接状态,无法更改硬件设备的名称密码;更改密码后需要重新    BlueToothAdapter.startDiscovery();扫描一遍才能生产效率


附上下载地址:官方Demo下载地


原创粉丝点击