1.启动App后:
判断->蓝牙是否打开(所有功能必须在打牙打开的情况下才能用)
已打开: 启动代码中的蓝牙通讯Service
未打开: 发布 打开蓝牙意图(系统),根据Activity返回进场操作
打开成功,启动代码中的蓝牙通讯Service
用户点back或失败 退出App
2.蓝牙设备列表:
2.1显示已经配对列表:
注册蓝牙设备发现广播
广播中将发现的设备添加到列表
2.2当用户点Scan时,启动蓝牙发现,发现设备时会收到广播事件。
2.3用户点某个条目时,将改条目的 MAC返回给主Activity(调用了startActivityForResult的Activity)
3.使设备可发现
private void ensureDiscoverable() {Log.d(TAG, "ensure discoverable");if (mBluetoothAdapter.getScanMode() !=BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);}}
4.蓝牙socket操作
/** Copyright (C) 2009 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.example.android.BluetoothChat;import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID;import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.Context; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log;/*** This class does all the work for setting up and managing Bluetooth* connections with other devices. It has a thread that listens for* incoming connections, a thread for connecting with a device, and a* thread for performing data transmissions when connected.*/ public class BluetoothChatService {// Debuggingprivate static final String TAG = "BluetoothChatService";private static final boolean D = true;// Name for the SDP record when creating server socketprivate static final String NAME_SECURE = "BluetoothChatSecure";private static final String NAME_INSECURE = "BluetoothChatInsecure";// Unique UUID for this applicationprivate static final UUID MY_UUID_SECURE =UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");private static final UUID MY_UUID_INSECURE =UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");// Member fieldsprivate final BluetoothAdapter mAdapter;private final Handler mHandler;private AcceptThread mSecureAcceptThread;private AcceptThread mInsecureAcceptThread;private ConnectThread mConnectThread;private ConnectedThread mConnectedThread;private int mState;// Constants that indicate the current connection statepublic static final int STATE_NONE = 0; // we're doing nothingpublic static final int STATE_LISTEN = 1; // now listening for incoming connectionspublic static final int STATE_CONNECTING = 2; // now initiating an outgoing connectionpublic 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 updatemHandler.obtainMessage(BluetoothChat.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 connectionif (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}setState(STATE_LISTEN);// Start the thread to listen on a BluetoothServerSocketif (mSecureAcceptThread == null) {mSecureAcceptThread = new AcceptThread(true);mSecureAcceptThread.start();}if (mInsecureAcceptThread == null) {mInsecureAcceptThread = new AcceptThread(false);mInsecureAcceptThread.start();}}/*** Start the ConnectThread to initiate a connection to a remote device.* @param device The BluetoothDevice to connect* @param secure Socket Security type - Secure (true) , Insecure (false)*/public synchronized void connect(BluetoothDevice device, boolean secure) {if (D) Log.d(TAG, "connect to: " + device);// Cancel any thread attempting to make a connectionif (mState == STATE_CONNECTING) {if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}// Start the thread to connect with the given devicemConnectThread = new ConnectThread(device, secure);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, BluetoothDevicedevice, final String socketType) {if (D) Log.d(TAG, "connected, Socket Type:" + socketType);// Cancel the thread that completed the connectionif (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}// Cancel any thread currently running a connectionif (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}// Cancel the accept thread because we only want to connect to one deviceif (mSecureAcceptThread != null) {mSecureAcceptThread.cancel();mSecureAcceptThread = null;}if (mInsecureAcceptThread != null) {mInsecureAcceptThread.cancel();mInsecureAcceptThread = null;}// Start the thread to manage the connection and perform transmissionsmConnectedThread = new ConnectedThread(socket, socketType);mConnectedThread.start();// Send the name of the connected device back to the UI ActivityMessage msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);Bundle bundle = new Bundle();bundle.putString(BluetoothChat.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 (mSecureAcceptThread != null) {mSecureAcceptThread.cancel();mSecureAcceptThread = null;}if (mInsecureAcceptThread != null) {mInsecureAcceptThread.cancel();mInsecureAcceptThread = 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 ConnectedThreadsynchronized (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() {// Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);Bundle bundle = new Bundle();bundle.putString(BluetoothChat.TOAST, "Unable to connect device");msg.setData(bundle);mHandler.sendMessage(msg);// Start the service over to restart listening modeBluetoothChatService.this.start();}/*** Indicate that the connection was lost and notify the UI Activity.*/private void connectionLost() {// Send a failure message back to the ActivityMessage msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);Bundle bundle = new Bundle();bundle.putString(BluetoothChat.TOAST, "Device connection was lost");msg.setData(bundle);mHandler.sendMessage(msg);// Start the service over to restart listening modeBluetoothChatService.this.start();}/*** 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 socketprivate final BluetoothServerSocket mmServerSocket;private String mSocketType;public AcceptThread(boolean secure) {BluetoothServerSocket tmp = null;mSocketType = secure ? "Secure":"Insecure";// Create a new listening server sockettry {if (secure) {tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,MY_UUID_SECURE);} else {tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(NAME_INSECURE, MY_UUID_INSECURE);}} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);}mmServerSocket = tmp;}public void run() {if (D) Log.d(TAG, "Socket Type: " + mSocketType +"BEGIN mAcceptThread" + this);setName("AcceptThread" + mSocketType);BluetoothSocket socket = null;// Listen to the server socket if we're not connectedwhile (mState != STATE_CONNECTED) {try {// This is a blocking call and will only return on a// successful connection or an exceptionsocket = mmServerSocket.accept();} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);break;}// If a connection was acceptedif (socket != null) {synchronized (BluetoothChatService.this) {switch (mState) {case STATE_LISTEN:case STATE_CONNECTING:// Situation normal. Start the connected thread. connected(socket, socket.getRemoteDevice(),mSocketType);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, socket Type: " + mSocketType);}public void cancel() {if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);try {mmServerSocket.close();} catch (IOException e) {Log.e(TAG, "Socket Type" + mSocketType + "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;private String mSocketType;public ConnectThread(BluetoothDevice device, boolean secure) {mmDevice = device;BluetoothSocket tmp = null;mSocketType = secure ? "Secure" : "Insecure";// Get a BluetoothSocket for a connection with the// given BluetoothDevicetry {if (secure) {tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);} else {tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE);}} catch (IOException e) {Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);}mmSocket = tmp;}public void run() {Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);setName("ConnectThread" + mSocketType);// Always cancel discovery because it will slow down a connection mAdapter.cancelDiscovery();// Make a connection to the BluetoothSockettry {// This is a blocking call and will only return on a// successful connection or an exception mmSocket.connect();} catch (IOException e) {// Close the sockettry {mmSocket.close();} catch (IOException e2) {Log.e(TAG, "unable to close() " + mSocketType +" socket during connection failure", e2);}connectionFailed();return;}// Reset the ConnectThread because we're donesynchronized (BluetoothChatService.this) {mConnectThread = null;}// Start the connected thread connected(mmSocket, mmDevice, mSocketType);}public void cancel() {try {mmSocket.close();} catch (IOException e) {Log.e(TAG, "close() of connect " + mSocketType + " 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, String socketType) {Log.d(TAG, "create ConnectedThread: " + socketType);mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;// Get the BluetoothSocket input and output streamstry {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;String buffString="";// Keep listening to the InputStream while connectedwhile (true) {try {// Read from the InputStreambytes = mmInStream.read(buffer);String msg=new String(buffer,0,bytes);buffString +=msg;int indexOfNewLine= buffString.indexOf("\n");if(indexOfNewLine>=0){String frameString= buffString.substring(0, indexOfNewLine+1);buffString=buffString.substring(indexOfNewLine+1);mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, frameString).sendToTarget();}if(buffString.length()>1024){buffString="";}// Send the obtained bytes to the UI Activity // mHandler.obtainMessage(BluetoothChat.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 ActivitymHandler.obtainMessage(BluetoothChat.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);}}} }
懒样状态图: