Android中Bluetooth的意义和用法

来源:互联网 发布:vb猜数游戏程序 编辑:程序博客网 时间:2024/05/22 09:48

本文章分析了android蓝牙的用法,包括蓝牙的开启关闭、设置可见、开始取消发现、配对、主动连接、反连、广播等。

1、示例演示

public class MainActivity extends Activity {/**在原码有@hide标志,外面看不到*/private static final String ACTION_PAIRING_CANCEL ="android.bluetooth.device.action.PAIRING_CANCEL";private static final String DEVICE_NAME_OXYGEN = "IVT-OX03";/**配对不需要提供密码,不接收ACTION_PAIRING_REQUEST广播*/private static final String DEVICE_NAME_PRESSURE = "HEM-7081-IT";/**不能反连,但长连接,只要socket不关闭就可点加压按钮采集数据*/private static final String DEVICE_NAME_HINGMED = "Hingmed WBP";/**不指定手机,不指定APP*/private static final String DEVICE_NAME_ECG = "IVT-ECG12-500-R";private static final int OXYGEN_SERVICE = 0xdd0000;private static final String TAG = MainActivity.class.getSimpleName();/**判断并开关蓝牙,判断并启停发现过程,创建反连过程*/private BluetoothAdapter bluetoothAdapter;private static final int ENABLE_BLUETOOTH = 0x0;private static final int DISCOVER_REQUEST = 0x1;private List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();ArrayAdapter<String> arrayAdapter;BluetoothDevice bluetoothDevice;BluetoothClass bluetoothClass;private BluetoothSocket transferSocket;/** * <li>构造器为包访问权限,蓝牙地址String作为其参数 * <li>在搜索到星脉血压计设备时记录其蓝牙地址,即在ACTION_FOUND赋值 */private String ADDRESS_WBP = "8C:DE:52:72:6D:AA";/** * @hide * 在收到连接建立的广播后实例化InputStream和OutputStream */private OutputStream os;private InputStream is;UUID uuid;TextView inbox;ListView listView;TextView tv;byte[] tmpBytes = new byte[32];public int count = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {Log.d(TAG, "onCreate");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);inbox = (TextView) findViewById(R.id.inbox);listView = (ListView) findViewById(R.id.listView);tv = (TextView) findViewById(R.id.txt);listView.setOnItemClickListener(mOnItemClickListener);arrayAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, new ArrayList<String>());listView.setAdapter(arrayAdapter);//扁鹊飞救用的UUID号uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();initBluetooth();}private void initBluetooth(){IntentFilter filter = new IntentFilter();filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);filter.addAction(BluetoothDevice.ACTION_FOUND);filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);filter.addAction(ACTION_PAIRING_CANCEL);filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);registerReceiver(mReceiver, filter);if(!bluetoothAdapter.isEnabled()){startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), ENABLE_BLUETOOTH);}else{startServerSocket();}isRunning = true;}@Overrideprotected void onPause() {super.onPause();if(isFinishing()){try {os.write(new byte[]{0x5A,0x05,0x1A,0x48,-0x2D});} catch (IOException e) {e.printStackTrace();}}}@Overrideprotected void onDestroy() {Log.d(TAG, "onDestroy");super.onDestroy();unregisterReceiver(mReceiver);resetSocket();isRunning = false;}int[] pressures = new int[3];/**接收读取的数据,然后发指令*/private void receiveData(final byte[] data, final int len, String deviceName) {if(DEVICE_NAME_PRESSURE.equals(deviceName)){System.arraycopy(data, 0, tmpBytes, count, len);count += len;if (count == 5 && arrayEquals(tmpBytes, "READY".getBytes(), count)) {// 5 READYprint(tmpBytes, count);count = 0;try {SystemClock.sleep(500);os.write("VER00".getBytes());// get version data} catch (IOException e) {e.printStackTrace();}} else if (count == 15 && tmpBytes[0]=='O' && checkSum(tmpBytes, 3, 14)) {// 1-9-5 receive version dataprint(tmpBytes, count);count = 0;try {SystemClock.sleep(500);os.write("GAT00".getBytes());// get automatic transmission} catch (IOException e) {e.printStackTrace();}} else if (count == 5 && tmpBytes[0]=='O' && checkSum(tmpBytes, 3, 4)) {// automatic transmissionbyte set = tmpBytes[3];print(tmpBytes, count);count = 0;try {if (set == 0x00) {//0:not;1:yes若未设置自动传输,就先设置SystemClock.sleep(500);os.write(new byte[] { 'S', 'A', 'T', '\0', 0x11, 0x11 });// set automatic transmissionSystemClock.sleep(500);}os.write("GPD00".getBytes());// get profile data} catch (IOException e) {e.printStackTrace();}} else if (count == 14 && tmpBytes[0]=='O' && checkSum(tmpBytes, 3, 13)) {// 1-8-5 receive profile dataprint(tmpBytes, count);count = 0;try {SystemClock.sleep(500);os.write("GDN00".getBytes());// send 'get data number' command} catch (IOException e) {e.printStackTrace();}} else if (count == 8 && tmpBytes[0]=='O' && checkSum(tmpBytes, 3, 7)) {// 1-7 receive data numberprint(tmpBytes, count);count = 0;try {SystemClock.sleep(500);os.write(new byte[] { 'G', 'M', 'D', '\0', 0, 0, 0 });//send 'get measurement data' command} catch (IOException e) {e.printStackTrace();}} else if (count == 18 && tmpBytes[0]=='O' && checkSum(tmpBytes, 3, 17)) {// 1-9-8 receive measurement dataprint(tmpBytes, count);count = 0;try {SystemClock.sleep(500);os.write(new byte[]{'T','O','K',(byte) 0xff,(byte) 0xff});} catch (IOException e) {e.printStackTrace();}}else if(count == 2 && arrayEquals("OK".getBytes(), tmpBytes, count)){//发TOK会收到OKprint(tmpBytes, count);count = 0;}}else if(DEVICE_NAME_OXYGEN.equals(deviceName)||(bluetoothClass.getMajorDeviceClass() == BluetoothClass.Device.Major.UNCATEGORIZED&&(bluetoothClass.hashCode() & 0xFFE000)==OXYGEN_SERVICE)){//for(int i=0;i<len;i+=6){//print(data, i, i+6);//SystemClock.sleep(5L);//}print(data, 0, 6);}else if(DEVICE_NAME_ECG.equals(deviceName)){handler.post(new Runnable() {@Overridepublic void run() {StringBuilder sb = new StringBuilder();for(int i=0;i<len;i++){if(i%12==0){sb.append('\n');}sb.append(data[i]&0xff).append(',');}inbox.setText(sb.deleteCharAt(0).deleteCharAt(sb.length()-1));}});}else if(DEVICE_NAME_HINGMED.equals(deviceName)){try {if(len == 5&&arrayEquals(data, new byte[]{0x5A,0x05,0x10}, 3)){printHingmed(data, len, "应答连接握手:");//血压计应答连接握手指令}else if(len == 7&&arrayEquals(data, new byte[]{0x5A,0x07,0x31}, 3)){printHingmed(data, len, "主发电池电量:");//血压计主发电池电量指令//data[3] 电量;data[4] 状态,0未充电,1充电,2充满os.write(new byte[]{0x5A,0x05,0x31,0x57,-0x6D});//客户端主发设备信息指令os.write(new byte[]{0x5A,0x05,0x11,-0x71,-0x6E});}else if(len == 7&&arrayEquals(data, new byte[]{0x5A,0x07,0x11}, 3)){printHingmed(data, len, "应答设备信息:");//血压计应答设备信息指令//客户端主发同步时间指令os.write(new byte[]{0x5A,0x0A,0x12,0x0D,0x0B,0x14,0x0B,0x17,-0x1B,0x44});}else if(len == 5&&arrayEquals(data, new byte[]{0x5A,0x05,0x12}, 3)){printHingmed(data, len, "应答时间同步:");//血压计应答时间同步指令//客户端下发登录用户名指令,用户名位置3-6os.write(new byte[]{0x5A,0x09,0x13,0x00,0x00,0x45,0x67,0x25,0x17});}else if(len == 5&&arrayEquals(data, new byte[]{0x5A,0x05,0x13}, 3)){printHingmed(data, len, "应答登录用户名:");//血压计应答登录用户名指令//客户端下发最近血压记录时间指令os.write(new byte[]{0x5A,0x0A,0x14,0x0D,0x0B,0x14,0x0F,0x30,0x59,0x06});}else if(len == 5&&arrayEquals(data, new byte[]{0x5A,0x0A,0x14}, 3)){printHingmed(data, len, "应答最近血压记录时间:");//血压计应答最近血压记录时间指令}else if(len==18&&arrayEquals(data, new byte[]{0x5A,0x12,0x30}, 3)){printHingmed(data, len, "主发血压记录:");//血压计主发未上传的血压记录数据,若不应答,收到4条相同结果//data[3]-data[8]收缩压,舒张压,心率//data[9]-data[13]年月日时分秒//记录血压记录。显示、本地保存、上传从这里开始pressures[0] = (((data[3] & 0xff) << 8)+(data[4] & 0xff));pressures[1] = (((data[5] & 0xff) << 8)+(data[6] & 0xff));pressures[2] = (((data[7] & 0xff) << 8)+(data[8] & 0xff));Log.d(TAG, "收缩压:"+pressures[0]+",舒张压:"+pressures[1]+",心率:"+pressures[2]);//客户端应答血压记录os.write(new byte[]{0x5A,0x05,0x30,-0x69,0x52});}else if(len==5&&arrayEquals(data, new byte[]{0x5A,0x05,0x3A}, 3)){printHingmed(data, len, "主发上传记录完毕:");//血压计主发上传记录完毕,若不应答,收到4条相同结果//客户端应答上传完毕os.write(new byte[]{0x5A,0x05,0x3A,-0x70,-0x2E});//客户端主发加压指令//确定最近血压记录上传完毕后,立马加压开始测量;或者点击血压计上的加压按钮os.write(new byte[]{0x5A,0x05,0x40,0x73,0x53});}else if(len==6&&arrayEquals(data, new byte[]{0x5A,0x05,0x40}, 3)){printHingmed(data, len, "应答启动测量:");//血压计应答启动测量命令;若点击加压按钮测量,则客户端收不到此命令}else if(len==8&&arrayEquals(data, new byte[]{0x5A,0x08,0x50}, 3)){printHingmed(data, len, "主发袖带压力数据:");//血压计主发袖带压力数据,多条}else if(len==5&&arrayEquals(data, new byte[]{0x5A,0x05,0x1A}, 3)){printHingmed(data, len, "应答血压计断开连接:");}} catch (IOException e) {e.printStackTrace();}}}/**校验接收到的数据是否正确*/private boolean checkSum(byte[] data,int start,int end){byte check = 0;for(int i=start;i<=end;i++){check ^= data[i];}if(check==0){return true;}return false;}/** 判断两个byte数组是否相同 * <li>从两数组0到len位置依次比较 */private boolean arrayEquals(byte[] one, byte[] another, int len) {if (one == null || another == null) {return false;}if(len<0||len>one.length||len>another.length){return false;}for (int i = 0; i < len; i++) {if (one[i] != another[i]) {return false;}}return true;}Handler handler = new Handler();private void print(byte[] bytes, int len){final StringBuilder sb = new StringBuilder();for(int i=0;i<len;i++){sb.append(bytes[i]).append(",");}handler.post(new Runnable() {@Overridepublic void run() {//if(inbox.getText().length()>256){//inbox.setText("");//}inbox.append(sb+"\n");}});}/** * 处理 * @param bytes * @param start * @param end */private void print(final byte[] bytes, final int start, int end){//final StringBuilder sb = new StringBuilder();//for(int i=start;i<end;i++){//sb.append(bytes[i]&0xff).append(",");//}handler.post(new Runnable() {@Overridepublic void run() {//inbox.append(sb+"\n");inbox.setText("血氧值:"+(bytes[start+2]&0xff)+"\n脉率值:"+(bytes[start+1]&0xff));}});}private void printHingmed(byte[] bs, int len, String title){StringBuilder sb = new StringBuilder();sb.append(title);for(int i=0;i<len;i++){sb.append(bs[i]&0xFF).append(',');}Log.d(TAG, sb.deleteCharAt(sb.length()-1).toString());}private boolean listening;@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if(requestCode == ENABLE_BLUETOOTH){if(resultCode == RESULT_OK){Toast.makeText(this, "Bluetooth is enabled", Toast.LENGTH_SHORT).show();}}else if(requestCode == DISCOVER_REQUEST){if(resultCode == RESULT_OK){Toast.makeText(this, "Bluetooth is discoverable", Toast.LENGTH_SHORT).show();}}}public void onClick(View v){switch (v.getId()) {case R.id.discoverable://对所有附近设备可见,反连使用//若蓝牙不可用则提示打开蓝牙startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE), DISCOVER_REQUEST);break;case R.id.discover:if(!bluetoothAdapter.isEnabled()){startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), ENABLE_BLUETOOTH);}else if(!bluetoothAdapter.isDiscovering()){//inquiry scan of 12s,followed by a page scan of each new device//heavyweight procedure, asynchronous call, return immediatelybluetoothAdapter.startDiscovery();}break;case R.id.clearEdit:inbox.setText("");arrayAdapter.clear();deviceList.clear();break;case R.id.connect:connectDevice();}}boolean isRunning;/** * <ul><li>当前设备作为server反连,监听连接请求 * <li>block until a connection is established,单开线程循环监听连接 * <li>程序启动时,若蓝牙已开,自动启动反连;若蓝牙未开,等接收到蓝牙打开广播后再启动反连 */private void startServerSocket(){Log.d(TAG, "反连过程启动");try {//getBluetoothService() called with no BluetoothManagerCallbackfinal BluetoothServerSocket server = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("bluetoothserver", uuid);new Thread(new Runnable() {@Overridepublic void run() {while(isRunning){try {Log.d(TAG, "before accept");transferSocket = server.accept();Log.d(TAG, transferSocket.getRemoteDevice().getName()+"-after accept");try {is = transferSocket.getInputStream();os = transferSocket.getOutputStream();bluetoothDevice = transferSocket.getRemoteDevice();bluetoothClass = transferSocket.getRemoteDevice().getBluetoothClass();} catch (IOException e) {e.printStackTrace();}if(mReadThread==null||!mReadThread.isAlive()){mReadThread = new ReadThread();mReadThread.start();}//Broken pipeos.write(new byte[]{0x5A,0x05,0x10,0x4F,0x53});} catch (IOException e) {e.printStackTrace();}}}}).start();} catch (IOException e) {e.printStackTrace();}}/**主动连接设备*/private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {try {BluetoothDevice bluetoothDevice = deviceList.get(position);//分三种情况://1、已经配对,直接建立连接//2、正在配对,不采取措施//3、未配对,先配对再连接Log.d(TAG, "before bond-"+bluetoothDevice.getBondState());if(bluetoothDevice.getBondState()==BluetoothDevice.BOND_BONDING){Toast.makeText(MainActivity.this, "正在配对...", Toast.LENGTH_SHORT).show();return;}if(bluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE){//配对方法立即返回,但实际配对过程持续10多秒boolean retValue = bluetoothDevice.createBond();//配对or//Method method = BluetoothDevice.class.getMethod("createBond");//boolean retValue = (Boolean) method.invoke(bluetoothDevice);if(retValue){//true表示配对过程开始new ConnectThread(true).start();return;}}new ConnectThread(false).start();} catch (Exception e) {e.printStackTrace();}}};private class ConnectThread extends Thread{boolean isBonding;public ConnectThread(boolean isBonding){this.isBonding = isBonding;}@Overridepublic void run() {super.run();//等待配对成功,配对过程大概10sif(isBonding){long start = SystemClock.elapsedRealtime();while(bluetoothDevice.getBondState()!=BluetoothDevice.BOND_BONDED){SystemClock.sleep(50);}Log.d(TAG, "配对成功,耗时-"+(SystemClock.elapsedRealtime()-start)+"ms");}//建立连接try {//transferSocket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);Method method = BluetoothDevice.class.getMethod("createInsecureRfcommSocketToServiceRecord", new Class[]{UUID.class});transferSocket = (BluetoothSocket) method.invoke(bluetoothDevice, uuid);long start = SystemClock.elapsedRealtime();transferSocket.connect();//阻塞直到连接成功Log.d(TAG, "after connect-"+(SystemClock.elapsedRealtime()-start)+"ms");is = transferSocket.getInputStream();os = transferSocket.getOutputStream();if(mReadThread==null||!mReadThread.isAlive()){mReadThread = new ReadThread();mReadThread.start();}//这么写每个设备都会发if(transferSocket.getRemoteDevice().getName().equals(DEVICE_NAME_HINGMED)){os.write(new byte[]{0x5A,0x05,0x10,0x4F,0x53});}} catch (Exception e) {e.printStackTrace();}}}/** * close InputStream,OutputStream,BluetoothSocket * 在Activity.onDestroy调用 */private void resetSocket(){Log.d(TAG, "resetSocket");listening = false;try {if(is!=null)is.close();} catch (IOException e1) {e1.printStackTrace();}try {if(os!=null)os.close();} catch (IOException e1) {e1.printStackTrace();}try {if(transferSocket!=null)transferSocket.close();} catch (IOException e) {e.printStackTrace();}}private BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();//减少代码量及方法多次调用带来的性能损失if(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)){Log.d(TAG, "发现开始");arrayAdapter.clear();deviceList.clear();}else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){Log.d(TAG, "发现结束");}else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);int preState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, 0);if(state == BluetoothAdapter.STATE_ON){Log.d(TAG, "蓝牙打开");startServerSocket();}else if(state == BluetoothAdapter.STATE_OFF){Log.d(TAG, "蓝牙关闭");}}BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if(remoteDevice==null){return;}if(BluetoothDevice.ACTION_FOUND.equals(action)){//BluetoothDevice和BluetoothClass均是Parcelable子类//BluetoothDevice.getName()有可能为nullLog.d(TAG, "find "+remoteDevice.getName()+"|"+remoteDevice.getAddress()+"|"+remoteDevice.getBondState()+"|"+remoteDevice.getType());BluetoothClass bluetoothClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);if(remoteDevice!=null&&bluetoothClass!=null){bluetoothDevice = remoteDevice;MainActivity.this.bluetoothClass = bluetoothClass;if(bluetoothClass.getDeviceClass()==BluetoothClass.Device.HEALTH_BLOOD_PRESSURE&&(bluetoothClass.getMajorDeviceClass()==BluetoothClass.Device.Major.HEALTH)){deviceList.add(remoteDevice);arrayAdapter.add(remoteDevice.getName());Log.d(TAG, "欧姆龙血压计-"+remoteDevice.getName()+"|"+bluetoothClass.getDeviceClass()+"|"+bluetoothClass.getMajorDeviceClass()+"|"+(bluetoothClass.hashCode() & 0xFFE000));bluetoothAdapter.cancelDiscovery();//找到一个符合的设备就停止发现过程}else if(DEVICE_NAME_OXYGEN.equals(remoteDevice.getName())||DEVICE_NAME_ECG.equals(remoteDevice.getName())){deviceList.add(remoteDevice);arrayAdapter.add(remoteDevice.getName());bluetoothAdapter.cancelDiscovery();}else if((bluetoothClass.getMajorDeviceClass() == BluetoothClass.Device.Major.UNCATEGORIZED&&(bluetoothClass.hashCode() & 0xFFE000)==OXYGEN_SERVICE)){//TODO 血氧name为nulldeviceList.add(remoteDevice);arrayAdapter.add(DEVICE_NAME_OXYGEN);bluetoothAdapter.cancelDiscovery();}else if("Hingmed WBP".equalsIgnoreCase(remoteDevice.getName())||((bluetoothClass.getDeviceClass()==BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)&&(bluetoothClass.getMajorDeviceClass()==BluetoothClass.Device.Major.AUDIO_VIDEO)&&(bluetoothClass.hashCode() & 0xFFE000)==0x240000)){//没法定位血压计 service 0x240000Log.d(TAG, "星脉血压计-"+remoteDevice.getName()+"|"+bluetoothClass.getDeviceClass()+"|"+bluetoothClass.getMajorDeviceClass()+"|"+(bluetoothClass.hashCode() & 0xFFE000));ADDRESS_WBP = remoteDevice.getAddress();deviceList.add(remoteDevice);arrayAdapter.add(remoteDevice.getName());bluetoothAdapter.cancelDiscovery();}}}else if(BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)){Log.d(TAG, "ACTION_ACL_CONNECTED-"+remoteDevice.getName());tv.setText("已连设备:"+remoteDevice.getName());Toast.makeText(MainActivity.this, remoteDevice.getName()+" 已连接", Toast.LENGTH_SHORT).show();}else if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)){Log.d(TAG, "ACTION_ACL_DISCONNECTED-"+remoteDevice.getName());tv.setText("已连设备:");Toast.makeText(MainActivity.this, remoteDevice.getName()+" 已断开", Toast.LENGTH_SHORT).show();}else if(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0);int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, 0);if(bondState==BluetoothDevice.BOND_BONDED){Log.d(TAG, "配对成功:"+remoteDevice.getName());}else if(bondState == BluetoothDevice.BOND_NONE){Log.d(TAG, "取消配对:"+remoteDevice.getName());}}else if (ACTION_PAIRING_CANCEL.equals(action)) {Log.d(TAG, "ACTION_PAIRING_CANCEL");} else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,BluetoothDevice.ERROR);Log.d(TAG, "ACTION_PAIRING_REQUEST-"+type);//PAIRING_VARIANT_CONSENT 3 Hingmed WBPif(type == BluetoothDevice.PAIRING_VARIANT_PIN){remoteDevice.setPin("0000".getBytes());//弹框后自动输入密码、自动确定}else if(type == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION){remoteDevice.setPairingConfirmation(true);}}else if(BluetoothDevice.ACTION_UUID.equals(action)){Log.d(TAG, "ACTION_UUID");}}};ReadThread mReadThread;private static final int BYTE_SIZE = 320*1024;/** * <ul><li>仅维持一个数组。 * <li>供所有mobile health device使用 * <li>数组设置比较大用于满足不同需求 * <li>并多次连接多次接收数据反复使用*/byte[] buffer = new byte[BYTE_SIZE];/** * 收到设备连上的广播后启动此线程,执行读取远程数据并显示 * 主动或反连成功,拿到BluetoothSocket及相应输入输出流后启动此线程读取数据 */private class ReadThread extends Thread{@Overridepublic void run() {super.run();try {int bytesRead = -1;listening = true;while(listening){long start = SystemClock.elapsedRealtime();//bt socket closed, read return: -1bytesRead = is.read(buffer);//IOExceptionlong readTime = SystemClock.elapsedRealtime()-start;if(readTime<200L){SystemClock.sleep(200L-readTime);}if(bytesRead != -1){/*try {Log.d(TAG, "反射");//NoSuchMethodException, JDK1.7.0_51可用//方法名和参数类型(Class<?>)Method method = MainActivity.class.getMethod("receiveData", new Class<?>[]{byte[].class, int.class, String.class});//对象和参数值method.invoke(this, new Object[]{buffer, bytesRead, bluetoothDevice.getName()});} catch (Exception e) {e.printStackTrace();}*/receiveData(buffer, bytesRead, bluetoothDevice.getName());}}} catch (IOException e) {e.printStackTrace();}}};private BluetoothDevice getBluetoothDeviceByAddress(String addr){return bluetoothAdapter.getRemoteDevice(ADDRESS_WBP);//Set<BluetoothDevice> set = bluetoothAdapter.getBondedDevices();//Iterator<BluetoothDevice> it = set.iterator();//while(it.hasNext()){//BluetoothDevice bd = it.next();//if(ADDRESS_WBP.equals(bd.getAddress())){//return bd;//}//}//return null;}/**不能反连,点击按钮连接指定设备*/private void connectDevice(){//客户端发完握手指令,线程就结束new Thread(){@Overridepublic void run() {super.run();bluetoothDevice = getBluetoothDeviceByAddress(ADDRESS_WBP);if(bluetoothDevice==null){//该设备未配对Log.d(TAG, "bluetoothDevice==null");return;}bluetoothClass = bluetoothDevice.getBluetoothClass();try {transferSocket = bluetoothDevice.createInsecureRfcommSocketToServiceRecord(uuid);Log.d(TAG, "before connect");//不管是否配对,getRemoteDevice立马返回//若未配对,connect阻塞弹配对对话框等待配对;若已配对,connect快速返回transferSocket.connect();//阻塞直到连接成功Log.d(TAG, "after connect");is = transferSocket.getInputStream();os = transferSocket.getOutputStream();if(mReadThread==null||!mReadThread.isAlive()){mReadThread = new ReadThread();mReadThread.start();}if(transferSocket.getRemoteDevice().getName().equals(DEVICE_NAME_HINGMED)){os.write(new byte[]{0x5A,0x05,0x10,0x4F,0x53});}} catch (Exception e) {e.printStackTrace();}};}.start();}}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><ScrollView     android:layout_width="match_parent"    android:layout_height="match_parent"     xmlns:android="http://schemas.android.com/apk/res/android">    <LinearLayout    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical">    <TextView         android:id="@+id/txt"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="已连设备:"/><Button         android:id="@+id/discoverable"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="设置当前设备可见"        android:onClick="onClick"/>    <Button         android:id="@+id/discover"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="启动发现过程"        android:onClick="onClick"/>    <TextView         android:id="@+id/inbox"        android:layout_width="match_parent"        android:layout_height="wrap_content"/>    <Button         android:id="@+id/clearEdit"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="onClick"        android:text="clearEdit"/>    <Button         android:id="@+id/connect"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:onClick="onClick"        android:text="connectSpecific"/>    <ListView         android:id="@+id/listView"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></LinearLayout></ScrollView>

0 0
原创粉丝点击