android 藍芽之資料傳輸
因為專案需要,需要將本地資料庫的資料,通過藍芽傳輸到另一臺裝置上。然後百度了蠻久,看了蠻多的,覺得有必要自己整理一下,藍芽的傳輸功能。
首先,我們都知道的,藍芽連線數需要先配對的,兩臺手機配對後才可進行藍芽處理。對於藍芽配對的方法網上一大堆,我也就不具體說了,大概記錄一下。基本的我們可以通過手機原有的藍芽功能,進行搜尋配對後在自身的APK中,直接啟動藍芽,然後查詢已匹配裝置就行了。因為專案目前沒有要求實現匹配功能,我也就能省則省了...不過還是總體介紹一下吧。
在安卓原始碼中,首先要知道有提供了一個藍芽類:BluetoothAdapter ,我們需要先初始化這個類,才能huod獲得藍芽的相關資料。
//註冊藍芽廣播 IntentFilter filter = new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_FINISHED); getActivity().registerReceiver(receiver, filter); filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); getActivity().registerReceiver(receiver, filter);
然後再實現廣播的處理:
public class BluetoothReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(BluetoothDevice.ACTION_FOUND)) { //未匹配 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { //搜尋完成 } } }
基本就是這樣,裡面的引數判斷的話,藍芽有各種不同的狀態,可以根據搜尋到的裝置進行檢查,然後區分當前藍芽處於什麼狀態。而我因為業務原因,暫時也不需要去監聽匹配,所以,我用的是以下這個方法:
Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
for (BluetoothDevice bondedDevice : bondedDevices) {
bluetoothDevices.add(bondedDevice);
}
當藍芽開啟後,通過此方法,獲得已匹配的裝置。
另外補充一個開啟藍芽的方法:此方法為了讓其他裝置可以搜尋到本機,裡面的300表示暴露時間秒
//開啟顯示,讓本機可以被搜尋到
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);
} else {
showToast("藍芽已開啟");
}
好了,以上是一些基本的藍芽功能,到哪裡都可以找到一大堆的。下面開始記錄關鍵,藍芽資料傳輸
既然要傳輸資料,和給api通訊一樣,肯定是要有一個服務端,一個客戶端的。而服務端是需要在開啟狀態,監聽客戶端傳送的資料。而服務屬於阻塞操作,所以要開啟一個執行緒,再來開啟一個服務:
BluetoothServerSocket mmServerSocket=mBluetoothAdapter.listenUsingRfcommWithServiceRecord("Name", UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"));
BluetoothSocket socket = mmServerSocket.accept();
通過以上方法來開啟一個服務,這裡“Name”,UUID,服務端和客戶端都必須一樣,這是識別用的。另外要注意mmServerSocket 是否為 null ,若未null 則也是無法開啟的。另外在之後若出現無法連線的情況,這裡我們可以查下緩一緩UUID的值,具體這個坑什麼原因我也說不清,反正換一換唄。
當以上的方法呼叫了之後,伺服器基本就算開啟了的。只要沒拋異常的話。
然後我們需要一個輸入流,可以寫迴圈,也可以不寫迴圈。迴圈的話就通過傳輸過來的資料,做個標記結束它。這些都是一些廢話,就直接寫個流吧...
InputStream mmInStream = socket.getInputStream();
bytes = mmInStream.read(buffer);
String data = new String(buffer, 0, bytes, "UTF-8");
Message msg = Message.obtain();
msg.what = Constants.MESSAGE_READ;
msg.obj = data;
mHandler.sendMessage(msg);
這裡注意,我們在之前開啟服務端的時候,要獲得一個藍芽的操作類:BluetoothSocket ,這個類是用來操作流,服務的。ranho然後通過handler 將接收的資料回傳到主執行緒。服務端到這裡就完了。
接著寫客戶端的:
客戶端這邊就輕鬆多了,既然服務端已經開啟,我們就進行連線,通過BluetoothAdapter 我們已經得到了已經匹配的裝置,然後選擇你要連線的藍芽裝置,不過記得先關閉藍芽搜尋功能:
mBluetoothAdapter.cancelDiscovery();
BluetoothSocket mmSocket= device.createRfcommSocketToServiceRecord(UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"));
mmSocket.connect();
然後用要連線的裝置device,輸入服務端的UUID,接著連線。當然,以上的操作也是需要在子執行緒中進行的。
連線結束後,可以寫個方法通知服務端,誰誰誰連線了。當然我們也要寫一個輸出流,用於一會輸出資料到服務端去。
最後,最最重要的,用完了li流一定要記得關閉。
為了以後方便,我也做了一個功能類,之後需要用時就直接呼叫。這裡就貢獻給大家分享一下吧!
public class BluetoothChatService {
private static final String TAG = "BluetoothChatService";
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";
private static final UUID MY_UUID_SECURE =
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
public final BluetoothAdapter mAdapter;
public final Handler mHandler;
public AcceptThread mSecureAcceptThread;
public AcceptThread mInsecureAcceptThread;
public ConnectThread mConnectThread;
public ConnectedThread mConnectedThread;
private int mState;
public static final int STATE_NONE = 0;
public static final int STATE_LISTEN = 1;
public static final int STATE_CONNECTING = 2;
public static final int STATE_CONNECTED = 3;
public BluetoothChatService(Context context, Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
private synchronized void setState(int state) {
Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
public synchronized int getState() {
return mState;
}
public synchronized void start() {
Log.d(TAG, "start");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_LISTEN);
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread();
mSecureAcceptThread.start();
}
}
public synchronized void connect(BluetoothDevice device) {
Log.d(TAG, "connect to: " + device);
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device) {
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;
}
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(Constants.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
public synchronized void stop() {
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);
}
public void write(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED)
return;
r = mConnectedThread;
}
r.write(out);
}
private void connectionFailed() {
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "無法連線裝置!");
msg.setData(bundle);
mHandler.sendMessage(msg);
BluetoothChatService.this.start();
}
private void connectionLost() {
Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(Constants.TOAST, "裝置連線已斷開");
msg.setData(bundle);
mHandler.sendMessage(msg);
BluetoothChatService.this.start();
}
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);
} catch (IOException e) {
// Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
while (mState != STATE_CONNECTED) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
// Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}
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:
try {
socket.close();
} catch (IOException e) {
//Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
}
public void cancel() {
// 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);
}
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} catch (IOException e) {
// Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
// Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
mAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException e) {
try {
mmSocket.close();
} catch (IOException e2) {
// Log.e(TAG, "unable to close() " + mSocketType +
// " socket during connection failure", e2);
}
connectionFailed();
return;
}
synchronized (BluetoothChatService.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
// Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
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: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
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() {
synchronized (BluetoothChatService.class) {
byte[] buffer = new byte[1024 * 4];
int bytes;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
String data = new String(buffer, 0, bytes, "UTF-8");
Message msg = Message.obtain();
msg.what = Constants.MESSAGE_READ;
msg.obj = data;
mHandler.sendMessage(msg);
} catch (IOException e) {
connectionLost();
BluetoothChatService.this.start();
break;
}
}
}
}
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
mmOutStream.flush();
mHandler.obtainMessage(Constants.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);
}
}
}
}
/**
* @desc ${BluetoothService 中使用的常量}
*/
public class Constants {
public static final int MESSAGE_STATE_CHANGE = 1; //狀態改變
public static final int MESSAGE_READ = 2; //讀取
public static final int MESSAGE_WRITE = 3; //寫出
public static final int MESSAGE_DEVICE_NAME = 4; //裝置 名稱
public static final int MESSAGE_TOAST = 5; //連線失敗
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case Constants.MESSAGE_TOAST:
String statu = msg.getData().getString(Constants.TOAST);
showToast(statu + "");
break;
case Constants.MESSAGE_DEVICE_NAME:
String string = msg.getData().getString(Constants.DEVICE_NAME);
showToast("已連線裝置" + string);
break;
case Constants.MESSAGE_READ: //讀取接收資料
break;
case Constants.MESSAGE_WRITE: //傳送端,正在傳送的資料
break;
}
}
};
private void iniData(){
省******
******
******略
BluetoothChatService chatService = new BluetoothChatService(getActivity(), mHandler);
Listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// 判斷當前是否還是正在搜尋周邊裝置,如果是則暫停搜尋
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
BluetoothDevice bluetoothDevice = bluetoothDevices.get(position);
//客戶端連線
chatService.connect(bluetoothDevice);
}
});
//如果要開啟服務端直接呼叫以下語句
//chatService.start();
}
/**
* 準備開始傳送資料
*/
private void snedInfo() {
if (chatService.getState() != BluetoothChatService.STATE_CONNECTED) {
showToast("連線失敗");
return;
}
String toSendJson = new Gson().toJson(“Bean資料”);
if (toSendJson.length() > 0) {
byte[] send = new byte[0];
try {
send = toSendJson.getBytes();
} catch (Exception e) {
e.printStackTrace();
}
chatService.write(send);
}
}
});
}
以上就是我目前做的藍芽傳輸功能了,先這樣吧...然後再慢慢優化改進的。各種狀態也都有了的,自己慢慢調整一下吧..