diff --git a/app/build.gradle b/app/build.gradle
index a2325ab..794f62c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,10 +5,10 @@ android {
defaultConfig {
applicationId "com.espressif.espblufi"
- minSdkVersion 18
+ minSdkVersion 21
targetSdkVersion 29
- versionCode 20
- versionName "1.4.3"
+ versionCode 21
+ versionName "1.5.0"
}
buildTypes {
release {
@@ -30,10 +30,8 @@ dependencies {
implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.preference:preference:1.1.0'
- implementation 'io.reactivex.rxjava2:rxjava:2.2.12'
+ implementation 'io.reactivex.rxjava2:rxjava:2.2.14'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
- implementation 'xxj.phiman:xxjtools:1.0.1'
-
implementation project(':blufilibrary')
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 06f477e..6b3b4d1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -10,9 +10,14 @@
+
+
mCache = new HashMap<>();
-
private SharedPreferences mSettingsShared;
public static BlufiApp getInstance() {
@@ -35,11 +32,9 @@ public void onCreate() {
@Override
public void onTerminate() {
super.onTerminate();
-
- mCache.clear();
}
- public boolean settingsPut(String key, Object value) {
+ public void settingsPut(String key, Object value) {
SharedPreferences.Editor editor = mSettingsShared.edit();
if (value instanceof String) {
editor.putString(key, (String) value);
@@ -59,11 +54,10 @@ public boolean settingsPut(String key, Object value) {
}
editor.putStringSet(key, newSet);
} else {
- return false;
+ throw new IllegalArgumentException("Unsupported value type");
}
editor.apply();
- return true;
}
public Object settingsGet(String key, Object defaultValue) {
diff --git a/app/src/main/java/com/espressif/espblufi/app/BlufiLog.java b/app/src/main/java/com/espressif/espblufi/app/BlufiLog.java
new file mode 100644
index 0000000..96f3819
--- /dev/null
+++ b/app/src/main/java/com/espressif/espblufi/app/BlufiLog.java
@@ -0,0 +1,90 @@
+package com.espressif.espblufi.app;
+
+import android.util.Log;
+
+public class BlufiLog {
+ private final String mTag;
+ private Level mLevel = Level.V;
+
+ /**
+ * @param cls The tag will use simple name of the cls.
+ */
+ public BlufiLog(Class cls) {
+ mTag = String.format("[%s]", cls.getSimpleName());
+ }
+
+ /**
+ * Set the print lowest level. It will set {@link Level#NIL} if the level is null.
+ *
+ * @param level The lowest level can print log.
+ */
+ public void setLevel(Level level) {
+ if (level == null) {
+ mLevel = Level.NIL;
+ } else {
+ mLevel = level;
+ }
+ }
+
+ /**
+ * Send a {@link Level#V} log message.
+ *
+ * @param msg The message you would like logged.
+ */
+ public void v(String msg) {
+ if (mLevel.ordinal() <= Level.V.ordinal()) {
+ Log.v(mTag, msg);
+ }
+ }
+
+ /**
+ * Send a {@link Level#V} log message.
+ *
+ * @param msg The message you would like logged.
+ */
+ public void d(String msg) {
+ if (mLevel.ordinal() <= Level.D.ordinal()) {
+ Log.d(mTag, msg);
+ }
+ }
+
+ /**
+ * Send a {@link Level#I} log message.
+ *
+ * @param msg The message you would like logged.
+ */
+ public void i(String msg) {
+ if (mLevel.ordinal() <= Level.I.ordinal()) {
+ Log.i(mTag, msg);
+ }
+ }
+
+ /**
+ * Send a {@link Level#W} log message.
+ *
+ * @param msg The message you would like logged.
+ */
+ public void w(String msg) {
+ if (mLevel.ordinal() <= Level.W.ordinal()) {
+ Log.w(mTag, msg);
+ }
+ }
+
+ /**
+ * Send a {@link Level#E} log message.
+ *
+ * @param msg The message you would like logged.
+ */
+ public void e(String msg) {
+ if (mLevel.ordinal() <= Level.E.ordinal()) {
+ Log.e(mTag, msg);
+ }
+ }
+
+ /**
+ * The level allow logged
+ */
+ public enum Level {
+ V, D, I, W, E, NIL
+ }
+}
diff --git a/app/src/main/java/com/espressif/espblufi/constants/BlufiConstants.java b/app/src/main/java/com/espressif/espblufi/constants/BlufiConstants.java
index 29ccec1..648f05c 100644
--- a/app/src/main/java/com/espressif/espblufi/constants/BlufiConstants.java
+++ b/app/src/main/java/com/espressif/espblufi/constants/BlufiConstants.java
@@ -17,4 +17,5 @@ public final class BlufiConstants {
public static final int DEFAULT_MTU_LENGTH = 128;
public static final int MIN_MTU_LENGTH = 15;
+ public static final int MAX_MTU_LENGTH = 512;
}
diff --git a/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java b/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java
index 25bd4e8..df447c5 100644
--- a/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java
+++ b/app/src/main/java/com/espressif/espblufi/ui/BlufiActivity.java
@@ -8,7 +8,6 @@
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.graphics.Color;
-import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
@@ -40,15 +39,14 @@
import blufi.espressif.response.BlufiScanResult;
import blufi.espressif.response.BlufiStatusResponse;
import blufi.espressif.response.BlufiVersionResponse;
-import tools.xxj.phiman.log.XxjLog;
+import com.espressif.espblufi.app.BlufiLog;
public class BlufiActivity extends BaseActivity {
private static final int REQUEST_CONFIGURE = 0x20;
- private final XxjLog mLog = new XxjLog(getClass());
+ private final BlufiLog mLog = new BlufiLog(getClass());
private BluetoothDevice mDevice;
- private BluetoothGatt mGatt;
private BlufiClient mBlufiClient;
private volatile boolean mConnected;
@@ -74,6 +72,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
setHomeAsUpEnable(true);
mDevice = getIntent().getParcelableExtra(BlufiConstants.KEY_BLE_DEVICE);
+ assert mDevice != null;
String deviceName = mDevice.getName() == null ? getString(R.string.string_unknown) : mDevice.getName();
setTitle(deviceName);
@@ -132,9 +131,6 @@ protected void onDestroy() {
mBlufiClient.close();
mBlufiClient = null;
}
- if (mGatt != null) {
- mGatt.close();
- }
}
@Override
@@ -169,22 +165,18 @@ private void updateMessage(String message, boolean isNotificaiton) {
/**
* Try to connect device
*/
- private void connectGatt() {
+ private void connect() {
mBlufiConnectBtn.setEnabled(false);
if (mBlufiClient != null) {
mBlufiClient.close();
mBlufiClient = null;
}
- if (mGatt != null) {
- mGatt.close();
- }
- GattCallback callback = new GattCallback();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mGatt = mDevice.connectGatt(this, false, callback, BluetoothDevice.TRANSPORT_LE);
- } else {
- mGatt = mDevice.connectGatt(this, false, callback);
- }
+
+ mBlufiClient = new BlufiClient(getApplicationContext(), mDevice);
+ mBlufiClient.setGattCallback(new GattCallback());
+ mBlufiClient.setBlufiCallback(new BlufiCallbackMain());
+ mBlufiClient.connect();
}
/**
@@ -310,31 +302,14 @@ private void onGattDisconnected() {
* mBlufiClient call onCharacteristicWrite and onCharacteristicChanged is required
*/
private class GattCallback extends BluetoothGattCallback {
- private int mChangedMtu = -1;
-
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String devAddr = gatt.getDevice().getAddress();
mLog.d(String.format(Locale.ENGLISH, "onConnectionStateChange addr=%s, status=%d, newState=%d",
devAddr, status, newState));
- mChangedMtu = -1;
if (status == BluetoothGatt.GATT_SUCCESS) {
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
- int mtu = (int) BlufiApp.getInstance().settingsGet(
- SettingsConstants.PREF_SETTINGS_KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH);
- boolean requestMtu = gatt.requestMtu(mtu);
- if (!requestMtu) {
- mLog.w("Request mtu failed");
- updateMessage(String.format(Locale.ENGLISH, "Request mtu %d failed", mtu), false);
- gatt.discoverServices();
- }
- } else {
- gatt.discoverServices();
- }
-
onGattConnected();
updateMessage(String.format("Connected %s", devAddr), false);
break;
@@ -356,59 +331,24 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
mLog.d(String.format(Locale.ENGLISH, "onMtuChanged status=%d, mtu=%d", status, mtu));
if (status == BluetoothGatt.GATT_SUCCESS) {
- mChangedMtu = mtu;
updateMessage(String.format(Locale.ENGLISH, "Set mtu complete, mtu=%d ", mtu), false);
+
+ if (mtu > 0 && mBlufiClient != null) {
+ int blufiPkgLenLimit = mtu - 3;
+ mLog.d("BluFiClient setPostPackageLengthLimit " + blufiPkgLenLimit);
+ mBlufiClient.setPostPackageLengthLimit(blufiPkgLenLimit);
+ }
} else {
updateMessage(String.format(Locale.ENGLISH, "Set mtu failed, mtu=%d, status=%d", mtu, status), false);
}
- gatt.discoverServices();
+ onGattServiceCharacteristicDiscovered();
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
mLog.d(String.format(Locale.ENGLISH, "onServicesDiscovered status=%d", status));
- if (status == BluetoothGatt.GATT_SUCCESS) {
- BluetoothGattService service = gatt.getService(BlufiConstants.UUID_SERVICE);
- if (service == null) {
- mLog.w("Discover service failed");
- gatt.disconnect();
- updateMessage("Discover service failed", false);
- return;
- }
-
- BluetoothGattCharacteristic writeCharact = service.getCharacteristic(BlufiConstants.UUID_WRITE_CHARACTERISTIC);
- if (writeCharact == null) {
- mLog.w("Get write characteristic failed");
- gatt.disconnect();
- updateMessage("Get write characteristic failed", false);
- return;
- }
-
- BluetoothGattCharacteristic notifyCharact = service.getCharacteristic(BlufiConstants.UUID_NOTIFICATION_CHARACTERISTIC);
- if (notifyCharact == null) {
- mLog.w("Get notification characteristic failed");
- gatt.disconnect();
- updateMessage("Get notification characteristic failed", false);
- return;
- }
-
- updateMessage("Discover service and characteristics success", false);
-
- if (mBlufiClient != null) {
- mBlufiClient.close();
- }
- mBlufiClient = new BlufiClient(gatt, writeCharact, notifyCharact, new BlufiCallbackMain());
- if (mChangedMtu > 0) {
- int blufiPkgLenLimit = mChangedMtu - 3;
- mLog.d("BluFiClient setPostPackageLengthLimit " + blufiPkgLenLimit);
- mBlufiClient.setPostPackageLengthLimit(blufiPkgLenLimit);
- }
-
- gatt.setCharacteristicNotification(notifyCharact, true);
-
- onGattServiceCharacteristicDiscovered();
- } else {
+ if (status != BluetoothGatt.GATT_SUCCESS) {
gatt.disconnect();
updateMessage(String.format(Locale.ENGLISH, "Discover services error status %d", status), false);
}
@@ -416,20 +356,48 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- mLog.d("onCharacteristicWrite " + status);
- // This is requirement
- mBlufiClient.onCharacteristicWrite(gatt, characteristic, status);
+ if (status != BluetoothGatt.GATT_SUCCESS) {
+ gatt.disconnect();
+ updateMessage(String.format(Locale.ENGLISH, "WriteChar error status %d", status), false);
+ }
}
+ }
+ private class BlufiCallbackMain extends BlufiCallback {
@Override
- public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- mLog.d("onCharacteristicChanged");
- // This is requirement
- mBlufiClient.onCharacteristicChanged(gatt, characteristic);
+ public void onGattPrepared(BlufiClient client, BluetoothGatt gatt, BluetoothGattService service,
+ BluetoothGattCharacteristic writeChar, BluetoothGattCharacteristic notifyChar) {
+ if (service == null) {
+ mLog.w("Discover service failed");
+ gatt.disconnect();
+ updateMessage("Discover service failed", false);
+ return;
+ }
+ if (writeChar == null) {
+ mLog.w("Get write characteristic failed");
+ gatt.disconnect();
+ updateMessage("Get write characteristic failed", false);
+ return;
+ }
+ if (notifyChar == null) {
+ mLog.w("Get notification characteristic failed");
+ gatt.disconnect();
+ updateMessage("Get notification characteristic failed", false);
+ return;
+ }
+
+ updateMessage("Discover service and characteristics success", false);
+
+ int mtu = (int) BlufiApp.getInstance().settingsGet(
+ SettingsConstants.PREF_SETTINGS_KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH);
+ boolean requestMtu = gatt.requestMtu(mtu);
+ if (!requestMtu) {
+ mLog.w("Request mtu failed");
+ updateMessage(String.format(Locale.ENGLISH, "Request mtu %d failed", mtu), false);
+ onGattServiceCharacteristicDiscovered();
+ }
}
- }
- private class BlufiCallbackMain extends BlufiCallback {
@Override
public void onNegotiateSecurityResult(BlufiClient client, int status) {
switch (status) {
@@ -546,7 +514,7 @@ private class BlufiButtonListener implements View.OnClickListener, View.OnLongCl
@Override
public void onClick(View v) {
if (v == mBlufiConnectBtn) {
- connectGatt();
+ connect();
} else if (v == mBlufiDisconnectBtn) {
disconnectGatt();
} else if (v == mBlufiSecurityBtn) {
diff --git a/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java b/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java
index 588bda0..5b92939 100644
--- a/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java
+++ b/app/src/main/java/com/espressif/espblufi/ui/ConfigureOptionsActivity.java
@@ -6,7 +6,6 @@
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
-import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
@@ -25,8 +24,12 @@
import com.espressif.espblufi.R;
import com.espressif.espblufi.app.BaseActivity;
+import com.espressif.espblufi.app.BlufiLog;
import com.espressif.espblufi.constants.BlufiConstants;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -39,8 +42,6 @@
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
-import tools.xxj.phiman.log.XxjLog;
-import tools.xxj.phiman.net.XxjNetUtil;
public class ConfigureOptionsActivity extends BaseActivity implements AdapterView.OnItemSelectedListener {
private static final int OP_MODE_POS_STA = 0;
@@ -62,7 +63,7 @@ public class ConfigureOptionsActivity extends BaseActivity implements AdapterVie
private static final String PREF_AP = "blufi_conf_aps";
- private XxjLog mLog = new XxjLog(getClass());
+ private BlufiLog mLog = new BlufiLog(getClass());
private Spinner mDeviceModeSp;
@@ -139,9 +140,9 @@ public void afterTextChanged(Editable s) {
}
});
mStationSsidET.setText(getConnectionSSID());
- WifiInfo info = ((WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE)).getConnectionInfo();
+ WifiInfo info = mWifiManager.getConnectionInfo();
if (info != null) {
- byte[] ssidBytes = XxjNetUtil.getOriginalSsidBytes(info);
+ byte[] ssidBytes = getSSIDRawData(info);
mStationSsidET.setTag(ssidBytes);
}
@@ -153,6 +154,45 @@ public void afterTextChanged(Editable s) {
.subscribe();
}
+ private boolean is5GHz(int freq) {
+ return freq > 4900 && freq < 5900;
+ }
+
+ private byte[] getSSIDRawData(WifiInfo info) {
+ try {
+ Method method = info.getClass().getMethod("getWifiSsid");
+ method.setAccessible(true);
+ Object wifiSsid = method.invoke(info);
+ if (wifiSsid == null) {
+ return null;
+ }
+ method = wifiSsid.getClass().getMethod("getOctets");
+ method.setAccessible(true);
+ return (byte[]) method.invoke(wifiSsid);
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NullPointerException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static byte[] getSSIDRawData(ScanResult scanResult) {
+ try {
+ Field field = scanResult.getClass().getField("wifiSsid");
+ field.setAccessible(true);
+ Object wifiSsid = field.get(scanResult);
+ if (wifiSsid == null) {
+ return null;
+ }
+ Method method = wifiSsid.getClass().getMethod("getOctets");
+ method.setAccessible(true);
+ return (byte[]) method.invoke(wifiSsid);
+ } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
private String getConnectionSSID() {
if (!mWifiManager.isWifiEnabled()) {
return null;
@@ -172,10 +212,6 @@ private String getConnectionSSID() {
}
private int getConnectionFrequncy() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- return -1;
- }
-
if (!mWifiManager.isWifiEnabled()) {
return -1;
}
@@ -214,13 +250,11 @@ public void onItemSelected(AdapterView> parent, View view, int position, long
break;
}
} else if (parent == mSoftapSecuritSP) {
- switch (position) {
- case 0: // OPEN
- mSoftAPPasswordForm.setVisibility(View.GONE);
- break;
- default:
- mSoftAPPasswordForm.setVisibility(View.VISIBLE);
- break;
+ if (position == 0) {
+ // OPEN
+ mSoftAPPasswordForm.setVisibility(View.GONE);
+ } else {
+ mSoftAPPasswordForm.setVisibility(View.VISIBLE);
}
}
}
@@ -323,7 +357,7 @@ private void showWifiListDialog() {
.setSingleChoiceItems(wifiSSIDs, checkedItem, (dialog, which) -> {
mStationSsidET.setText(wifiSSIDs[which]);
ScanResult scanResult = mWifiList.get(which);
- byte[] ssidBytes = XxjNetUtil.getOriginalSsidBytes(scanResult);
+ byte[] ssidBytes = getSSIDRawData(scanResult);
mStationSsidET.setTag(ssidBytes);
dialog.dismiss();
})
@@ -383,7 +417,7 @@ private boolean checkSta(BlufiConfigureParams params) {
}
}
}
- if (XxjNetUtil.is5GHz(freq)) {
+ if (is5GHz(freq)) {
mStationSsidET.setError(getString(R.string.configure_station_wifi_5g_error));
new AlertDialog.Builder(this)
.setMessage(R.string.configure_station_wifi_5g_dialog_message)
diff --git a/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java b/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java
index fd4caa4..833a1d6 100644
--- a/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java
+++ b/app/src/main/java/com/espressif/espblufi/ui/MainActivity.java
@@ -3,8 +3,11 @@
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
@@ -23,6 +26,7 @@
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
+import androidx.core.app.ActivityCompat;
import androidx.core.location.LocationManagerCompat;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@@ -32,6 +36,7 @@
import com.espressif.espblufi.constants.BlufiConstants;
import com.espressif.espblufi.constants.SettingsConstants;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
@@ -41,10 +46,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
-import tools.xxj.phiman.app.XxjPermissionHelper;
-import tools.xxj.phiman.ble.XxjBleScanListener;
-import tools.xxj.phiman.ble.XxjBleUtils;
-import tools.xxj.phiman.log.XxjLog;
+import com.espressif.espblufi.app.BlufiLog;
public class MainActivity extends AppCompatActivity {
private static final long TIMEOUT_SCAN = 4000L;
@@ -54,17 +56,15 @@ public class MainActivity extends AppCompatActivity {
private static final int MENU_SETTINGS = 0x01;
- private final XxjLog mLog = new XxjLog(getClass());
-
- private XxjPermissionHelper mPermissionHelper;
+ private final BlufiLog mLog = new BlufiLog(getClass());
private SwipeRefreshLayout mRefreshLayout;
private RecyclerView mRecyclerView;
- private List mBleList;
+ private List mBleList;
private BleAdapter mBleAdapter;
- private Map mDeviceRssiMap;
+ private Map mDeviceMap;
private ScanCallback mScanCallback;
private String mBlufiFilter;
private volatile long mScanStartTime;
@@ -90,17 +90,10 @@ protected void onCreate(Bundle savedInstanceState) {
mBleAdapter = new BleAdapter();
mRecyclerView.setAdapter(mBleAdapter);
- mDeviceRssiMap = new HashMap<>();
+ mDeviceMap = new HashMap<>();
mScanCallback = new ScanCallback();
- mPermissionHelper = new XxjPermissionHelper(this, REQUEST_PERMISSION);
- mPermissionHelper.setOnPermissionsListener((permission, granted) -> {
- if (granted && permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
- mRefreshLayout.setRefreshing(true);
- scan();
- }
- });
- mPermissionHelper.requestAuthorities(new String[]{Manifest.permission.ACCESS_FINE_LOCATION});
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION);
}
@Override
@@ -113,7 +106,19 @@ protected void onDestroy() {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- mPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ int size = permissions.length;
+ for (int i = 0; i < size; ++i) {
+ String permission = permissions[i];
+ int grant = grantResults[i];
+
+ if (permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)) {
+ if (grant == PackageManager.PERMISSION_GRANTED) {
+ mRefreshLayout.setRefreshing(true);
+ scan();
+ }
+ }
+ }
+
}
@Override
@@ -144,7 +149,9 @@ public boolean onOptionsItemSelected(MenuItem item) {
}
private void scan() {
- if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
+ if (!adapter.isEnabled() || scanner == null) {
Toast.makeText(this, R.string.main_bt_disable_msg, Toast.LENGTH_SHORT).show();
mRefreshLayout.setRefreshing(false);
return;
@@ -161,7 +168,7 @@ private void scan() {
}
}
- mDeviceRssiMap.clear();
+ mDeviceMap.clear();
mBleList.clear();
mBleAdapter.notifyDataSetChanged();
mBlufiFilter = (String) BlufiApp.getInstance().settingsGet(SettingsConstants.PREF_SETTINGS_KEY_BLE_PREFIX,
@@ -169,7 +176,8 @@ private void scan() {
mScanStartTime = SystemClock.elapsedRealtime();
mLog.d("Start scan ble");
- XxjBleUtils.startScanBle(mScanCallback);
+ scanner.startScan(null, new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(),
+ mScanCallback);
mUpdateFuture = mThreadPool.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
@@ -187,14 +195,21 @@ private void scan() {
onIntervalScanUpdate(false);
}
- XxjBleUtils.stopScanBle(mScanCallback);
+ BluetoothLeScanner inScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
+ if (inScanner != null) {
+ inScanner.stopScan(mScanCallback);
+ }
onIntervalScanUpdate(true);
mLog.d("Scan ble thread is interrupted");
});
}
private void stopScan() {
- XxjBleUtils.stopScanBle(mScanCallback);
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
+ if (scanner != null) {
+ scanner.stopScan(mScanCallback);
+ }
if (mUpdateFuture != null) {
mUpdateFuture.cancel(true);
}
@@ -202,11 +217,10 @@ private void stopScan() {
}
private void onIntervalScanUpdate(boolean over) {
- List devices = new LinkedList<>(mDeviceRssiMap.keySet());
+ List devices = new ArrayList<>(mDeviceMap.values());
Collections.sort(devices, (dev1, dev2) -> {
- Integer rssi1 = mDeviceRssiMap.get(dev1);
- Integer rssi2 = mDeviceRssiMap.get(dev2);
- assert rssi1 != null && rssi2 != null;
+ Integer rssi1 = dev1.getRssi();
+ Integer rssi2 = dev2.getRssi();
return rssi2.compareTo(rssi1);
});
runOnUiThread(() -> {
@@ -225,13 +239,13 @@ private void gotoDevice(BluetoothDevice device) {
intent.putExtra(BlufiConstants.KEY_BLE_DEVICE, device);
startActivityForResult(intent, REQUEST_BLUFI);
- mDeviceRssiMap.clear();
+ mDeviceMap.clear();
mBleList.clear();
mBleAdapter.notifyDataSetChanged();
}
private class BleHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
- BluetoothDevice device;
+ ScanResult scanResult;
TextView text1;
TextView text2;
@@ -247,22 +261,38 @@ private class BleHolder extends RecyclerView.ViewHolder implements View.OnClickL
@Override
public void onClick(View v) {
stopScan();
- gotoDevice(device);
+ gotoDevice(scanResult.getDevice());
}
}
- private class ScanCallback implements XxjBleScanListener {
+ private class ScanCallback extends android.bluetooth.le.ScanCallback {
@Override
- public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord, ScanResult scanResult) {
- String name = device.getName();
+ public void onScanFailed(int errorCode) {
+ super.onScanFailed(errorCode);
+ }
+
+ @Override
+ public void onBatchScanResults(List results) {
+ for (ScanResult result : results) {
+ onLeScan(result);
+ }
+ }
+
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ onLeScan(result);
+ }
+
+ private void onLeScan(ScanResult scanResult) {
+ String name = scanResult.getDevice().getName();
if (!TextUtils.isEmpty(mBlufiFilter)) {
if (name == null || !name.startsWith(mBlufiFilter)) {
return;
}
}
- mDeviceRssiMap.put(device, rssi);
+ mDeviceMap.put(scanResult.getDevice().getAddress(), scanResult);
}
}
@@ -277,15 +307,16 @@ public BleHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@Override
public void onBindViewHolder(@NonNull BleHolder holder, int position) {
- BluetoothDevice device = mBleList.get(position);
- holder.device = device;
+ ScanResult scanResult = mBleList.get(position);
+ holder.scanResult = scanResult;
+ BluetoothDevice device = scanResult.getDevice();
String name = device.getName() == null ? getString(R.string.string_unknown) : device.getName();
holder.text1.setText(name);
SpannableStringBuilder info = new SpannableStringBuilder();
info.append("Mac:").append(device.getAddress())
- .append(" RSSI:").append(String.valueOf(mDeviceRssiMap.get(device)));
+ .append(" RSSI:").append(String.valueOf(scanResult.getRssi()));
info.setSpan(new ForegroundColorSpan(0xFF9E9E9E), 0, 21, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
info.setSpan(new ForegroundColorSpan(0xFF8D6E63), 21, info.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
holder.text2.setText(info);
diff --git a/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java b/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java
index 2f037f3..532f3a4 100644
--- a/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java
+++ b/app/src/main/java/com/espressif/espblufi/ui/SettingsActivity.java
@@ -4,7 +4,6 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
@@ -13,7 +12,6 @@
import androidx.appcompat.widget.Toolbar;
import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
import com.espressif.espblufi.R;
@@ -29,7 +27,6 @@
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
-import tools.xxj.phiman.app.XxjAppUtils;
public class SettingsActivity extends BaseActivity {
@@ -56,6 +53,9 @@ public static class SettingsFragment extends PreferenceFragmentCompat implements
private Preference mVersionCheckPref;
private volatile BlufiAppReleaseTask.ReleaseInfo mAppLatestRelease;
+ private long mAppVersionCode;
+ private String mAppVersionName;
+
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.blufi_settings, rootKey);
@@ -67,19 +67,15 @@ public void onCreate(Bundle savedInstanceState) {
mApp = BlufiApp.getInstance();
- findPreference(getString(R.string.settings_version_key)).setSummary(getVersionName());
+ getVersionInfo();
+ findPreference(getString(R.string.settings_version_key)).setSummary(mAppVersionName);
findPreference(getString(R.string.settings_blufi_version_key)).setSummary(BlufiClient.VERSION);
mMtuPref = findPreference(getString(R.string.settings_mtu_length_key));
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- PreferenceCategory blufiCategory = findPreference(getString(R.string.settings_category_blufi_key));
- blufiCategory.removePreference(mMtuPref);
- } else {
- int mtuLen = (int) mApp.settingsGet(KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH);
- mMtuPref.setOnPreferenceChangeListener(this);
- if (mtuLen >= BlufiConstants.MIN_MTU_LENGTH) {
- mMtuPref.setSummary(String.valueOf(mtuLen));
- }
+ int mtuLen = (int) mApp.settingsGet(KEY_MTU_LENGTH, BlufiConstants.DEFAULT_MTU_LENGTH);
+ mMtuPref.setOnPreferenceChangeListener(this);
+ if (mtuLen >= BlufiConstants.MIN_MTU_LENGTH && mtuLen <= BlufiConstants.MAX_MTU_LENGTH) {
+ mMtuPref.setSummary(String.valueOf(mtuLen));
}
mBlePrefixPref = findPreference(getString(R.string.settings_ble_prefix_key));
@@ -90,16 +86,16 @@ public void onCreate(Bundle savedInstanceState) {
mVersionCheckPref = findPreference(getString(R.string.settings_upgrade_check_key));
}
- private String getVersionName() {
- String version;
+ private void getVersionInfo() {
try {
- PackageInfo pi = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
- version = pi.versionName;
+ PackageInfo pi = requireActivity().getPackageManager()
+ .getPackageInfo(requireActivity().getPackageName(), 0);
+ mAppVersionName = pi.versionName;
+ mAppVersionCode = pi.versionCode;
} catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- version = getString(R.string.string_unknown);
+ mAppVersionName = getString(R.string.string_unknown);
+ mAppVersionCode = -1;
}
- return version;
}
@Override
@@ -124,9 +120,7 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
int mtuLen = BlufiConstants.DEFAULT_MTU_LENGTH;
if (!TextUtils.isEmpty(lenStr)) {
int newLen = Integer.parseInt(lenStr);
- if (newLen > BlufiConstants.MIN_MTU_LENGTH) {
- mtuLen = newLen;
- }
+ mtuLen = Math.min(BlufiConstants.MAX_MTU_LENGTH, Math.max(BlufiConstants.MIN_MTU_LENGTH, newLen));
}
mMtuPref.setSummary(String.valueOf(mtuLen));
mApp.settingsPut(KEY_MTU_LENGTH, mtuLen);
@@ -159,13 +153,12 @@ private void checkAppLatestRelease() {
return;
}
- long currentVersion = XxjAppUtils.getVersionCode(getActivity());
long latestVersion = latestRelease.getVersionCode();
- if (latestVersion > currentVersion) {
+ if (latestVersion > mAppVersionCode) {
mVersionCheckPref.setSummary(R.string.settings_upgrade_check_disciver_new);
mAppLatestRelease = latestRelease;
- new AlertDialog.Builder(getActivity())
+ new AlertDialog.Builder(requireActivity())
.setTitle(R.string.settings_upgrade_dialog_title)
.setMessage(R.string.settings_upgrade_dialog_message)
.setNegativeButton(android.R.string.cancel, null)
diff --git a/app/src/main/res/xml/backup_descriptor.xml b/app/src/main/res/xml/backup_descriptor.xml
new file mode 100644
index 0000000..2c0be85
--- /dev/null
+++ b/app/src/main/res/xml/backup_descriptor.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/blufilibrary/build.gradle b/blufilibrary/build.gradle
index 8e3296d..71832ec 100644
--- a/blufilibrary/build.gradle
+++ b/blufilibrary/build.gradle
@@ -6,8 +6,8 @@ android {
defaultConfig {
minSdkVersion 18
targetSdkVersion 29
- versionCode 7
- versionName "2.2.3"
+ versionCode 8
+ versionName "2.3.0"
}
buildTypes {
release {
diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiCallback.java b/blufilibrary/src/main/java/blufi/espressif/BlufiCallback.java
index 29990b4..4d55fe7 100644
--- a/blufilibrary/src/main/java/blufi/espressif/BlufiCallback.java
+++ b/blufilibrary/src/main/java/blufi/espressif/BlufiCallback.java
@@ -1,5 +1,9 @@
package blufi.espressif;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+
import java.util.List;
import blufi.espressif.response.BlufiScanResult;
@@ -24,6 +28,19 @@ public abstract class BlufiCallback {
public static final int CODE_CONF_ERR_POST_STA = -3002;
public static final int CODE_CONF_ERR_POST_SOFTAP = -3003;
+ /**
+ * Callback invoked after BluetoothGattCallback receive onServicesDiscovered
+ *
+ * @param client BlufiClient
+ * @param gatt BluetoothGatt
+ * @param service null if discover Blufi GattService failed
+ * @param writeChar null if discover Blufi write GattCharacteristic failed
+ * @param notifyChar null if discover Blufi notify GattCharacteristic failed
+ */
+ public void onGattPrepared(BlufiClient client, BluetoothGatt gatt, BluetoothGattService service,
+ BluetoothGattCharacteristic writeChar, BluetoothGattCharacteristic notifyChar) {
+ }
+
/**
* Callback invoked when receive Gatt notification
*
@@ -37,14 +54,6 @@ public boolean onGattNotification(BlufiClient client, int pkgType, int subType,
return false;
}
- /**
- * Callback invoked when the client close the Gatt
- *
- * @param client BlufiClient
- */
- public void onGattClose(BlufiClient client) {
- }
-
/**
* Callback invoked when received error code from device
*
diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java b/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java
index a0b658a..e0adb0d 100644
--- a/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java
+++ b/blufilibrary/src/main/java/blufi/espressif/BlufiClient.java
@@ -1,8 +1,8 @@
package blufi.espressif;
-import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattCallback;
+import android.content.Context;
import java.util.List;
@@ -11,55 +11,16 @@
import blufi.espressif.response.BlufiVersionResponse;
public class BlufiClient {
- public static final String VERSION = "2.2.3";
+ public static final String VERSION = BuildConfig.VERSION_NAME;
private BlufiClientImpl mImpl;
- public BlufiClient() {
- mImpl = new BlufiClientImpl(this);
+ public BlufiClient(Context context, BluetoothDevice device) {
+ mImpl = new BlufiClientImpl(this, context, device);
}
- /**
- * The client to data communication with device which run BluFi.
- * When communicate complete, the client should call {@link #close()} to release the resources.
- */
- public BlufiClient(BluetoothGatt gatt, BluetoothGattCharacteristic writeCharact,
- BluetoothGattCharacteristic notiCharact, BlufiCallback callback) {
- mImpl = new BlufiClientImpl(this, gatt, writeCharact, notiCharact, callback);
- }
-
- /**
- * Set BluetoothGatt.
- *
- * @param gatt Device BLE gatt
- */
- public void setBluetoothGatt(BluetoothGatt gatt) {
- mImpl.setBluetoothGatt(gatt);
- }
-
- /**
- * @return BluetoothGatt
- */
- public BluetoothGatt getBluetoothGatt() {
- return mImpl.getBluetoothGatt();
- }
-
- /**
- * Set write BluetoothGattCharacteristic
- *
- * @param characteristic App send data to Device
- */
- public void setWriteGattCharacteristic(BluetoothGattCharacteristic characteristic) {
- mImpl.setWriteGattCharacteristic(characteristic);
- }
-
- /**
- * Set notification BluetoothGattCharacteristic
- *
- * @param characteristic Device send data to App
- */
- public void setNotificationGattCharacteristic(BluetoothGattCharacteristic characteristic) {
- mImpl.setNotificationGattCharacteristic(characteristic);
+ public void setGattCallback(BluetoothGattCallback callback) {
+ mImpl.setGattCallback(callback);
}
/**
@@ -71,6 +32,10 @@ public void setBlufiCallback(BlufiCallback callback) {
mImpl.setBlufiCallback(callback);
}
+ public void connect() {
+ mImpl.connect();
+ }
+
/**
* Close the client
*/
@@ -78,29 +43,6 @@ public void close() {
mImpl.close();
}
- /**
- * Call this function in
- * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt, BluetoothGattCharacteristic)}
- *
- * @param gatt BluetoothGatt
- * @param characteristic BluetoothGattCharacteristic
- */
- public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- mImpl.onCharacteristicChanged(gatt, characteristic);
- }
-
- /**
- * Call this function in
- * {@link BluetoothGattCallback#onCharacteristicWrite(BluetoothGatt, BluetoothGattCharacteristic, int)}
- *
- * @param gatt BluetoothGatt
- * @param characteristic BluetoothGattCharacteristic
- * @param status gatt status
- */
- public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- mImpl.onCharacteristicWrite(gatt, characteristic, status);
- }
-
/**
* Set the maximum length of each packet of data, the excess part will be subcontracted.
*
diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java b/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java
index 6660fc9..67afaec 100644
--- a/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java
+++ b/blufilibrary/src/main/java/blufi/espressif/BlufiClientImpl.java
@@ -1,7 +1,15 @@
package blufi.espressif;
+import android.annotation.TargetApi;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
@@ -46,12 +54,16 @@ class BlufiClientImpl implements BlufiParameter {
private BlufiClient mClient;
+ private Context mContext;
+ private BluetoothDevice mDevice;
+ private BluetoothGattCallback mInnerGattCallback;
+ private volatile BluetoothGattCallback mUserGattCallback;
+ private volatile BlufiCallback mUserBlufiCallback;
+
private BluetoothGatt mGatt;
- private BluetoothGattCharacteristic mWriteCharact;
+ private BluetoothGattCharacteristic mWriteChar;
private final Object mWriteLock;
- private BluetoothGattCharacteristic mNotiCharact;
-
- private volatile BlufiCallback mUserCallback;
+ private BluetoothGattCharacteristic mNotifyChar;
private int mPackageLengthLimit;
@@ -59,9 +71,9 @@ class BlufiClientImpl implements BlufiParameter {
private AtomicInteger mReadSequence;
private LinkedBlockingQueue mAck;
- private volatile BlufiNotiyData mNotiyData;
+ private volatile BlufiNotifyData mNotifyData;
- private byte[] mSecretKeyMD5;
+ private byte[] mAESKey;
private boolean mEncrypted = false;
private boolean mChecksum = false;
@@ -74,8 +86,11 @@ class BlufiClientImpl implements BlufiParameter {
private ExecutorService mThreadPool;
private Handler mUIHandler;
- BlufiClientImpl(BlufiClient client) {
+ BlufiClientImpl(BlufiClient client, Context context, BluetoothDevice device) {
mClient = client;
+ mContext = context;
+ mDevice = device;
+ mInnerGattCallback = new InnerGattCallback();
mPackageLengthLimit = DEFAULT_PACKAGE_LENGTH;
mSendSequence = new AtomicInteger(0);
@@ -91,37 +106,27 @@ class BlufiClientImpl implements BlufiParameter {
mWriteLock = new Object();
}
- BlufiClientImpl(BlufiClient client, BluetoothGatt gatt, BluetoothGattCharacteristic writeCharact,
- BluetoothGattCharacteristic notiCharact, BlufiCallback callback) {
- this(client);
-
- mGatt = gatt;
- mWriteCharact = writeCharact;
- mNotiCharact = notiCharact;
- mUserCallback = callback;
- }
-
- void setBluetoothGatt(BluetoothGatt gatt) {
- mGatt = gatt;
- }
-
- BluetoothGatt getBluetoothGatt() {
- return mGatt;
+ void setGattCallback(BluetoothGattCallback callback) {
+ mUserGattCallback = callback;
}
- void setWriteGattCharacteristic(BluetoothGattCharacteristic characteristic) {
- mWriteCharact = characteristic;
+ void setBlufiCallback(BlufiCallback callback) {
+ mUserBlufiCallback = callback;
}
- void setNotificationGattCharacteristic(BluetoothGattCharacteristic characteristic) {
- mNotiCharact = characteristic;
- }
+ synchronized void connect() {
+ if (mThreadPool == null) {
+ throw new IllegalStateException("The BlufiClient has closed");
+ }
- void setBlufiCallback(BlufiCallback callback) {
- mUserCallback = callback;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ mGatt = mDevice.connectGatt(mContext, false, mInnerGattCallback, BluetoothDevice.TRANSPORT_LE);
+ } else {
+ mGatt = mDevice.connectGatt(mContext, false, mInnerGattCallback);
+ }
}
- void close() {
+ synchronized void close() {
if (mThreadPool != null) {
mThreadPool.shutdownNow();
mThreadPool = null;
@@ -130,14 +135,18 @@ void close() {
mGatt.close();
mGatt = null;
}
- mNotiCharact = null;
- mWriteCharact = null;
+ mNotifyChar = null;
+ mWriteChar = null;
if (mAck != null) {
mAck.clear();
mAck = null;
}
mClient = null;
- mUserCallback = null;
+ mUserBlufiCallback = null;
+ mInnerGattCallback = null;
+ mUserGattCallback = null;
+ mContext = null;
+ mDevice = null;
}
void setPostPackageLengthLimit(int lengthLimit) {
@@ -210,36 +219,6 @@ void execute() {
});
}
- void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- if (characteristic != mNotiCharact) {
- return;
- }
-
- if (mNotiyData == null) {
- mNotiyData = new BlufiNotiyData();
- }
-
- byte[] data = characteristic.getValue();
- // lt 0 is error, eq 0 is complete, gt 0 is continue
- int parse = parseNotification(data, mNotiyData);
- if (parse < 0) {
- onError(BlufiCallback.CODE_INVALID_NOTIFICATION);
- } else if (parse == 0) {
- parseBlufiNotiData(mNotiyData);
- mNotiyData = null;
- }
- }
-
- void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- if (characteristic != mWriteCharact) {
- return;
- }
-
- synchronized (mWriteLock) {
- mWriteLock.notifyAll();
- }
- }
-
private void logd(String msg) {
Log.d(TAG, msg);
}
@@ -301,8 +280,8 @@ private byte[] generateAESIV(int sequence) {
private synchronized void gattWrite(byte[] data) throws InterruptedException {
synchronized (mWriteLock) {
- mWriteCharact.setValue(data);
- mGatt.writeCharacteristic(mWriteCharact);
+ mWriteChar.setValue(data);
+ mGatt.writeCharacteristic(mWriteChar);
mWriteLock.wait();
}
@@ -343,52 +322,43 @@ private boolean postNonData(boolean encrypt, boolean checksum, boolean requireAc
private boolean postContainData(boolean encrypt, boolean checksum, boolean requireAck, int type, byte[] data)
throws InterruptedException {
ByteArrayInputStream dataIS = new ByteArrayInputStream(data);
-
ByteArrayOutputStream postOS = new ByteArrayOutputStream();
-
- for (int b = dataIS.read(); b != -1; b = dataIS.read()) {
- postOS.write(b);
- int postDataLengthLimit = mPackageLengthLimit - PACKAGE_HEADER_LENGTH;
- if (checksum) {
- postDataLengthLimit -= 1;
- }
- if (postOS.size() >= postDataLengthLimit) {
- boolean frag = dataIS.available() > 0;
- if (frag) {
- int frameCtrl = FrameCtrlData.getFrameCTRLValue(encrypt, checksum, DIRECTION_OUTPUT, requireAck, true);
- int sequence = generateSendSequence();
- int totleLen = postOS.size() + dataIS.available();
- byte totleLen1 = (byte) (totleLen & 0xff);
- byte totleLen2 = (byte) ((totleLen >> 8) & 0xff);
- byte[] tempData = postOS.toByteArray();
- postOS.reset();
- postOS.write(totleLen1);
- postOS.write(totleLen2);
- postOS.write(tempData, 0, tempData.length);
- int posDatatLen = postOS.size();
-
- byte[] postBytes = getPostBytes(type, frameCtrl, sequence, posDatatLen, postOS.toByteArray());
- gattWrite(postBytes);
- postOS.reset();
- if (requireAck && !receiveAck(sequence)) {
- return false;
- }
-
- sleep(10L);
- }
+ int postDataLengthLimit = mPackageLengthLimit - PACKAGE_HEADER_LENGTH;
+ if (checksum) {
+ postDataLengthLimit -= 1;
+ }
+ byte[] dateBuf = new byte[postDataLengthLimit];
+ while (true) {
+ int read = dataIS.read(dateBuf, 0, dateBuf.length);
+ if (read == -1) {
+ break;
}
- }
- if (postOS.size() > 0) {
- int frameCtrl = FrameCtrlData.getFrameCTRLValue(encrypt, checksum, DIRECTION_OUTPUT, requireAck, false);
+ postOS.write(dateBuf, 0, read);
+ boolean frag = dataIS.available() > 0;
+ int frameCtrl = FrameCtrlData.getFrameCTRLValue(encrypt, checksum, DIRECTION_OUTPUT, requireAck, frag);
int sequence = generateSendSequence();
- int postDataLen = postOS.size();
-
- byte[] postBytes = getPostBytes(type, frameCtrl, sequence, postDataLen, postOS.toByteArray());
- gattWrite(postBytes);
+ if (frag) {
+ int totalLen = postOS.size() + dataIS.available();
+ byte totalLen1 = (byte) (totalLen & 0xff);
+ byte totalLen2 = (byte) ((totalLen >> 8) & 0xff);
+ byte[] tempData = postOS.toByteArray();
+ postOS.reset();
+ postOS.write(totalLen1);
+ postOS.write(totalLen2);
+ postOS.write(tempData, 0, tempData.length);
+ }
+ byte[] postBytes = getPostBytes(type, frameCtrl, sequence, postOS.size(), postOS.toByteArray());
postOS.reset();
-
- return !requireAck || receiveAck(sequence);
+ gattWrite(postBytes);
+ if (frag) {
+ if (requireAck && !receiveAck(sequence)) {
+ return false;
+ }
+ sleep(10L);
+ } else {
+ return !requireAck || receiveAck(sequence);
+ }
}
return true;
@@ -418,8 +388,8 @@ private byte[] getPostBytes(int type, int frameCtrl, int sequence, int dataLengt
}
if (frameCtrlData.isEncrypted() && data != null) {
- BlufiAES espAES = new BlufiAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence));
- data = espAES.encrypt(data);
+ BlufiAES aes = new BlufiAES(mAESKey, AES_TRANSFORMATION, generateAESIV(sequence));
+ data = aes.encrypt(data);
}
if (data != null) {
byteOS.write(data, 0, data.length);
@@ -433,7 +403,7 @@ private byte[] getPostBytes(int type, int frameCtrl, int sequence, int dataLengt
return byteOS.toByteArray();
}
- private int parseNotification(byte[] response, BlufiNotiyData notification) {
+ private int parseNotification(byte[] response, BlufiNotifyData notification) {
if (response == null) {
logw("parseNotification null data");
return -1;
@@ -472,8 +442,8 @@ private int parseNotification(byte[] response, BlufiNotiyData notification) {
}
if (frameCtrlData.isEncrypted()) {
- BlufiAES espAES = new BlufiAES(mSecretKeyMD5, AES_TRANSFORMATION, generateAESIV(sequence));
- dataBytes = espAES.decrypt(dataBytes);
+ BlufiAES aes = new BlufiAES(mAESKey, AES_TRANSFORMATION, generateAESIV(sequence));
+ dataBytes = aes.decrypt(dataBytes);
}
if (frameCtrlData.isChecksum()) {
@@ -508,11 +478,11 @@ private int parseNotification(byte[] response, BlufiNotiyData notification) {
return frameCtrlData.hasFrag() ? 1 : 0;
}
- private void parseBlufiNotiData(BlufiNotiyData data) {
+ private void parseBlufiNotifyData(BlufiNotifyData data) {
int pkgType = data.getPkgType();
int subType = data.getSubType();
- if (mUserCallback != null) {
- boolean complete = mUserCallback.onGattNotification(mClient, pkgType, subType, data.getDataArray());
+ if (mUserBlufiCallback != null) {
+ boolean complete = mUserBlufiCallback.onGattNotification(mClient, pkgType, subType, data.getDataArray());
if (complete) {
return;
}
@@ -723,8 +693,8 @@ private void parseWifiScanList(byte[] data) {
private void onError(final int errCode) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onError(mClient, errCode);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onError(mClient, errCode);
}
});
}
@@ -757,7 +727,7 @@ private void __negotiateSecurity() {
return;
}
- mSecretKeyMD5 = BlufiMD5.getMD5Bytes(espDH.getSecretKey());
+ mAESKey = BlufiMD5.getMD5Bytes(espDH.getSecretKey());
} catch (Exception e) {
e.printStackTrace();
onNegotiateSecurityResult(BlufiCallback.CODE_NEG_ERR_SECURITY);
@@ -782,8 +752,8 @@ private void __negotiateSecurity() {
private void onNegotiateSecurityResult(final int status) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onNegotiateSecurityResult(mClient, status);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onNegotiateSecurityResult(mClient, status);
}
});
}
@@ -983,8 +953,8 @@ private void __configure(BlufiConfigureParams params) {
private void onConfigureResult(final int status) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onConfigureResult(mClient, status);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onConfigureResult(mClient, status);
}
});
}
@@ -1092,8 +1062,8 @@ private void __requestDeviceVersion() {
private void onVersionResponse(final int status, final BlufiVersionResponse response) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onDeviceVersionResponse(mClient, status, response);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onDeviceVersionResponse(mClient, status, response);
}
});
}
@@ -1116,8 +1086,8 @@ private void __requestDeviceStatus() {
private void onStatusResponse(final int status, final BlufiStatusResponse response) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onDeviceStatusResponse(mClient, status, response);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onDeviceStatusResponse(mClient, status, response);
}
});
}
@@ -1140,8 +1110,8 @@ private void __requestDeviceWifiScan() {
private void onDeviceScanResult(final int status, final List results) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onDeviceScanResult(mClient, status, results);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onDeviceScanResult(mClient, status, results);
}
});
}
@@ -1160,16 +1130,16 @@ private void __postCustomData(byte[] data) {
private void onPostCustomDataResult(final int status, final byte[] data) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onPostCustomDataResult(mClient, status, data);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onPostCustomDataResult(mClient, status, data);
}
});
}
private void onReceiveCustomData(final int status, final byte[] data) {
mUIHandler.post(() -> {
- if (mUserCallback != null) {
- mUserCallback.onReceiveCustomData(mClient, status, data);
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onReceiveCustomData(mClient, status, data);
}
});
}
@@ -1209,4 +1179,145 @@ private void sleep(long timeout) {
Thread.currentThread().interrupt();
}
}
+
+ private class InnerGattCallback extends BluetoothGattCallback {
+
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+ }
+
+ gatt.discoverServices();
+ }
+ }
+
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onConnectionStateChange(gatt, status, newState);
+ }
+ }
+
+ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+ BluetoothGattService service = null;
+ BluetoothGattCharacteristic writeChar = null;
+ BluetoothGattCharacteristic notifyChar = null;
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ service = gatt.getService(BlufiParameter.UUID_SERVICE);
+ if (service != null) {
+ writeChar = service.getCharacteristic(BlufiParameter.UUID_WRITE_CHARACTERISTIC);
+ notifyChar = service.getCharacteristic(BlufiParameter.UUID_NOTIFICATION_CHARACTERISTIC);
+ if (notifyChar != null) {
+ gatt.setCharacteristicNotification(notifyChar, true);
+ }
+ }
+
+ mWriteChar = writeChar;
+ mNotifyChar = notifyChar;
+ }
+
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onServicesDiscovered(gatt, status);
+ }
+ if (mUserBlufiCallback != null) {
+ final BluetoothGattService cbService = service;
+ final BluetoothGattCharacteristic cbWriteChar = writeChar;
+ final BluetoothGattCharacteristic cbNotifyChar = notifyChar;
+ mUIHandler.post(() -> {
+ if (mUserBlufiCallback != null) {
+ mUserBlufiCallback.onGattPrepared(mClient, gatt, cbService, cbWriteChar, cbNotifyChar);
+ }
+ });
+ }
+ }
+
+ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
+ if (characteristic != mNotifyChar) {
+ return;
+ }
+
+ if (mNotifyData == null) {
+ mNotifyData = new BlufiNotifyData();
+ }
+
+ byte[] data = characteristic.getValue();
+ // lt 0 is error, eq 0 is complete, gt 0 is continue
+ int parse = parseNotification(data, mNotifyData);
+ if (parse < 0) {
+ onError(BlufiCallback.CODE_INVALID_NOTIFICATION);
+ } else if (parse == 0) {
+ parseBlufiNotifyData(mNotifyData);
+ mNotifyData = null;
+ }
+
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onCharacteristicChanged(gatt, characteristic);
+ }
+ }
+
+ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ if (characteristic != mWriteChar) {
+ return;
+ }
+
+ synchronized (mWriteLock) {
+ mWriteLock.notifyAll();
+ }
+
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onCharacteristicWrite(gatt, characteristic, status);
+ }
+ }
+
+ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onCharacteristicRead(gatt, characteristic, status);
+ }
+ }
+
+ public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onDescriptorRead(gatt, descriptor, status);
+ }
+ }
+
+ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onDescriptorWrite(gatt, descriptor, status);
+ }
+ }
+
+ public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onReliableWriteCompleted(gatt, status);
+ }
+ }
+
+ public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onReadRemoteRssi(gatt, rssi, status);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onMtuChanged(gatt, mtu, status);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onPhyUpdate(gatt, txPhy, rxPhy, status);
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
+ if (mUserGattCallback != null) {
+ mUserGattCallback.onPhyRead(gatt, txPhy, rxPhy, status);
+ }
+ }
+ }
}
diff --git a/blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java b/blufilibrary/src/main/java/blufi/espressif/BlufiNotifyData.java
similarity index 95%
rename from blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java
rename to blufilibrary/src/main/java/blufi/espressif/BlufiNotifyData.java
index 7bc6309..556cb98 100644
--- a/blufilibrary/src/main/java/blufi/espressif/BlufiNotiyData.java
+++ b/blufilibrary/src/main/java/blufi/espressif/BlufiNotifyData.java
@@ -2,7 +2,7 @@
import java.io.ByteArrayOutputStream;
-public class BlufiNotiyData {
+public class BlufiNotifyData {
private int mTypeValue;
private int mPkgType;
private int mSubType;
@@ -11,7 +11,7 @@ public class BlufiNotiyData {
private ByteArrayOutputStream mDataOS;
- public BlufiNotiyData() {
+ public BlufiNotifyData() {
mDataOS = new ByteArrayOutputStream();
}
diff --git a/build.gradle b/build.gradle
index 5600a93..07aecfa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:3.5.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__cn.md b/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__cn.md
index 6fbf0e7..281d15e 100644
--- a/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__cn.md
+++ b/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__cn.md
@@ -6,50 +6,20 @@
为了方便用户进行 Blufi 的二次开发,我司针对 EspBlufi for Android 提供了一些 API 接口。本文档将对这些接口进行简要介绍。
-## BLE 连接
-
-- 调用 API 发起 BLE 连接,获得 `BluetoothGatt`。
-
- ```java
- BluetoothGatt gatt;
- BluetoothGattCallback gattCallback = ; // 实现 Gatt 回调,可参考 BlufiActivity 内部类 GattCallback
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- gatt = bluetoothDevice.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE);
- } else {
- gatt = bluetoothDevice.connectGatt(context, false, gattCallback);
- }
- ```
-
-- 连接成功后,搜索并获得 `BluetoothGattService`
- - UUID 为 0000ffff-0000-1000-8000-00805f9b34fb
-- 获得 Service 后,获得 `BluetoothGattCharacteristic`
- - App 向 Device 写数据的 `BluetoothGattCharacteristic UUID` 为 0000ff01-0000-1000-8000-00805f9b34fb
- - Device 向 App 推送消息的 `BluetoothGattCharacteristic UUID` 为 0000ff02-0000-1000-8000-00805f9b34fb,使用 Notification 方式
-
## 使用 BlufiClient 与 Device 发起通信
-
- 实例化 BlufiClient
```java
+ BlufiClient client = new BlufiClient(context, device);
+
// BlufiCallback 为抽象类,回调 Device 通信过程中的数据,实现您自己的需求,可参考 BlufiActivity 的内部类 BlufiCallbackMain
BlufiCallback blufiCallback = ;
- BlufiClient client = new BlufiClient(gatt, writeCharact, notifyCharact, blufiCallback);
- ```
+ client.setBlufiCallback(blufiCallback);
- ```java
- // 需要在之前 BluetoothGattCallback 的两个回调方法中调用 Client 的方法
- // 若没用调用实例 BlufiClient 的这两个方法,将无法进行数据通信
-
- @Override
- public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- client.onCharacteristicWrite(gatt, characteristic, status);
- }
-
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- client.onCharacteristicChanged(gatt, characteristic);
- }
+ // Gatt 系统回调
+ BluetoothGattCallback gattCallback = ;
+ client.setGattCallback(gattCallback);
```
- 设置 Blufi 发送数据时每包数据的最大长度
@@ -59,6 +29,14 @@
client.setPostPackageLengthLimit(limit)
```
+- 与 Device 建立连接
+
+ ```java
+ // 若 client 与设备建立连接,client 将主动扫描 Blufi 的服务和特征
+ // 用户在收到 BlufiCallback 回调 onGattPrepared 后才可以与设备发起通信
+ client.connect();
+ ```
+
- 与 Device 协商数据加密
```java
@@ -240,46 +218,47 @@
## BlufiCallback 说明
```java
- // 收到 Device 的通知数据
- // 返回 false 表示处理尚未结束,交给 BlufiClient 继续后续处理
- // 返回 true 表示处理结束,后续将不再解析该数据,也不会调用回调方法
- public boolean onGattNotification(BlufiClient client, int pkgType, int subType, byte[] data) {
- return false;
- }
-
- // BluetoothGatt 关闭时调用
- public void onGattClose(BlufiClient client) {
- }
-
- // 收到 Device 发出的错误代码
- public void onError(BlufiClient client, int errCode) {
- }
-
- // 与 Device 协商加密的结果
- public void onNegotiateSecurityResult(BlufiClient client, int status) {
- }
-
- // 发送配置信息的结果
- public void onConfigureResult(BlufiClient client, int status) {
- }
-
- // 收到 Device 的版本信息
- public void onDeviceVersionResponse(BlufiClient client, int status, BlufiVersionResponse response) {
- }
-
- // 收到 Device 的状态信息
- public void onDeviceStatusResponse(BlufiClient client, int status, BlufiStatusResponse response) {
- }
-
- // 收到 Device 扫描到的 Wi-Fi 信息
- public void onDeviceScanResult(BlufiClient client, int status, List results) {
- }
-
- // 发送自定义数据的结果
- public void onPostCustomDataResult(BlufiClient client, int status, byte[] data) {
- }
-
- // 收到 Device 的自定义信息
- public void onReceiveCustomData(BlufiClient client, int status, byte[] data) {
- }
+// 当扫描 Gatt 服务结束后调用该方法
+// service, writeChar, notifyChar 中有 null 的时候表示扫描失败
+public void onGattPrepared(BlufiClient client, BluetoothGatt gatt, BluetoothGattService service, BluetoothGattCharacteristic writeChar, BluetoothGattCharacteristic notifyChar) {
+}
+
+// 收到 Device 的通知数据
+// 返回 false 表示处理尚未结束,交给 BlufiClient 继续后续处理
+// 返回 true 表示处理结束,后续将不再解析该数据,也不会调用回调方法
+public boolean onGattNotification(BlufiClient client, int pkgType, int subType, byte[] data) {
+ return false;
+}
+
+// 收到 Device 发出的错误代码
+public void onError(BlufiClient client, int errCode) {
+}
+
+// 与 Device 协商加密的结果
+public void onNegotiateSecurityResult(BlufiClient client, int status) {
+}
+
+// 发送配置信息的结果
+public void onConfigureResult(BlufiClient client, int status) {
+}
+
+// 收到 Device 的版本信息
+public void onDeviceVersionResponse(BlufiClient client, int status, BlufiVersionResponse response) {
+}
+
+// 收到 Device 的状态信息
+public void onDeviceStatusResponse(BlufiClient client, int status, BlufiStatusResponse response) {
+}
+
+// 收到 Device 扫描到的 Wi-Fi 信息
+public void onDeviceScanResult(BlufiClient client, int status, List results) {
+}
+
+// 发送自定义数据的结果
+public void onPostCustomDataResult(BlufiClient client, int status, byte[] data) {
+}
+
+// 收到 Device 的自定义信息
+public void onReceiveCustomData(BlufiClient client, int status, byte[] data) {
+}
```
\ No newline at end of file
diff --git a/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__en.md b/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__en.md
index 978d13e..9eb738f 100644
--- a/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__en.md
+++ b/doc/Introduction_to_the_EspBlufi_API_Interface_for_Android__en.md
@@ -4,36 +4,20 @@
------
This guide is a basic introduction to the APIs provided by Espressif to facilitate the customers' secondary development of BluFi.
-## BLE Connection
-
-- Call API to establish a BLE connection and obtain `BluetoothGatt`.
-
- ```java
- BluetoothGatt gatt;
- BluetoothGattCallback gattCallback = ; // Gatt callback. Please refer to the GattCallback inner class in BlufiActivity.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- gatt = bluetoothDevice.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE);
- } else {
- gatt = bluetoothDevice.connectGatt(context, false, gattCallback);
- }
- ```
-
-- After the connection is established, discover `BluetoothGattService`.
- - UUID is 0000ffff-0000-1000-8000-00805f9b34fb
-- After the service is discovered, obtain `BluetoothGattCharacteristic`.
- - `BluetoothGattCharacteristic UUID` 0000ff01-0000-1000-8000-00805f9b34fb is used by the app to write data to the device.
- - `BluetoothGattCharacteristic UUID` 0000ff02-0000-1000-8000-00805f9b34fb is used by the device to send data/notification to the app.
-
## Communicate with the device using BlufiClient
-
- Create a BlufiClient instance
```java
- // BlufiCallback is declared as an abstract class, which can be used to notify the app of the data sent by the device. Please refer to the BlufiCallbackMain inner class in BlufiActivity.
+ BlufiClient client = new BlufiClient(context, device);
+ // BlufiCallback is declared as an abstract class, which can be used to notify the app of the data sent by the device. Please refer to the BlufiCallbackMain inner class in BlufiActivity.
BlufiCallback blufiCallback = ;
- BlufiClient client = new BlufiClient(gatt, writeCharact, notifyCharact, blufiCallback);
+ client.setBlufiCallback(blufiCallback);
+
+ // Gatt system callback
+ BluetoothGattCallback gattCallback = ;
+ client.setGattCallback(gattCallback);
```
```java
@@ -57,6 +41,14 @@ This guide is a basic introduction to the APIs provided by Espressif to facilita
client.setPostPackageLengthLimit(limit)
```
+- Establish a BLE connection
+
+ ```java
+ // If establish connection successfully,client will discover service and characteristic for Blufi
+ // client can communicate with Device after receive callback function 'onGattPrepared' in BlufiCallback
+ client.connect();
+ ```
+
- Negotiate data security with the device
```java
@@ -235,6 +227,11 @@ This guide is a basic introduction to the APIs provided by Espressif to facilita
## Notes on BlufiCallback
```java
+// Discover Gatt service over
+// Discover failed if service, writeChar or notifyChar is null
+public void onGattPrepared(BlufiClient client, BluetoothGatt gatt, BluetoothGattService service, BluetoothGattCharacteristic writeChar, BluetoothGattCharacteristic notifyChar) {
+}
+
// Receive the notification of the device
// false indicates that the processing has not been completed yet and that the procewssing will be transferred to BlufiClient.
// true indicates that the processing has been completed and there will be no data processing or function calling afterwards.
@@ -242,10 +239,6 @@ public boolean onGattNotification(BlufiClient client, int pkgType, int subType,
return false;
}
-// Call this function after BluetoothGatt has been closed
-public void onGattClose(BlufiClient client) {
-}
-
// Error code sent by the device
public void onError(BlufiClient client, int errCode) {
}
diff --git a/log/updatelog-en.md b/log/updatelog-en.md
index 926fa93..bdaebd6 100644
--- a/log/updatelog-en.md
+++ b/log/updatelog-en.md
@@ -2,6 +2,11 @@
# Update Log
+## v1.5.0
+- Update BlufiClient APIs
+- Update development [doc](../doc)
+- Change minSdkVersion to 21 (Android 5.0)
+
## v1.4.3
- Make blufilibrary module fully independent, delete apptools module
- Change targetSdkVersion to Android Q(29)
diff --git a/log/updatelog-zh-rCN.md b/log/updatelog-zh-rCN.md
index 638a141..837e8db 100644
--- a/log/updatelog-zh-rCN.md
+++ b/log/updatelog-zh-rCN.md
@@ -2,6 +2,11 @@
# 更新日志
+## v1.5.0
+- BlufiClient 接口已升级
+- 开发文档已更新 [doc](../doc)
+- 最低支持版本改为 Android 5.0 (Api Level 21)
+
## v1.4.3
- 将 blufilibrary 模块改为完全独立的模块, 删除 apptools 模块
- 将 targetSdkVersion 改为 Android Q(29)