Android蓝牙开发开源框架 代码案例
蓝牙开步骤:
1.了解,蓝牙API共有五个类,其中需要撑握三个类:
BluetoothAdapter(蓝牙适配器):该类主要获取蓝牙信息,比较打开蓝牙、获取本机mac地址、配对的蓝牙信息、等等;BluetoothDevice(蓝牙设备):如果连接非安卓设备,该类主要是初始服务端连接蓝牙(把本机看作客户端),如果连接安卓设备,看谁先发连接谁就是客户端;
BluetoothSocket(蓝牙通信):如果对Socket有了解的,就比较好理解了,就是当连接成功时,可以下午通信。
注:这里讲的不够详解,可以去官方网了解。
2.连接
2.1 找目标MAC地址,可以从BluetoothAdapter可以获取已经配对过的蓝牙地址,选择要连接的蓝牙地址(mac)。2.2 根据MAC生成对象,通过:BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(mac);得到一个BluetoothDevice,相当于找到了连接的对象;
2.3连接,BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);连接非Android设备要用固定UUID:
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");如果Android设备之间连接要自定义。
2.4发起连接,socket.connect(); 阻止anr事件,要在异步处理连接。
3.通信
通信从socket可得输出流和输入流:stream = socket.getInputStream(); output = socket.getOutputStream();要注意思的是,当蓝牙发数据过来并不是一次性可以从输入流得到,一条数据有可以分几次发送过来。所以要做缓冲区!
4.解析数据,这个没什么好说的,根据协议解析返回数据(不懂的可以加我QQ:755022831)
下面代码展示:
package com.cyy.bluetest; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import com.cyy.bluetooth.BlueConnetHandler; import com.cyy.bluetooth.BlueDeviceControl; import com.cyy.bluetooth.BlueToothCallBack; public class MainActivity extends Activity implements OnClickListener { private TextView tv; private BlueConnetHandler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.bn).setOnClickListener(this); tv = (Button) findViewById(R.id.tv); } private void blue() { BlueDeviceControl control = new BlueDeviceControl(); control.openBlue();// 打开蓝牙 handler = new BlueConnetHandler(new BlueToothCallBack() { @Override public void getDate(String date) { tv.setText("连接数据: " + date); } @Override public void connect(boolean state) { tv.setText("连接: " + state); } }, "mac地址"); handler.sendEmptyMessage(BlueConnetHandler.CONNECT); } @Override public void onClick(View v) { if (handler.getStateConnect() != 0) { tv.setText("已在连接中....."); } else { tv.setText("连接中....."); blue(); } } }
BlueDeviceControl对BluetoothAdapter一个封装:
package com.cyy.bluetooth; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.SharedPreferences; public class BlueDeviceControl { private BluetoothAdapter adapter; /** 构造方法 */ public BlueDeviceControl() { adapter = BluetoothAdapter.getDefaultAdapter(); } /** 设备是否支持蓝牙 */ public boolean isBlueToothSupported() { return adapter != null; } /** 打开蓝牙 */ public void openBlue() { if (adapter != null && !adapter.isEnabled()) { adapter.enable(); } } /** 关闭蓝牙 */ public void closeBlue() { if (adapter != null && adapter.isEnabled()) { adapter.disable(); } } /** 返回已配对的蓝牙设备 */ public String[] getPartners() { Set<BluetoothDevice> set = adapter.getBondedDevices(); String list[] = new String[set.size()]; int i = 0; for (BluetoothDevice device : set) { list[i] = device.getAddress(); i++; } return list; } /** 返回已配对的蓝牙设备 */ public ArrayList<Map<String, String>> allPartners() { ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>(); Set<BluetoothDevice> set = adapter.getBondedDevices(); for (BluetoothDevice device : set) { Map<String, String> map = new HashMap<String, String>(); map.put("name", device.getName()); map.put("address", device.getAddress()); list.add(map); } return list; } /** 自动连接上次连接过的蓝牙地址 */ public String getAdress(Context context) { SharedPreferences prference; String BLUE_PREF_NAME = "BLUE_PREF_NAME"; String ADDRESS = "address"; prference = context.getSharedPreferences(BLUE_PREF_NAME, 0); String tmp = prference.getString(ADDRESS, "00:0E:EA:CE:C9:64"); return tmp; } /** 保存蓝牙地址,SharedPreferences保存 */ public void saveAdress(Context context, String mac) { if (context != null) { SharedPreferences prference; String BLUE_PREF_NAME = "BLUE_PREF_NAME"; String ADDRESS = "address"; prference = context.getSharedPreferences(BLUE_PREF_NAME, 0); prference.edit().putString(ADDRESS, mac).commit(); } } }
BlueConnectThread蓝牙连接线程:
package com.cyy.bluetooth; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.os.Handler; import android.os.Message; public class BlueConnectThread extends Thread { private Handler handler; // 连接非安卓设备固定UUID private final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private BluetoothDevice device; private BluetoothSocket socket; private OutputStream output; private String mac; public BlueConnectThread(Handler handler) { this.handler = handler; } @Override public void run() { InputStream stream; try { socket.connect(); stream = socket.getInputStream(); output = socket.getOutputStream(); BufferedInputStream input = new BufferedInputStream(stream); Message message = handler.obtainMessage( BlueConnetHandler.CONNECT_SUCCEED, mac); message.sendToTarget(); int length; byte[] bytes = new byte[100]; while ((length = input.read(bytes)) != -1) { byte[] cacheByte = new byte[length]; System.arraycopy(bytes, 0, cacheByte, 0, length); message = handler.obtainMessage(BlueConnetHandler.GET_DATA, cacheByte); message.sendToTarget(); } } catch (IOException e) { Message message = handler.obtainMessage(BlueConnetHandler.CONNECT_FAIL); message.sendToTarget(); System.out.println(e.toString()); } } public boolean sendMsg(String msg) { if (output != null) { try { output.write(msg.getBytes("UTF-8")); return true; } catch (UnsupportedEncodingException e) { System.out.println(e.toString()); } catch (IOException e) { System.out.println(e.toString()); } } return false; } public void setMac(String mac) { this.mac = mac; try { // 判断是不是有效蓝牙地址,如果地址无效IllegalArgumentException异常 device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(mac); // 更改socket信道 socket = device.createRfcommSocketToServiceRecord(uuid); } catch (IllegalArgumentException e) { System.out.println(e.toString()); } catch (IOException e) { System.out.println(e.toString()); } } }
BlueConnetHandler数据处理
package com.cyy.bluetooth; import java.nio.ByteBuffer; import android.os.Handler; import android.os.Message; public class BlueConnetHandler extends Handler { private BlueToothCallBack callBack; // 默认,可以自定义测试目标mac地址 private String mac = "00:0E:EA:CE:C9:53"; // 缓冲区1024字节,如果接收的内容多,可以适当增大缓冲区 private ByteBuffer blueData = ByteBuffer.allocate(1024); public static final int CONNECT = 0x111111; public static final int GET_DATA = 0x111111 + 1; public static final int CONNECT_FAIL = 0x111111 + 2; public static final int CONNECT_SUCCEED = 0x111111 + 3; private static final int RESET = 0x111111 + 4; private static final int time = 10 * 1000; private int stateConnect = 0;// 连接状态,默认未开始连接 private BlueConnectThread thread; public BlueConnetHandler(BlueToothCallBack callBack) { this.callBack = callBack; } public BlueConnetHandler(BlueToothCallBack callBack, String mac) { this.callBack = callBack; this.mac = mac; } @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case CONNECT: if (thread == null || !thread.isAlive()) { stateConnect = CONNECT; thread = new BlueConnectThread(this); thread.setMac(mac); thread.start(); } break; case CONNECT_FAIL: stateConnect = CONNECT_FAIL; dealACallBack(false); // 设置连接失败后继续重新连接,10秒后重启 this.sendEmptyMessageDelayed(CONNECT, time); break; case CONNECT_SUCCEED: stateConnect = CONNECT_SUCCEED; mac = (String) msg.obj; callBack.connect(true); dealACallBack(true); break; case GET_DATA:// 从蓝牙获取到一些数据,通常一组数据分几次发送过来 byte[] bytes = (byte[]) msg.obj; blueData.put(bytes); this.removeMessages(RESET); this.sendEmptyMessageDelayed(RESET, 100); break; case RESET: // 从蓝牙获取一组数据后发送出去 decodeReSet(); break; default: break; } } private void dealACallBack(boolean isConnect) { if (null != callBack) { callBack.connect(isConnect); } } /** 根据蓝牙协议解析数据。然后重置data */ private void decodeReSet() { blueData.flip(); // String data = bytes2String(blueData.array()); // 简单地处理,具体还要根据协议来解析数据 String data = new String(blueData.array()); if (callBack != null) { callBack.getDate(data); } blueData.clear(); } /** 16进制字节数组转换成十进制字符串 */ private String bytes2String(byte[] bytes) { long sum = 0; for (int i = 0; i < bytes.length; i++) { long cache = bytes[i] & 0xff; for (int j = 0; j < i; j++) { cache = cache << 4 << 4; } sum += cache; } return sum + ""; } public int getStateConnect() { return stateConnect; } public boolean sendMsg(String msg) { if (thread != null) { return thread.sendMsg(msg); } return false; } }
代码开源 SVN:http://code.taobao.org/svn/blueconnect/trunk
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。