new PrinterBle class

This commit is contained in:
Jay 2017-08-22 18:03:42 +08:00
parent 37ac5f399a
commit 85f9b96137
3 changed files with 398 additions and 31 deletions

View File

@ -24,7 +24,7 @@
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@ -19,7 +19,7 @@ class MainActivity : Activity() {
val btn: Button by bind(R.id.bt)
val connectBtn: Button by bind(R.id.connect)
val disconnectBtn: Button by bind(R.id.disconnect)
var ble: BLECls? = null
var ble: PrinterBle? = null
val uiHandler: Handler = Handler()
var th: Thread? = null
var thrun: Boolean = false
@ -33,7 +33,11 @@ class MainActivity : Activity() {
connectBtn.isEnabled = true
disconnectBtn.isEnabled = false
ble = BLECls(this@MainActivity)
ble = PrinterBle(this@MainActivity, "43:43:A1:12:1F:AC", "dd535b71-8f05-4e30-beb0-6fa7ea3dfc3e", "00000002-8f05-4e30-beb0-6fa7ea3dfc3e")
ble?.setOnStateChangeListener {
System.out.println("Now State is >>>> " + it)
}
var permissionCheck: Int = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
@ -46,7 +50,7 @@ class MainActivity : Activity() {
btn.setOnClickListener {
val txt: String = intxt.text.toString()
ble?.sendLongData(txt.toByteArray())
}
connectBtn.setOnClickListener {
@ -67,41 +71,17 @@ class MainActivity : Activity() {
}
fun scanConnect() {
if (ble?.init()!!) {
isInit = true
if(ble?.init()!!){
ble?.startScan()
}
th = Thread(Runnable {
thrun = true
while (thrun) {
System.out.println("state ===== " + ble?.mState)
if (ble?.mState == ble?.CONNECTED) {
uiHandler.post {
btn.isEnabled = true
disconnectBtn.isEnabled = true
connectBtn.isEnabled = false
}
thrun = false
break
}
Thread.sleep(200)
}
})
th?.start()
}
fun disconnect() {
thrun = false
if (ble?.isScanning!!) {
if(ble?.mState!! == PrinterBle.SCANNING) {
ble?.stopScan()
}
if (ble?.mState == ble?.CONNECTED) {
if(ble?.mState!! == PrinterBle.CONNECTED) {
ble?.disconnect()
}
disconnectBtn.isEnabled = false
connectBtn.isEnabled = true
btn.isEnabled = false
isInit = false
}
}

View File

@ -0,0 +1,387 @@
package xyz.mtfos.btdemo;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.ParcelUuid;
import android.util.Log;
import org.apache.commons.lang3.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
* Created by jay on 2017/8/22.
*/
public class PrinterBle {
final private String TAG = "Bluetooth LE Object";
private Context ctx;
private BluetoothAdapter mAdapter;
private BluetoothGatt mBtGatt;
private BluetoothGattCharacteristic printerCharacteristic;
// for android api >= 21 use
private BluetoothLeScanner mLeScanner;
private ScanSettings mLeSettings;
private List<ScanFilter> mLeFilters;
// BLE相關參數
private String macAddr, serviceUUID, characteristicUUID;
// 藍芽狀態列表
final public static int CONNECTING = 0x01;
final public static int CONNECTED = 0x02;
final public static int DISCONNECTED = 0x00;
final public static int SCANNING = 0x03;
// printer 相關參數
final public static int ALIGN_LEFT = 0x00;
final public static int ALIGN_CENTER = 0x01;
final public static int ALIGN_RIGHT = 0x02;
// 藍芽狀態
public int mState = 0x00;
// 藍芽通訊flag
private boolean sending = false;
// 發送內容陣列
private ArrayList<byte[]> sendingQueue = new ArrayList<>();
// 待處理發送陣列
private ArrayList<String> dataQueue = new ArrayList<>();
// Listener Object
private stateChangeListener mStateListener;
private notifyListener mNotifyListener;
public interface stateChangeListener {
void onChange(int state);
}
public interface notifyListener {
void onNotify(String msg);
}
public PrinterBle(Context ctx, String macAddr, String serviceUUID, String characteristicUUID) {
this.ctx = ctx;
this.macAddr = macAddr;
this.serviceUUID = serviceUUID;
this.characteristicUUID = characteristicUUID;
}
private BluetoothGattCallback mBtGattCB = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
Log.d(TAG, "Connect State Change to " + status + " new State : " + newState);
if (status == BluetoothGatt.GATT_SUCCESS) {
if(mState != DISCONNECTED) {
mState = CONNECTED;
Log.d(TAG, "Connected");
}
mStateListener.onChange(mState);
if(mState == CONNECTED) {
mBtGatt.discoverServices();
}
} else if (newState == BluetoothGatt.GATT_FAILURE) {
mState = DISCONNECTED;
Log.d(TAG, "Connect Failed");
mStateListener.onChange(mState);
}
}
// 遠端設備中的服務可用時的回調
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService btService = mBtGatt.getService(UUID.fromString(serviceUUID));
if (btService != null) {
printerCharacteristic = btService.getCharacteristic(UUID.fromString(characteristicUUID));
// set notify enable
mBtGatt.setCharacteristicNotification(printerCharacteristic, true);
}
}
}
// write characteristic callback
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
switch (status) {
case BluetoothGatt.GATT_SUCCESS:
Log.d(TAG, "Write Data Success");
break;
case BluetoothGatt.GATT_FAILURE:
Log.d(TAG, "Write Data Filed");
break;
case BluetoothGatt.GATT_WRITE_NOT_PERMITTED:
Log.d(TAG, "Write not permitted");
break;
}
sending = false;
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
readCharacteristicValue(characteristic);
}
};
/**
* 讀取 BLE characteristic 資料
*
* @param characteristic
*/
private void readCharacteristicValue(BluetoothGattCharacteristic characteristic) {
byte[] data = characteristic.getValue();
StringBuffer buffer = new StringBuffer("0x");
int i;
for (byte b : data) {
i = b & 0xff;
buffer.append(Integer.toHexString(i));
}
Log.d(TAG, "ReadData: " + buffer.toString());
Log.d(TAG, "ReadData(As String): " + new String(data));
mNotifyListener.onNotify(new String(data));
}
/**
* 初始化檢查
*
* @return 檢查成功返回true
*/
public boolean init() {
BluetoothManager btMng = (BluetoothManager) ctx.getSystemService(Context.BLUETOOTH_SERVICE);
if (btMng == null) return false;
mAdapter = btMng.getAdapter();
if (mAdapter == null) return false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mLeScanner = mAdapter.getBluetoothLeScanner();
if (mLeScanner == null) return false;
mLeSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
mLeFilters = new ArrayList<>();
// mLeFilters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUID.fromString(serviceUUID))).build());
}
return true;
}
private BluetoothAdapter.LeScanCallback mLeScanCB = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int rssi, byte[] bytes) {
String devAddr = bluetoothDevice.getAddress();
if (devAddr.equals(macAddr)) {
Log.d(TAG, bluetoothDevice.getName() + " has available service UUID");
// 處理連線配段相關
stopScan();
connect(bluetoothDevice);
}
}
};
private ScanCallback mLeScanCB_21 = new ScanCallback() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void onScanResult(int callbackType, ScanResult result) {
// super.onScanResult(callbackType, result);
BluetoothDevice device = result.getDevice();
Log.d(TAG, "Device : " + device.getName() + " Found\nDeviceMac : " + device.getAddress());
if (device.getAddress().equals(macAddr)) {
// 處理連線配段相關
stopScan();
connect(device);
}
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
Log.d(TAG, "BLE Scan Fail Code : " + errorCode);
}
};
public void startScan() {
if (mAdapter == null) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mLeScanner == null) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.d(TAG, "Start Scanning");
mLeScanner.startScan(mLeFilters, mLeSettings, mLeScanCB_21);
} else {
mAdapter.startLeScan(mLeScanCB);
}
mState = CONNECTING;
}
public void stopScan() {
if (mAdapter == null) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mLeScanner == null) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mLeScanner.stopScan(mLeScanCB_21);
} else {
mAdapter.stopLeScan(mLeScanCB);
}
if (mState == CONNECTING) mState = DISCONNECTED;
}
/**
* 中斷與設備的連線
*/
public void disconnect() {
mState = DISCONNECTED;
if (mBtGatt != null) mBtGatt.disconnect();
}
/**
* 與指定設備建立連線
*
* @param device
*/
public void connect(BluetoothDevice device) {
if (device == null) return;
mBtGatt = device.connectGatt(ctx, false, mBtGattCB);
mState = CONNECTING;
}
public void setOnStateChangeListener(stateChangeListener listener) {
this.mStateListener = listener;
}
public void setOnNotifyListener(notifyListener listener) {
this.mNotifyListener = listener;
}
private void sendData(byte[] data) {
if (data == null || data.length < 1 || data.length > 20) return;
boolean setVal = printerCharacteristic.setValue(data);
boolean sendVal = mBtGatt.writeCharacteristic(printerCharacteristic);
Log.d(TAG, String.format("setVal: %s / sendVal: %s", String.valueOf(setVal), String.valueOf(sendVal)));
}
private void sendQueue() {
if (sendingQueue == null) sendingQueue = new ArrayList<>();
if (dataQueue == null) dataQueue = new ArrayList<>();
if (dataQueue.size() == 0) return;
sendingQueue.clear();
StringBuilder strbuild = new StringBuilder();
for (String s : dataQueue) {
strbuild.append(s);
}
String str = strbuild.toString();
byte[] dataByte = str.getBytes();
pushQueue(new byte[]{0x00});
int idx = 0;
while (true) {
int st = idx * 18;
int ed = idx * 18 + 18;
ed = ed > dataByte.length ? dataByte.length : ed;
byte[] tmp = Arrays.copyOfRange(dataByte, st, ed);
byte[] sdata = new byte[2 + tmp.length];
sdata[1] = (byte) (idx & 0xff);
sdata[0] = (byte) ((idx >> 8) & 0xff);
for (int i = 2; i < sdata.length; i++) {
if (i - 2 >= tmp.length) break;
sdata[i] = tmp[i - 2];
}
pushQueue(sdata);
idx++;
if (ed >= dataByte.length) break;
}
pushQueue(new byte[]{(byte) 0xff});
dataQueue.clear();
}
private void pushQueue(byte[] data) {
if (data == null || data.length == 0) return;
if (sendingQueue == null) sendingQueue = new ArrayList<>();
sendingQueue.add(data);
runQueue();
}
private void runQueue() {
if (sendingQueue == null) sendingQueue = new ArrayList<>();
if (sendingQueue.size() < 1 || sending == true) return;
sending = true;
byte[] d = sendingQueue.get(0);
sendingQueue.remove(0);
sendData(d);
}
public void clearQueue() {
dataQueue.clear();
}
public void textTab() {
addText("\t");
}
public void textNewLine() {
addText("\n");
}
public void addText(String txt) {
if (txt == null || txt.isEmpty()) return;
dataQueue.add(txt);
}
public void addTextln(String txt) {
if (txt == null || txt.isEmpty()) return;
addText(txt + "\n");
}
public void setAlign(int align) {
String strAlign = "";
switch (align) {
case ALIGN_CENTER:
strAlign = "ct";
break;
case ALIGN_LEFT:
strAlign = "lt";
case ALIGN_RIGHT:
strAlign = "rt";
default:
return;
}
addText("__a" + strAlign + "__");
}
public void setSize(int w, int h) {
if (w < 1 || h < 1 || w > 3 || h > 3) return;
addText(String.format("__s%d,%d__", w, h));
}
public void resetSize() {
setSize(1, 1);
}
}