一. 藍(lán)牙權(quán)限
? ? <uses-permission android:name="android.permission.BLUETOOTH"/>
? ? <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
二.配對
代碼走起~~ 會順帶加些常用的知識點(diǎn)序愚。簡書這個(gè)貼代碼率碾,格式都沒了,將就的看吧撑刺,需要的時(shí)候自己再檢查括號啥的鹉胖,畢竟時(shí)間很緊張。
1.發(fā)起請求:
BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();
?if(mAdapter!=null && mAdapter.isEnabled()){
? ?try {? ?
? ? ? ? ? // pair before connect? ?
? ? ? ? ? BluetoothDevice Vdevice = mAdapter.getRemoteDevice(BTMAC);
? ? ? ? ? ?if (Vdevice.getBondState() == BluetoothDevice.BOND_NONE) {? ?
? ? ? ? ? ? ? ? ? ? ? ?Method creMethod = BluetoothDevice.class.getMethod("createBond");? ?
? ? ? ? ? ? ? ? ? ? ? ?Log.e(TAG, "START pair");? ?
? ? ? ? ? ? ? ? ? ? ?creMethod.invoke(Vdevice);? ?
? ? ? ? ? ?} else {
? ? ? ? ? ? ? ? ? ? Log.e(TAG, "paired!");
? ? ? ? ? ?}?
? ? ? ?} catch (Exception e) {? ?
? ? ? ? // TODO: handle exception? ?
? ? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? ?}
}else{
? ? ? ? ?//;
?}
2.如果需要固定碼直接配對够傍,可以使用方法:(此段代碼在下面完整的廣播例子中有)
if(action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) //再次得到的action甫菠,會等于PAIRING_REQUEST
? ? ? ? {?
? ? ? ? ? ? BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
? ? ? ? ? ? Log.e(TAG, action);?
? ? ? ? ? ? if(btDevice.getAddress().equals(BTMAC))? //btDevice.getName().contains("HC-05")
? ? ? ? ? ? {?
? ? ? ? ? ? ? ? try {?
? ? ? ? ? ? ? ? ? ? //1.確認(rèn)配對?
? ? ? ? ? ? ? ? ? ? ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);?
? ? ? ? ? ? ? ? ? ? //2.終止有序廣播?
? ? ? ? ? ? ? ? ? ? Log.i(TAG, "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());?
? ? ? ? ? ? ? ? ? ? abortBroadcast();//如果沒有將廣播終止,則會出現(xiàn)一個(gè)一閃而過的配對框王带。?
? ? ? ? ? ? ? ? ? ? //3.調(diào)用setPin方法進(jìn)行配對...?
? ? ? ? ? ? ? ? ? ? boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, BTPIN);?
? ? ? ? ? ? ? ? } catch (Exception e) {?
? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block?
? ? ? ? ? ? ? ? ? ? e.printStackTrace();?
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }else{?
? ? ? ? ? ? ? ? Log.e(TAG, "NOT THE BT U WANT");?
? ? ? ? ? ? }
3.以上用到將相關(guān)方法封裝的一個(gè)類淑蔚,ClsUtils。也是參考網(wǎng)上的“輪子”愕撰,感謝熱心分享的技術(shù)大牛刹衫。
public class ClsUtils
{? ?
? ? /**?
? ? * 與設(shè)備配對 參考源碼:platform/packages/apps/Settings.git?
? ? * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java?
? ? */? ?
? ? static public boolean createBond(Class btClass, BluetoothDevice btDevice)? ?
? ? throws Exception? ?
? ? {? ?
? ? ? ? Method createBondMethod = btClass.getMethod("createBond");? ?
? ? ? ? Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);? ?
? ? ? ? return returnValue.booleanValue();? ?
? ? }? ?
? ? static public boolean removeBond(Class btClass, BluetoothDevice btDevice)? ?
? ? ? ? ? ? throws Exception? ?
? ? {? ?
? ? ? ? Method removeBondMethod = btClass.getMethod("removeBond");? ?
? ? ? ? Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);? ?
? ? ? ? return returnValue.booleanValue();? ?
? ? }? ?
? ? static public boolean setPin(Class btClass, BluetoothDevice btDevice,? ?
? ? ? ? ? ? String str) throws Exception? ?
? ? {? ?
? ? ? ? try? ?
? ? ? ? {? ?
? ? ? ? ? ? Method removeBondMethod = btClass.getDeclaredMethod("setPin",? ?
? ? ? ? ? ? ? ? ? ? new Class[]? ?
? ? ? ? ? ? ? ? ? ? {byte[].class});? ?
? ? ? ? ? ? Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,? ?
? ? ? ? ? ? ? ? ? ? new Object[]? ?
? ? ? ? ? ? ? ? ? ? {str.getBytes()});? ?
? ? ? ? ? ? Log.e("returnValue", "" + returnValue);? ?
? ? ? ? }? ?
? ? ? ? catch (SecurityException e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // throw new RuntimeException(e.getMessage());? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? ? ? catch (IllegalArgumentException e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // throw new RuntimeException(e.getMessage());? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? ? ? catch (Exception e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // TODO Auto-generated catch block? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? ? ? return true;? ?
? ? }? ?
? ? // 取消用戶輸入? ?
? ? static public boolean cancelPairingUserInput(Class btClass,? ?
? ? ? ? ? ? BluetoothDevice device)? throws Exception? ?
? ? {? ?
? ? ? ? Method createBondMethod = btClass.getMethod("cancelPairingUserInput");? ?
//? ? ? ? cancelBondProcess(btClass, device);?
? ? ? ? Boolean returnValue = (Boolean) createBondMethod.invoke(device);? ?
? ? ? ? return returnValue.booleanValue();? ?
? ? }? ?
? ? // 取消配對? ?
? ? static public boolean cancelBondProcess(Class btClass,? ?
? ? ? ? ? ? BluetoothDevice device)? ?
? ? throws Exception? ?
? ? {? ?
? ? ? ? Method createBondMethod = btClass.getMethod("cancelBondProcess");? ?
? ? ? ? Boolean returnValue = (Boolean) createBondMethod.invoke(device);? ?
? ? ? ? return returnValue.booleanValue();? ?
? ? }?
? ? //確認(rèn)配對?
? ? static public void setPairingConfirmation(Class btClass,BluetoothDevice device,boolean isConfirm)throws Exception?
? ? {?
? ? ? ? Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class);?
? ? ? ? setPairingConfirmation.invoke(device,isConfirm);?
? ? }?
? ? /**?
? ? *?
? ? * @param clsShow?
? ? */? ?
? ? static public void printAllInform(Class clsShow)? ?
? ? {? ?
? ? ? ? try? ?
? ? ? ? {? ?
? ? ? ? ? ? // 取得所有方法? ?
? ? ? ? ? ? Method[] hideMethod = clsShow.getMethods();? ?
? ? ? ? ? ? int i = 0;? ?
? ? ? ? ? ? for (; i < hideMethod.length; i++)? ?
? ? ? ? ? ? {? ?
? ? ? ? ? ? ? ? Log.e("method name", hideMethod[i].getName() + ";and the i is:"? ?
? ? ? ? ? ? ? ? ? ? ? ? + i);? ?
? ? ? ? ? ? }?
? ? ? ? ? ? // 取得所有常量? ?
? ? ? ? ? ? Field[] allFields = clsShow.getFields();? ?
? ? ? ? ? ? for (i = 0; i < allFields.length; i++)? ?
? ? ? ? ? ? {? ?
? ? ? ? ? ? ? ? Log.e("Field name", allFields[i].getName());? ?
? ? ? ? ? ? }?
? ? ? ? }? ?
? ? ? ? catch (SecurityException e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // throw new RuntimeException(e.getMessage());? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? ? ? catch (IllegalArgumentException e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // throw new RuntimeException(e.getMessage());? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? ? ? catch (Exception e)? ?
? ? ? ? {? ?
? ? ? ? ? ? // TODO Auto-generated catch block? ?
? ? ? ? ? ? e.printStackTrace();? ?
? ? ? ? }? ?
? ? }? ?
}?
4.配對的相關(guān)廣播醋寝,查詢配對狀態(tài),根據(jù)這些時(shí)機(jī)插入需要處理的事件带迟,
順便把廣播的使用方式貼出來:
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
//filter.addAction(Intent.ACTION_POWER_CONNECTED);
//filter.addAction(Intent.ACTION_POWER_DISCONNECTED);
filter.addAction("android.bluetooth.device.action.PAIRING_REQUEST");
//filter.addAction("android.bluetooth.device.action.FOUND");
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
//filter.addAction("android.bluetooth.adapter.action.STATE_CHANGED");
registerReceiver(myReceiver, filter);
private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)){
? ? ? ? Log.d(TAG, "ACTION_USB_DEVICE_ATTACHED");//這個(gè)廣播是當(dāng)Android系統(tǒng)作為host插入U(xiǎn)SB設(shè)備的時(shí)候發(fā)出的
}else if(action.equals(UsbManager.ACTION_USB_DEVICE_DETACHED)){
? ? ? ? Log.d(TAG, "ACTION_USB_DEVICE_DETACHED");//拔出USB設(shè)備
}else if(action.equals(Intent.ACTION_POWER_CONNECTED)){
? ? ? ? Log.d(TAG, "ACTION_POWER_CONNECTED");
}else if(action.equals(Intent.ACTION_POWER_DISCONNECTED)){
? ? ? ? Log.d(TAG, "ACTION_POWER_DISCONNECTED");
}else if(action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) //再次得到的action音羞,會等于PAIRING_REQUEST?
? ? ? ? {?
? ? ? ? ? ? BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
? ? ? ? ? ? Log.e(TAG, action);?
? ? ? ? ? ? if(btDevice.getAddress().equals(BTMAC))? //btDevice.getName().contains("HC-05")
? ? ? ? ? ? {?
? ? ? ? ? ? ? ? try {?
? ? ? ? ? ? ? ? ? ? //1.確認(rèn)配對?
? ? ? ? ? ? ? ? ? ? ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);?
? ? ? ? ? ? ? ? ? ? //2.終止有序廣播?
? ? ? ? ? ? ? ? ? ? Log.i(TAG, "isOrderedBroadcast:"+isOrderedBroadcast()+",isInitialStickyBroadcast:"+isInitialStickyBroadcast());?
? ? ? ? ? ? ? ? ? ? abortBroadcast();//如果沒有將廣播終止,則會出現(xiàn)一個(gè)一閃而過的配對框仓犬。?
? ? ? ? ? ? ? ? ? ? //3.調(diào)用setPin方法進(jìn)行配對...?
? ? ? ? ? ? ? ? ? ? boolean ret = ClsUtils.setPin(btDevice.getClass(), btDevice, BTPIN);?
? ? ? ? ? ? ? ? } catch (Exception e) {?
? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block?
? ? ? ? ? ? ? ? ? ? e.printStackTrace();?
? ? ? ? ? ? ? ? }?
? ? ? ? ? ? }else{?
? ? ? ? ? ? ? ? Log.e(TAG, "NOT THE BT U WANT");?
? ? ? ? ? ? }
? ? ? ? }else if(action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
? ? ? ? ? ? BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
? ? ? ? ? ? //String name = device.getName();
? ? ? ? ? ? //Log.d("aaa", "device name: " + name);
? ? ? ? ? ? int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
? ? ? ? ? ? switch (state) {
? ? ? ? ? ? ? ? case BluetoothDevice.BOND_NONE:
? ? ? ? ? ? ? ? ? ? Log.d(TAG, "BOND_NONE 刪除配對");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case BluetoothDevice.BOND_BONDING:
? ? ? ? ? ? ? ? ? ? Log.d(TAG, "BOND_BONDING 正在配對");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case BluetoothDevice.BOND_BONDED:
? ? ? ? ? ? ? ? ? ? Log.d(TAG, "BOND_BONDED 配對成功");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }else if(action.equals("android.bluetooth.adapter.action.STATE_CHANGED")){
? ? ? ? int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
? ? ? ? ? ? BluetoothAdapter.ERROR);
? ? switch (state) {
? ? ? ? case BluetoothAdapter.STATE_OFF:
? ? ? ? ? ? //Log.d("aaa", "STATE_OFF 手機(jī)藍(lán)牙關(guān)閉");
? ? ? ? ? ? break;
? ? ? ? case BluetoothAdapter.STATE_TURNING_OFF:
? ? ? ? ? ? //Log.d("aaa", "STATE_TURNING_OFF 手機(jī)藍(lán)牙正在關(guān)閉");
? ? ? ? ? ? break;
? ? ? ? case BluetoothAdapter.STATE_ON:
? ? ? ? ? ? //Log.d(TAG, "STATE_ON"+s);
? ? ? ? ?break;
? ? ? ? case BluetoothAdapter.STATE_TURNING_ON:
? ? ? ? ? ? //Log.d("aaa", "STATE_TURNING_ON 手機(jī)藍(lán)牙正在開啟");
? ? ? ? ? ? break;
? ? }
? ? ? ? }else{
Log.d(TAG, action);
}
}
};
5.解配對方法:
try {
? ? ? // pair before connect? ?
? ? ? ? ? BluetoothDevice Vdevice = mAdapter2.getRemoteDevice(BTMAC);
? ? ? if (Vdevice.getBondState() == BluetoothDevice.BOND_BONDED) {? ?
? ? ? ? ? ? ? Method creMethod = BluetoothDevice.class.getMethod("removeBond");? ?
? ? ? ? ? Log.e(TAG, "removeBond");? ?
? ? ? ? ? creMethod.invoke(Vdevice);? ?
? ? ? } else {
? ? ? Log.e(TAG, "un paired");
? ? ? }?
? ? } catch (Exception e) {? ?
? ? ? ? // TODO: handle exception? ?
? ? ? ? e.printStackTrace();? ?
? ? }
三.連接
private int connect(String mac) {//這個(gè)返回int狀態(tài)只是因?yàn)閭€(gè)人項(xiàng)目需要嗅绰,可以自行修改
? ? Log.e("wwww", "start, was connect()? "+isConnection);
? ? if (!this.isConnection ) {
? ? ? ?mBluetoothDevice=mBluetoothAdapter.getRemoteDevice(mac);
? ? ? ? try {
? ? ? ? // 固定的UUID? ? ?串口通信profile
? ? ? ? ? ? final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";? ?
? ? ? ? ? ? UUID uuid = UUID.fromString(SPP_UUID);
? ? ? ? mBluetoothSocket = this.mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
? ? ? ? mBluetoothSocket.connect();
? ? ? ? ? ? outputStream = mBluetoothSocket.getOutputStream();
? ? ? ? ? ? inputStream = mBluetoothSocket.getInputStream();
? ? ? ? ? ? SocketReadThread rt = new SocketReadThread();//這個(gè)用來等待接收對方的數(shù)據(jù)
? ? ? ? ? ? rt.setLocalSocket(inputStream, 1);
? ? ? ? ? ? Thread thread = new Thread(rt);
? ? ? ? ? ? ? ?thread.start();
? ? ? ? ? ? this.isConnection = true;
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? System.out.println("1" + e);
? ? ? ? ? ? return -1;
? ? ? ? }
? ? ? ? Log.e("www", "連接成功!");
? ? ? ? return 0;
? ? } else {
? ? ? ? return 0;
? ? }
}
接收線程:
public class SocketReadThread implements Runnable
? ? {
? ? InputStream input;
? ? int inum = 1;//預(yù)留
? ? ? ? public void setLocalSocket(InputStream is, int num )
? ? ? ? {
? ? ? ? input = is;
? ? ? ? inum = num;
? ? ? ? }
? ? ? ? public void run()
? ? ? ? {
try {
? ? ? ? ? ? DataInputStream dis = new DataInputStream(input);
? ? ? ? ? ? byte[] bytes = new byte[1024];//1k
? ? ? ? ? ? ? ? int readnum=0;
? ? ? ? ? ? while ((readnum=dis.read(bytes)) != -1) {//阻塞
? ? ? ? ? ? ?????printHexString(TAG,bytes);//前面的文章有講過這個(gè)方法
? ? ? ? ? ? ?}
} catch (IOException e) {
Log.d(TAG, "read duankai");
// TODO Auto-generated catch block
e.printStackTrace();
}
}? ?
}
四.發(fā)送數(shù)據(jù)
private boolean send(byte[] sendData) {//這個(gè)返回也是因?yàn)楫?dāng)時(shí)項(xiàng)目需要
? ? if (this.isConnection) {
? ? ? ? try {
? ? ? ? ? ? //byte[] data = sendData.getBytes();//"GBK"
? ? ? ? ? ? outputStream.write(sendData, 0, sendData.length);
? ? ? ? ? ? outputStream.flush();
? ? ? ? ? ? Log.e("com send", "send-flush");
? ? ? ? } catch (IOException e) {
? ? ? ? Log.e("com send", "send-", e);
? ? ? ? return false;
? ? ? ? }
? ? ? ? return true;
? ? } else {
? ? Log.e("com send", "not connection");
? ? return false;
? ? }
}
五.關(guān)閉資源
這些不使用的時(shí)候搀继,沒關(guān)閉也是很耗資源的窘面,不能忘記哈
private void closeBtconnect() {
// TODO Auto-generated method stub
? ? try {
? ? ? ? ? ? if(outputStream!=null){
? ? ? ? ? ? outputStream.close();
? ? ? ? ? ? outputStream=null;
? ? ? ? ? ? }
? ? ? ? ? ? if(inputStream!=null){
? ? ? ? ? ? inputStream.close();
? ? ? ? ? ? inputStream=null;
? ? ? ? ? ? }
? ? ? ? ? ? if(mBluetoothSocket!=null){
? ? ? ? ? ? mBluetoothSocket.close();
? ? ? ? ? ? mBluetoothSocket=null;
? ? ? ? ? ? }
} catch (Exception e) {
// TODO: handle exception
}
? ? ? ? this.isConnection = false;
}
幾個(gè)主要的功能API使用大概如此。就是這個(gè)后臺不適合代碼編排叽躯,簡書需要改進(jìn)才是财边。