new PrinterBle class
This commit is contained in:
parent
37ac5f399a
commit
85f9b96137
@ -24,7 +24,7 @@
|
|||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</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" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
@ -19,7 +19,7 @@ class MainActivity : Activity() {
|
|||||||
val btn: Button by bind(R.id.bt)
|
val btn: Button by bind(R.id.bt)
|
||||||
val connectBtn: Button by bind(R.id.connect)
|
val connectBtn: Button by bind(R.id.connect)
|
||||||
val disconnectBtn: Button by bind(R.id.disconnect)
|
val disconnectBtn: Button by bind(R.id.disconnect)
|
||||||
var ble: BLECls? = null
|
var ble: PrinterBle? = null
|
||||||
val uiHandler: Handler = Handler()
|
val uiHandler: Handler = Handler()
|
||||||
var th: Thread? = null
|
var th: Thread? = null
|
||||||
var thrun: Boolean = false
|
var thrun: Boolean = false
|
||||||
@ -33,7 +33,11 @@ class MainActivity : Activity() {
|
|||||||
connectBtn.isEnabled = true
|
connectBtn.isEnabled = true
|
||||||
disconnectBtn.isEnabled = false
|
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
|
var permissionCheck: Int = 0
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
@ -46,7 +50,7 @@ class MainActivity : Activity() {
|
|||||||
|
|
||||||
btn.setOnClickListener {
|
btn.setOnClickListener {
|
||||||
val txt: String = intxt.text.toString()
|
val txt: String = intxt.text.toString()
|
||||||
ble?.sendLongData(txt.toByteArray())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connectBtn.setOnClickListener {
|
connectBtn.setOnClickListener {
|
||||||
@ -68,40 +72,16 @@ class MainActivity : Activity() {
|
|||||||
|
|
||||||
fun scanConnect() {
|
fun scanConnect() {
|
||||||
if(ble?.init()!!){
|
if(ble?.init()!!){
|
||||||
isInit = true
|
|
||||||
ble?.startScan()
|
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() {
|
fun disconnect() {
|
||||||
thrun = false
|
if(ble?.mState!! == PrinterBle.SCANNING) {
|
||||||
if (ble?.isScanning!!) {
|
|
||||||
ble?.stopScan()
|
ble?.stopScan()
|
||||||
}
|
}
|
||||||
if (ble?.mState == ble?.CONNECTED) {
|
if(ble?.mState!! == PrinterBle.CONNECTED) {
|
||||||
ble?.disconnect()
|
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