关于安卓蓝牙2.0的app开发原理

最近时间比较宽裕,觉得自己可以写一些东西来总结一下工作,索性就写一篇关于安卓蓝牙的开发总结吧

安卓蓝牙开发其实也就是socket的开发,同时分为服务端和客户端,下面我就按照我的开发流程来降整个的安卓蓝牙2.0开发叙述一下,蓝牙4.0BLE我也会在之后给大家更新

首先,我们要注册蓝牙相关的广播并在manifest中给出相应的权限(安卓6.0之后由于相应的底层改变,注册权限的时候不仅要给蓝牙的权限,还要给相应的位置权限),我在这里只为大家提供相应的广播,权限自己百度吧哈哈:

if (BluetoothDevice. ACTION_FOUND .equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice. EXTRA_DEVICE ); //额外的设备

if (BluetoothAdapter. ACTION_DISCOVERY_FINISHED .equals(action)) {
setSupportProgressBarIndeterminateVisibility( false );
setTitle( "请选择要连接的设备" );
if ( mPairedDevicesArrayAdapter .getCount() == 0 ) {
String noDevices = getResources().getText(R.string. none_found ).toString();
mPairedDevicesArrayAdapter .add(noDevices);//当没有设备的时候
pairedListView .setEnabled( false );
}
}

之后我们需要获得蓝牙模块的mac地址和模块名,所以我们要进行蓝牙设备的查找,在查找界面中 我们使用BluetoothAdapter这个适配器来存储我们搜索的设备,使用Set集合来降获得的设备进行存储通过for循环来循环出手机搜索到的所有设备,代码如下

Set pairedDevices = mBtAdapter .getBondedDevices();
得到的设备名称和设备地址
for (BluetoothDevice device : pairedDevices) {
mPairedDevicesArrayAdapter .add(device.getName() + "( "
+ getResources().getText(R.string. has ) + " )"
+ " \n " + device.getAddress());
}
之后我们会将得到的设备传递到我们的主界面当中,传递使用Intent(感觉是废话)代码如下:
ntent intent = new Intent();
intent.putExtra( EXTRA_DEVICE_ADDRESS , address);
intent.putExtra( EXTRA_RE_PAIR , re_pair);
intent.putExtra( EXTRA_DEVICE_NAME , name);
setResult(Activity. RESULT_OK , intent);
这样关于蓝牙设备的扫描和获取大致已经完成
在我做的app中我已经将蓝牙的打开,关闭,连接,读取,接收做了一个封装类:话不多说直接上代码:
public class BluetoothPort implements BasePrinterPort {
    private static final String TAG = "BluetoothPort";
    private String mDeviceAddress;
    private BluetoothSocket mSocket;
    private BluetoothAdapter mAdapter;
    private static InputStream inputStream;
    private static OutputStream outputStream;
    private Context mContext;
    private Handler mHandler;
    private int mState;
    private BluetoothDevice mDevice;
    private final UUID PRINTER_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

    public BluetoothPort(BluetoothDevice bluetoothDevice, Handler handler) {
        this.mHandler = handler;
        this.mDevice = bluetoothDevice;
        this.mAdapter = BluetoothAdapter.getDefaultAdapter();
        this.mState = 103;
    }

    public BluetoothPort(String address, Handler handler) {
        this.mHandler = handler;
        this.mAdapter = BluetoothAdapter.getDefaultAdapter();
        this.mDevice = this.mAdapter.getRemoteDevice(address);
        this.mState = 103;
    }

    public boolean open() {
        boolean isConnected = false;
        if(this.mState != 103) {
            this.close();
        }

        isConnected = this.connect2Device();
        return isConnected;
    }

    public void close() {
        try {
            if(this.mSocket != null) {
                this.mSocket.close();
            }
        } catch (IOException var2) {
            var2.printStackTrace();
        }

        this.mDevice = null;
        this.mSocket = null;
        if(this.mState != 102) {
            this.setState(103);
        }

    }

    public int write(byte[] srcData) {
        try {
            if(outputStream == null) {
                return -3;
            }

            outputStream.write(srcData);
            outputStream.flush();
        } catch (IOException var3) {
            var3.printStackTrace();
            return -1;
        } catch (Exception var4) {
            var4.printStackTrace();
            return -2;
        }

        return srcData.length;
    }

    public int read(byte[] buffer) {
        int readLen = 0;

        try {
            if(inputStream != null && (readLen = inputStream.available()) > 0) {
                inputStream.read(buffer);
            }

            return readLen;
        } catch (IOException var4) {
            var4.printStackTrace();
            return -1;
        } catch (Exception var5) {
            var5.printStackTrace();
            return -1;
        }
    }

    public int read(int timeout, byte[] buffer) {
        int readLen = -1;

        try {
            while((readLen = inputStream.available()) <= 0) {
                timeout -= 50;
                if(timeout <= 0) {
                    break;
                }

                try {
                    Thread.sleep(50L);
                } catch (InterruptedException var5) {
                    var5.printStackTrace();
                }
            }

            if(readLen > 0) {
                buffer = new byte[readLen];
                inputStream.read(buffer);
            }
        } catch (IOException var6) {
            var6.printStackTrace();
        }

        return readLen;
    }

    private boolean connect2Device() {
        boolean hasError = false;
        if(this.mAdapter.isDiscovering()) {
            this.mAdapter.cancelDiscovery();
        }

        try {
            this.mSocket = this.mDevice.createRfcommSocketToServiceRecord(this.PRINTER_UUID);
            this.mSocket.connect();
        } catch (IOException var9) {
            var9.printStackTrace();

            try {
                if(this.mSocket != null) {
                    this.mSocket.close();
                }

                Thread.sleep(2000L);
            } catch (IOException var7) {
                var7.printStackTrace();
            } catch (InterruptedException var8) {
                var8.printStackTrace();
            }

            hasError = this.ReTryConnect();
        } catch (Exception var10) {
            try {
                if(this.mSocket != null) {
                    this.mSocket.close();
                }

                Thread.sleep(2000L);
            } catch (IOException var5) {
                var5.printStackTrace();
            } catch (InterruptedException var6) {
                var6.printStackTrace();
            }

            hasError = this.ReTryConnect();
        }

        if(!hasError) {
            try {
                inputStream = this.mSocket.getInputStream();
                outputStream = this.mSocket.getOutputStream();
            } catch (IOException var4) {
                hasError = true;
                var4.printStackTrace();
            }
        }

        if(hasError) {
            this.setState(102);
            this.close();
        } else {
            this.setState(101);
        }

        return !hasError;
    }

    @SuppressLint({"NewApi"})
    private boolean ReTryConnect() {
        try {
            if(VERSION.SDK_INT >= 10) {
                this.mSocket = this.mDevice.createInsecureRfcommSocketToServiceRecord(this.PRINTER_UUID);
            } else {
                Method var4 = this.mDevice.getClass().getMethod("createRfcommSocket", new Class[]{Integer.TYPE});
                this.mSocket = (BluetoothSocket)var4.invoke(this.mDevice, new Object[]{Integer.valueOf(1)});
            }

            this.mSocket.connect();
            return false;
        } catch (Exception var41) {
            if(this.mSocket != null) {
                try {
                    this.mSocket.close();
                } catch (IOException var3) {
                    var3.printStackTrace();
                }
            }

            var41.printStackTrace();
            return true;
        }
    }

    private synchronized void setState(int state) {
        if(this.mState != state) {
            this.mState = state;
            if(this.mHandler != null) {
                this.mHandler.obtainMessage(this.mState).sendToTarget();
            }
        }

    }
}

在主界面中,我们需要将之前获得的address和port传递过来并与手机建立相对应的连接,接收address和port的代码我就不贴了,小儿科代码,下面我直接粘贴连接代码:
mDevice = BluetoothAdapter. getDefaultAdapter ().getRemoteDevice( devicesAddress );
2.使用端口打开连接
myPrinter = PrinterInstance_One. getPrinterInstance ( mDevice , mHandler );
3.判断是否连接:
使用线程在连接状态下直接打开连接
private class connectThread extends Thread {
@Override
public void run() {
super .run();
if ( myPrinter != null ) {
isConnected = myPrinter .openConnection();
}
}
}
(其中myPrinter是主要的实现类,我会在最后给大家上传我的GitHub)
蓝牙在连接过程中会涉及到一个配对的过程,所以我们要做出相应的配对检测,来查看所连接的设备是否为一配对设别,如果为新设备,那么我们要让手机提示用户进行配对
判断是否配对:
private void PairOrConnect( boolean pair) {
if (pair) {
IntentFilter boundFilter = new IntentFilter(BluetoothDevice. ACTION_BOND_STATE_CHANGED );
mContext .registerReceiver( boundDeviceReceiver , boundFilter);
boolean success = false ;
try {
Method createBondMethod = BluetoothDevice. class .getMethod( "createBond" );
success = ( boolean ) createBondMethod.invoke( mDevice );
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
new connectThread().start();
}
}

相应的,我们要发送广播来获取设备与手机的配对连接:
   private BroadcastReceiver boundDeviceReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (!mDevice.equals(device)) {
                    return;
                }
                switch (device.getBondState()) {
                    case BluetoothDevice.BOND_BONDING:

                        break;
                    case BluetoothDevice.BOND_BONDED:
                        mContext.unregisterReceiver(boundDeviceReceiver);
                        dialog.show();
                        if (myPrinter != null) {
                            new connectThread().start();
//                            received();
                        }
                        break;
                    case BluetoothDevice.BOND_NONE:
                        mContext.unregisterReceiver(boundDeviceReceiver);
                        break;
                }
            }
        }
    };

这里会看到一个连接线程,主要作用是为连接做的,其中当获取的设备为空的时候,线程直接pass:
private class connectThread extends Thread {
    @Override
    public void run() {
        super.run();
        if (myPrinter != null) {
            isConnected = myPrinter.openConnection();
            
        }
    }

}

关于关闭连接我在我的封装类中已经做了相应的处理,大家直接可以调用close方法来关闭

下面是我的GitHub地址:
https://github.com/wenhao555/USB-BLE-Serial-Printer.git



你可能感兴趣的:(安卓蓝牙2.0开发)