new PrinterBle class
This commit is contained in:
parent
37ac5f399a
commit
85f9b96137
@ -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">
|
||||
|
@ -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
|
||||
}
|
||||
}
|
387
app/src/main/java/xyz/mtfos/btdemo/PrinterBle.java
Normal file
387
app/src/main/java/xyz/mtfos/btdemo/PrinterBle.java
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user