蓝牙连接不稳定修复

This commit is contained in:
fengjignqi
2026-06-10 11:34:47 +08:00
parent 121c69fdfc
commit 2a933d09a4
6 changed files with 711 additions and 30 deletions

View File

@@ -4,7 +4,7 @@
<selectionStates> <selectionStates>
<SelectionState runConfigName="app"> <SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" /> <option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2026-06-06T06:46:42.891310900Z"> <DropdownSelection timestamp="2026-06-10T01:13:16.309557300Z">
<Target type="DEFAULT_BOOT"> <Target type="DEFAULT_BOOT">
<handle> <handle>
<DeviceId pluginId="PhysicalDevice" identifier="serial=D122222104A9" /> <DeviceId pluginId="PhysicalDevice" identifier="serial=D122222104A9" />

View File

@@ -35,6 +35,7 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 蓝牙权限 --> <!-- 蓝牙权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

View File

@@ -7,6 +7,7 @@ import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.util.Log;
import com.ckkj.water.ConstantUtil; import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R; import com.ckkj.water.R;
@@ -15,9 +16,12 @@ import com.ckkj.water.databinding.DeviceConnectLayoutBinding;
import com.ckkj.water.device.mvp.DeviceContract; import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl; import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter; import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.espBle.EspProvisionManager;
import com.ckkj.water.espBle.ProvisionCallback;
import com.ckkj.water.index.entity.WaterDeviceEntity; import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean; import com.ckkj.water.network.BaseBean;
import com.ckkj.water.utils.manager.ActivityManager; import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar; import com.gyf.immersionbar.ImmersionBar;
/** /**
@@ -30,6 +34,14 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
private Handler handler = new Handler(Looper.getMainLooper()); private Handler handler = new Handler(Looper.getMainLooper());
private static final long ANIMATION_DURATION = 5000L; // 5秒 private static final long ANIMATION_DURATION = 5000L; // 5秒
private String mWifiName;
private String mWifiPassword;
private WaterDeviceEntity mBleDeviceEntity;
private EspProvisionManager espProvisionManager;
private boolean isBleConnecting = false;
private boolean isBleConnected = false;
private boolean provisioningStarted = false;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -38,6 +50,14 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
@Override @Override
public void initData(Bundle savedInstanceState) { public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState); super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
mWifiName = bundle.getString("wifi_name", "");
mWifiPassword = bundle.getString("wifi_password", "");
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
}
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG); ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
ImmersionBar.with(this) ImmersionBar.with(this)
.statusBarColor(R.color.color_F9F9F9) .statusBarColor(R.color.color_F9F9F9)
@@ -45,7 +65,10 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
.titleBar(viewBinding.rlTitle) .titleBar(viewBinding.rlTitle)
.init(); .init();
viewBinding.includedTitle.tvTitle.setText(R.string.select_wifi_tip); viewBinding.includedTitle.tvTitle.setText(R.string.select_wifi_tip);
initEspProvision();
startConnectAnimation(); startConnectAnimation();
startProvisionWhenReady();
} }
private void startConnectAnimation() { private void startConnectAnimation() {
@@ -59,16 +82,125 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
} }
viewBinding.linearConnectIng.setVisibility(GONE); viewBinding.linearConnectIng.setVisibility(GONE);
viewBinding.linearSuccess.setVisibility(VISIBLE); viewBinding.linearSuccess.setVisibility(VISIBLE);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
goTo(mContext, DeviceReNameActivity.class,null);
}
},1000);
}, ANIMATION_DURATION); }, ANIMATION_DURATION);
} }
} }
private void initEspProvision() {
espProvisionManager = EspProvisionManager.init(mContext).setCallback(new ProvisionCallback() {
@Override
public void onConnecting() {
isBleConnecting = true;
isBleConnected = false;
Log.i("TEST", "DeviceConnectActivity===== onConnecting");
}
@Override
public void onConnected() {
isBleConnecting = false;
isBleConnected = true;
startProvisionWhenReady();
Log.i("TEST", "DeviceConnectActivity===== onConnected设备连接成功");
}
@Override
public void onProvisioning(int progress) {
Log.i("TEST", "DeviceConnectActivity===== WIFI连接进度 == " + progress);
mProgressLoadingDialog.setProgress(progress);
}
@Override
public void onSuccess(String deviceName, String deviceType) {
Log.i("TEST", "DeviceConnectActivity===== deviceName" + deviceName + "配网成功");
ToastUtil.showShort(mContext, deviceName + "配网成功");
handler.postDelayed(new Runnable() {
@Override
public void run() {
hideDialogLoading();
goTo(mContext, DeviceReNameActivity.class, null);
finish();
}
}, 800);
}
@Override
public void onFailed(int errorCode, String message) {
isBleConnecting = false;
if (errorCode != 0) {
isBleConnected = espProvisionManager != null && espProvisionManager.isConnected();
}
Log.i("TEST", "DeviceConnectActivity===== errorCode == " + errorCode + " message == " + message);
ToastUtil.showShort(mContext, message);
hideDialogLoading();
}
@Override
public void onDisconnected() {
isBleConnecting = false;
isBleConnected = false;
hideDialogLoading();
Log.i("TEST", "DeviceConnectActivity===== onDisconnected");
}
@Override
public void onWifiListReceived(String[] wifiList) {
Log.i("TEST", "DeviceConnectActivity===== onWifiListReceived" + wifiList.toString());
}
@Override
public void onWifiListFailed(String message) {
Log.i("TEST", "DeviceConnectActivity===== onWifiListFailed-Msg==" + message);
}
@Override
public void onProvisioningRejected() {
Log.i("TEST", "DeviceConnectActivity===== onProvisioningRejected");
}
});
}
private void connectBleDevice() {
if (mBleDeviceEntity == null || espProvisionManager == null) {
ToastUtil.showShort(mContext, "\u8bbe\u5907\u8fde\u63a5\u672a\u521d\u59cb\u5316");
return;
}
if (isBleConnected || isBleConnecting) {
return;
}
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
}
private void startProvisionWhenReady() {
if (provisioningStarted || espProvisionManager == null) {
return;
}
isBleConnected = espProvisionManager.isConnected();
if (isBleConnected) {
provisionWifi();
return;
}
if (!isBleConnecting) {
connectBleDevice();
}
}
private void provisionWifi() {
if (provisioningStarted) {
return;
}
if (espProvisionManager == null) {
ToastUtil.showShort(mContext, "设备连接未初始化");
return;
}
if (!espProvisionManager.isConnected()) {
startProvisionWhenReady();
return;
}
provisioningStarted = true;
showProgressLoadingDialog(0);
espProvisionManager.provisionWifi(mWifiName, mWifiPassword);
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
@@ -76,6 +208,10 @@ public class DeviceConnectActivity extends BaseActivity<DeviceConnectLayoutBindi
if (animationDrawable != null && animationDrawable.isRunning()) { if (animationDrawable != null && animationDrawable.isRunning()) {
animationDrawable.stop(); animationDrawable.stop();
} }
if (espProvisionManager != null) {
espProvisionManager.disconnect();
espProvisionManager.setCallback(null);
}
} }
@Override @Override

View File

@@ -57,6 +57,8 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
private EspProvisionManager espProvisionManager; private EspProvisionManager espProvisionManager;
private boolean isBleConnecting = false; private boolean isBleConnecting = false;
private boolean isBleConnected = false; private boolean isBleConnected = false;
private boolean keepBleConnectionForProvision = false;
private Handler bleConnectHandler = new Handler();
@Override @Override
public DevicePresenter createPresenter() { public DevicePresenter createPresenter() {
@@ -67,7 +69,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiScanReceiver = new WifiScanReceiver(); wifiScanReceiver = new SelectWifiActivity.WifiScanReceiver();
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG); ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
} }
@@ -86,7 +88,8 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
if (WITCH_FROM_CODE == 100 && espProvisionManager != null) { bleConnectHandler.removeCallbacksAndMessages(null);
if (WITCH_FROM_CODE == 100 && espProvisionManager != null && !keepBleConnectionForProvision) {
espProvisionManager.disconnect(); espProvisionManager.disconnect();
espProvisionManager.setCallback(null); espProvisionManager.setCallback(null);
} }
@@ -115,7 +118,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
initWifiList(); initWifiList();
if (WITCH_FROM_CODE == 100) { if (WITCH_FROM_CODE == 100) {
initEspProvision(); initEspProvision();
connectBleDevice(); scheduleBleConnect();
} }
} }
@@ -154,7 +157,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
boolean hasPermission = hasRecordPermission(permission); boolean hasPermission = hasRecordPermission(permission);
if(!hasPermission){ if(!hasPermission){
goTo(mContext, PermissionActivity.class,null); goTo(mContext, PermissionActivity.class,null);
}else{ return;
} }
scanWifi(); scanWifi();
break; break;
@@ -168,12 +171,13 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
ToastUtil.showShort(mContext,getString(R.string.toast_select_wifi_psd_tip)); ToastUtil.showShort(mContext,getString(R.string.toast_select_wifi_psd_tip));
return; return;
} }
String wifiPassword = viewBinding.etInputPsd.getText().toString();
if(WITCH_FROM_CODE == 100){ if(WITCH_FROM_CODE == 100){
provisionWifi(); goToDeviceConnect(wifiPassword);
}else{ }else{
Intent intent = new Intent(); Intent intent = new Intent();
intent.putExtra("wifi_name",mWifiName); intent.putExtra("wifi_name",mWifiName);
intent.putExtra("wifi_psd",viewBinding.etInputPsd.getText().toString()); intent.putExtra("wifi_psd",wifiPassword);
setResult(RESULT_OK,intent); setResult(RESULT_OK,intent);
finish(); finish();
} }
@@ -181,6 +185,32 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
} }
} }
private void goToDeviceConnect(String wifiPassword) {
if (espProvisionManager == null) {
initEspProvision();
}
if (mBleDeviceEntity == null) {
ToastUtil.showShort(mContext, "\u8bbe\u5907\u8fde\u63a5\u672a\u521d\u59cb\u5316");
return;
}
isBleConnected = espProvisionManager != null && espProvisionManager.isConnected();
if (!isBleConnected) {
if (!isBleConnecting) {
scheduleBleConnect();
}
ToastUtil.showShort(mContext, "\u8bbe\u5907\u8fde\u63a5\u4e2d\uff0c\u8bf7\u7a0d\u540e\u518d\u8bd5");
return;
}
Bundle bundle = new Bundle();
bundle.putString("wifi_name", mWifiName);
bundle.putString("wifi_password", wifiPassword);
bundle.putSerializable("ble_device_entity", mBleDeviceEntity);
keepBleConnectionForProvision = true;
goTo(mContext, DeviceConnectActivity.class, bundle);
finish();
}
/** /**
* 配置网络 * 配置网络
*/ */
@@ -215,6 +245,8 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
isBleConnecting = false; isBleConnecting = false;
isBleConnected = true; isBleConnected = true;
Log.i("TEST","onConnected设备连接成功"); Log.i("TEST","onConnected设备连接成功");
hideDialogLoading();
ToastUtil.showShort(mContext, "设备连接成功");
} }
@Override @Override
@@ -252,11 +284,13 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
isBleConnected = false; isBleConnected = false;
hideDialogLoading(); hideDialogLoading();
Log.i("TEST","onDisconnected"); Log.i("TEST","onDisconnected");
hideDialogLoading();
ToastUtil.showShort(mContext, "设备已断开");
} }
@Override @Override
public void onWifiListReceived(String[] wifiList) { public void onWifiListReceived(String[] wifiList) {
Log.i("TEST","onWifiListReceived-Msg==" + wifiList.toString());
} }
@Override @Override
@@ -274,6 +308,16 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
/** /**
* 连接设备 * 连接设备
*/ */
private void scheduleBleConnect() {
bleConnectHandler.removeCallbacksAndMessages(null);
bleConnectHandler.postDelayed(new Runnable() {
@Override
public void run() {
connectBleDevice();
}
}, 1000);
}
private void connectBleDevice() { private void connectBleDevice() {
if (WITCH_FROM_CODE != 100 || mBleDeviceEntity == null || espProvisionManager == null) { if (WITCH_FROM_CODE != 100 || mBleDeviceEntity == null || espProvisionManager == null) {
return; return;
@@ -281,6 +325,7 @@ public class SelectWifiActivity extends BaseActivity<DeviceResetWifiBinding, Dev
if (isBleConnected || isBleConnecting) { if (isBleConnected || isBleConnecting) {
return; return;
} }
showLoadingDialog();
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName()); espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
} }

View File

@@ -0,0 +1,386 @@
package com.ckkj.water.device;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import androidx.core.app.ActivityCompat;
import com.ckkj.water.ConstantUtil;
import com.ckkj.water.R;
import com.ckkj.water.base.BaseActivity;
import com.ckkj.water.databinding.DeviceResetWifiBinding;
import com.ckkj.water.device.adapter.WifiListAdapter;
import com.ckkj.water.device.mvp.DeviceContract;
import com.ckkj.water.device.mvp.DeviceImpl;
import com.ckkj.water.device.mvp.DevicePresenter;
import com.ckkj.water.espBle.EspProvisionManager;
import com.ckkj.water.espBle.ProvisionCallback;
import com.ckkj.water.index.entity.WaterDeviceEntity;
import com.ckkj.water.network.BaseBean;
import com.ckkj.water.permission.PermissionActivity;
import com.ckkj.water.utils.manager.ActivityManager;
import com.ckkj.water.utils.manager.ThemeManager;
import com.ckkj.water.utils.show.ToastUtil;
import com.gyf.immersionbar.ImmersionBar;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 配置wifi
*/
public class SelectWifiActivity_copy extends BaseActivity<DeviceResetWifiBinding, DevicePresenter>
implements DeviceContract.DeviceView {
private WifiManager wifiManager;
private WifiListAdapter wifiListAdapter;
private WifiScanReceiver wifiScanReceiver;
//100 来自设备添加, 200 来自设备信息
private int WITCH_FROM_CODE = 100;
private String mWifiName = "";
private WaterDeviceEntity mBleDeviceEntity;
private EspProvisionManager espProvisionManager;
private boolean isBleConnecting = false;
private boolean isBleConnected = false;
@Override
public DevicePresenter createPresenter() {
return new DevicePresenter(new DeviceImpl());
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiScanReceiver = new WifiScanReceiver();
ActivityManager.addActivity(this,getClass().getSimpleName() + "_" + ConstantUtil.ADD_DEVICE_FLAG);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(wifiScanReceiver);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (WITCH_FROM_CODE == 100 && espProvisionManager != null) {
espProvisionManager.disconnect();
espProvisionManager.setCallback(null);
}
}
@Override
public void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
Bundle bundle = getIntent().getExtras();
if(bundle != null){
WITCH_FROM_CODE = bundle.getInt(ConstantUtil.ACTIVITY_NAVIGATE_FLAG);
mBleDeviceEntity = (WaterDeviceEntity) bundle.getSerializable("ble_device_entity");
}
ImmersionBar.with(this)
.statusBarColor(R.color.color_gray_theme)
.statusBarDarkFont(ThemeManager.isAppThemeLight(mContext))
.titleBar(viewBinding.rlTitle)
.init();
if(WITCH_FROM_CODE == 200){
viewBinding.tvNext.setText(getString(R.string.confirm_text));
}
viewBinding.includedTitle.tvTitle.setText(R.string.select_wifi_tip);
initListener();
initWifiList();
if (WITCH_FROM_CODE == 100) {
initEspProvision();
connectBleDevice();
}
}
private void initWifiList() {
wifiListAdapter = new WifiListAdapter(mContext);
viewBinding.rvWifiList.setAdapter(wifiListAdapter);
wifiListAdapter.setOnWifiItemClickListener(wifiName -> {
mWifiName = wifiName;
viewBinding.etWifiName.setText(wifiName);
viewBinding.rvWifiList.setVisibility(View.GONE);
viewBinding.linearWifiInfo.setVisibility(View.VISIBLE);
viewBinding.tvNext.setVisibility(View.VISIBLE);
});
}
private void initListener() {
setClick(viewBinding.includedTitle.imgBack);
setClick(viewBinding.tvSelectWifi);
setClick(viewBinding.tvNext);
}
private void setClick(View view) {
view.setOnClickListener(this::onClick);
}
public void onClick(View view){
switch (view.getId()){
case R.id.img_back:
finish();
break;
case R.id.tv_select_wifi:
String[] permission = {
Manifest.permission.ACCESS_FINE_LOCATION
};
boolean hasPermission = hasRecordPermission(permission);
if(!hasPermission){
goTo(mContext, PermissionActivity.class,null);
}else{
}
scanWifi();
break;
case R.id.tv_next:
if(TextUtils.isEmpty(mWifiName)){
ToastUtil.showShort(mContext,getString(R.string.toast_select_wifi_tip));
return;
}
if(TextUtils.isEmpty(viewBinding.etInputPsd.getText().toString())){
ToastUtil.showShort(mContext,getString(R.string.toast_select_wifi_psd_tip));
return;
}
if(WITCH_FROM_CODE == 100){
provisionWifi();
}else{
Intent intent = new Intent();
intent.putExtra("wifi_name",mWifiName);
intent.putExtra("wifi_psd",viewBinding.etInputPsd.getText().toString());
setResult(RESULT_OK,intent);
finish();
}
break;
}
}
/**
* 配置网络
*/
private void provisionWifi() {
if (espProvisionManager == null) {
ToastUtil.showShort(mContext, "设备连接未初始化");
return;
}
if (!isBleConnected) {
if (!isBleConnecting) {
connectBleDevice();
}
ToastUtil.showShort(mContext, "设备连接中,请稍后再试");
return;
}
showProgressLoadingDialog(0);
espProvisionManager.provisionWifi(mWifiName, viewBinding.etInputPsd.getText().toString());
// goTo(mContext,DeviceConnectActivity.class,null);
}
private void initEspProvision() {
espProvisionManager = EspProvisionManager.init(mContext).setCallback(new ProvisionCallback() {
@Override
public void onConnecting() {
isBleConnecting = true;
isBleConnected = false;
Log.i("TEST","onConnecting");
}
@Override
public void onConnected() {
isBleConnecting = false;
isBleConnected = true;
Log.i("TEST","onConnected设备连接成功");
}
@Override
public void onProvisioning(int progress) {
Log.i("TEST","WIFI连接进度 == " + progress);
mProgressLoadingDialog.setProgress(progress);
}
@Override
public void onSuccess(String deviceName, String deviceType) {
Log.i("TEST","deviceName" + deviceName + "连接成功");
ToastUtil.showShort(mContext, deviceName + "连接成功");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
hideDialogLoading();
}
}, 800);
}
@Override
public void onFailed(int errorCode, String message) {
isBleConnecting = false;
if (errorCode != 0) {
isBleConnected = espProvisionManager != null && espProvisionManager .isConnected();
}
Log.i("TEST","errorCode == " + errorCode + " message == " + message);
ToastUtil.showShort(mContext, message);
hideDialogLoading();
}
@Override
public void onDisconnected() {
isBleConnecting = false;
isBleConnected = false;
hideDialogLoading();
Log.i("TEST","onDisconnected");
}
@Override
public void onWifiListReceived(String[] wifiList) {
}
@Override
public void onWifiListFailed(String message) {
Log.i("TEST","onWifiListFailed-Msg==" + message);
}
@Override
public void onProvisioningRejected() {
Log.i("TEST","onProvisioningRejected");
}
});
}
/**
* 连接设备
*/
private void connectBleDevice() {
if (WITCH_FROM_CODE != 100 || mBleDeviceEntity == null || espProvisionManager == null) {
return;
}
if (isBleConnected || isBleConnecting) {
return;
}
espProvisionManager.connect(mBleDeviceEntity.getMacAddress(), mBleDeviceEntity.getDeviceName());
}
private void scanWifi() {
showLoadingDialog();
viewBinding.tvNext.setVisibility(View.GONE);
if (wifiManager != null && wifiManager.isWifiEnabled()) {
wifiManager.startScan();
} else {
ToastUtil.showShort(mContext, getString(R.string.wifi_not_enabled));
hideDialogLoading();
}
}
private void displayWifiList(List<ScanResult> scanResults) {
Set<String> wifiSet = new HashSet<>();
List<String> wifiNameList = new ArrayList<>();
for (ScanResult result : scanResults) {
String wifiName = result.SSID;
if (wifiName != null && !wifiName.isEmpty() && !wifiSet.contains(wifiName)) {
wifiSet.add(wifiName);
wifiNameList.add(wifiName);
}
}
hideDialogLoading();
if (wifiNameList.isEmpty()) {
ToastUtil.showShort(mContext, getString(R.string.no_wifi_found));
viewBinding.linearWifiInfo.setVisibility(View.VISIBLE);
viewBinding.rvWifiList.setVisibility(View.GONE);
} else {
wifiListAdapter.setData(wifiNameList);
viewBinding.linearWifiInfo.setVisibility(View.GONE);
viewBinding.rvWifiList.setVisibility(View.VISIBLE);
}
}
@Override
public void addDeviceSuccess(BaseBean bean) {
}
@Override
public void getDeviceDetailInfo(WaterDeviceEntity bean) {
}
@Override
public void editDeviceInfoSuccess(BaseBean bean) {
}
@Override
public void deleteDeviceSuccess(BaseBean bean) {
}
@Override
public void turnOnOffDeviceSuccess(BaseBean bean) {
}
private class WifiScanReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
boolean success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);
if (success) {
if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
List<ScanResult> results = wifiManager.getScanResults();
displayWifiList(results);
} else {
ToastUtil.showShort(mContext, getString(R.string.wifi_scan_failed));
}
}
}
}
@Override
public int getLayoutResId(Bundle savedInstanceState) {
return 0;
}
@Override
public void showError(String message) {
ToastUtil.showShort(mContext,message);
}
@Override
public void logOut(BaseBean bean) {
}
}

View File

@@ -36,6 +36,10 @@ public class EspProvisionManager {
private final Context context; private final Context context;
private final Handler mainHandler; private final Handler mainHandler;
private final com.espressif.provisioning.ESPProvisionManager provisionManager; private final com.espressif.provisioning.ESPProvisionManager provisionManager;
private static final long CONNECT_COOLDOWN = 1200L;
private static final long QUICK_DISCONNECT_WINDOW = 3000L;
private static final long RETRY_DELAY = 1200L;
private static final int MAX_CONNECT_RETRY = 2;
private ESPDevice espDevice; private ESPDevice espDevice;
private ProvisionCallback callback; private ProvisionCallback callback;
@@ -47,12 +51,28 @@ public class EspProvisionManager {
private boolean expectDisconnected; // 标记是否预期断开(配网成功后) private boolean expectDisconnected; // 标记是否预期断开(配网成功后)
private String currentDeviceName; private String currentDeviceName;
private String currentDeviceType = ProvisionConfig.TRANSPORT_BLE; private String currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
private BluetoothDevice pendingBluetoothDevice;
private String pendingDeviceName;
private String pendingServiceUuid;
private String pendingProofOfPossession;
private String pendingUserName;
private int pendingSecurityType;
private int connectRetryCount;
private long lastDisconnectTime;
private long connectStartTime;
private final Runnable connectionTimeoutTask = new Runnable() { private final Runnable connectionTimeoutTask = new Runnable() {
@Override @Override
public void run() { public void run() {
if (connecting && !connected) { if (connecting && !connected) {
connecting = false; connecting = false;
disconnectDeviceOnly();
lastDisconnectTime = System.currentTimeMillis();
if (retryConnectIfAllowed()) {
return;
}
resetState(true);
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_TIMEOUT, "蓝牙连接超时"); notifyFailed(ProvisionConfig.ERROR_CONNECT_TIMEOUT, "蓝牙连接超时");
disconnectDeviceOnly(); disconnectDeviceOnly();
} }
@@ -68,6 +88,13 @@ public class EspProvisionManager {
} }
}; };
private final Runnable connectRetryTask = new Runnable() {
@Override
public void run() {
startPendingConnect(false);
}
};
private EspProvisionManager(Context context) { private EspProvisionManager(Context context) {
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
this.mainHandler = new Handler(Looper.getMainLooper()); this.mainHandler = new Handler(Looper.getMainLooper());
@@ -150,32 +177,91 @@ public class EspProvisionManager {
return; return;
} }
String primaryServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid; if (connecting && pendingBluetoothDevice != null
String displayName = !TextUtils.isEmpty(deviceName) ? deviceName : bluetoothDevice.getName(); && TextUtils.equals(pendingBluetoothDevice.getAddress(), bluetoothDevice.getAddress())) {
return;
}
pendingBluetoothDevice = bluetoothDevice;
pendingDeviceName = deviceName;
pendingServiceUuid = TextUtils.isEmpty(serviceUuid) ? ProvisionConfig.SERVICE_UUID : serviceUuid;
pendingProofOfPossession = proofOfPossession == null ? "" : proofOfPossession;
pendingUserName = userName == null ? "" : userName;
pendingSecurityType = securityType;
connectRetryCount = 0;
startPendingConnect(true);
}
private void startPendingConnect(boolean respectCooldown) {
if (pendingBluetoothDevice == null) {
notifyFailed(ProvisionConfig.ERROR_INVALID_DEVICE, "钃濈墮璁惧鏃犳晥");
return;
}
if (provisioning) {
return;
}
mainHandler.removeCallbacks(connectRetryTask);
long elapsedSinceDisconnect = System.currentTimeMillis() - lastDisconnectTime;
if (respectCooldown && lastDisconnectTime > 0 && elapsedSinceDisconnect < CONNECT_COOLDOWN) {
mainHandler.postDelayed(connectRetryTask, CONNECT_COOLDOWN - elapsedSinceDisconnect);
return;
}
String displayName = !TextUtils.isEmpty(pendingDeviceName)
? pendingDeviceName : pendingBluetoothDevice.getName();
currentDeviceName = displayName; currentDeviceName = displayName;
currentDeviceType = ProvisionConfig.TRANSPORT_BLE; currentDeviceType = ProvisionConfig.TRANSPORT_BLE;
ignoreNextDisconnectEvent = espDevice != null; boolean hadActiveDevice = espDevice != null && (connecting || connected || provisioning);
ignoreNextDisconnectEvent = hadActiveDevice;
disconnectDeviceOnly(); disconnectDeviceOnly();
ensureEventBusRegistered(); ensureEventBusRegistered();
espDevice = provisionManager.createESPDevice( espDevice = provisionManager.createESPDevice(
ESPConstants.TransportType.TRANSPORT_BLE, ESPConstants.TransportType.TRANSPORT_BLE,
parseSecurityType(securityType) parseSecurityType(pendingSecurityType)
); );
espDevice.setBluetoothDevice(bluetoothDevice); espDevice.setBluetoothDevice(pendingBluetoothDevice);
espDevice.setPrimaryServiceUuid(primaryServiceUuid); espDevice.setPrimaryServiceUuid(pendingServiceUuid);
espDevice.setDeviceName(displayName); espDevice.setDeviceName(displayName);
espDevice.setProofOfPossession(proofOfPossession == null ? "" : proofOfPossession); espDevice.setProofOfPossession(pendingProofOfPossession);
espDevice.setUserName(userName == null ? "" : userName); espDevice.setUserName(pendingUserName);
connecting = true; connecting = true;
connected = false; connected = false;
provisioning = false; provisioning = false;
connectStartTime = System.currentTimeMillis();
mainHandler.removeCallbacks(connectionTimeoutTask); mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.postDelayed(connectionTimeoutTask, ProvisionConfig.CONNECTION_TIMEOUT); mainHandler.postDelayed(connectionTimeoutTask, ProvisionConfig.CONNECTION_TIMEOUT);
notifyConnecting(); notifyConnecting();
espDevice.connectBLEDevice(bluetoothDevice, primaryServiceUuid); espDevice.connectBLEDevice(pendingBluetoothDevice, pendingServiceUuid);
}
private boolean retryConnectIfAllowed() {
if (pendingBluetoothDevice == null || provisioning || connected) {
return false;
}
if (connectRetryCount >= MAX_CONNECT_RETRY) {
return false;
}
connectRetryCount++;
resetState(true);
mainHandler.removeCallbacks(connectRetryTask);
mainHandler.postDelayed(connectRetryTask, RETRY_DELAY * connectRetryCount);
return true;
}
private void clearPendingConnect() {
pendingBluetoothDevice = null;
pendingDeviceName = null;
pendingServiceUuid = null;
pendingProofOfPossession = null;
pendingUserName = null;
pendingSecurityType = 0;
connectRetryCount = 0;
connectStartTime = 0;
} }
@@ -241,8 +327,11 @@ public class EspProvisionManager {
public void disconnect() { public void disconnect() {
boolean shouldNotify = connected || connecting || provisioning; boolean shouldNotify = connected || connecting || provisioning;
mainHandler.removeCallbacks(connectRetryTask);
disconnectDeviceOnly(); disconnectDeviceOnly();
resetState(); lastDisconnectTime = System.currentTimeMillis();
resetState(true);
clearPendingConnect();
if (shouldNotify) { if (shouldNotify) {
notifyDisconnected(); notifyDisconnected();
} }
@@ -258,8 +347,10 @@ public class EspProvisionManager {
switch (event.getEventType()) { switch (event.getEventType()) {
case ESPConstants.EVENT_DEVICE_CONNECTED: case ESPConstants.EVENT_DEVICE_CONNECTED:
mainHandler.removeCallbacks(connectionTimeoutTask); mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(connectRetryTask);
connecting = false; connecting = false;
connected = true; connected = true;
connectRetryCount = 0;
notifyConnected(); notifyConnected();
break; break;
@@ -270,7 +361,13 @@ public class EspProvisionManager {
connecting = false; connecting = false;
connected = false; connected = false;
provisioning = false; provisioning = false;
lastDisconnectTime = System.currentTimeMillis();
if (wasConnecting && retryConnectIfAllowed()) {
break;
}
if (wasConnecting) { if (wasConnecting) {
resetState(true);
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败"); notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
} else { } else {
notifyFailed(ProvisionConfig.ERROR_PROVISION_FAILED, "设备通信失败"); notifyFailed(ProvisionConfig.ERROR_PROVISION_FAILED, "设备通信失败");
@@ -285,14 +382,27 @@ public class EspProvisionManager {
mainHandler.removeCallbacks(connectionTimeoutTask); mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask); mainHandler.removeCallbacks(provisionTimeoutTask);
boolean shouldNotify = connected || connecting || provisioning; boolean shouldNotify = connected || connecting || provisioning;
resetState(); boolean expectedDisconnect = expectDisconnected;
boolean wasConnecting2 = connecting;
long connectDuration = System.currentTimeMillis() - connectStartTime;
lastDisconnectTime = System.currentTimeMillis();
resetState(true);
if (wasConnecting2 && !expectedDisconnect
&& connectDuration < QUICK_DISCONNECT_WINDOW
&& retryConnectIfAllowed()) {
break;
}
if (wasConnecting2 && !expectedDisconnect) {
clearPendingConnect();
notifyFailed(ProvisionConfig.ERROR_CONNECT_FAILED, "蓝牙连接失败");
break;
}
if (shouldNotify) { if (shouldNotify) {
// 如果是配网成功后的预期断开,不发送断开回调 // 如果是配网成功后的预期断开,不发送断开回调
// 因为 onSuccess 已经通知过了 // 因为 onSuccess 已经通知过了
if (!expectDisconnected) { if (!expectedDisconnect) {
notifyDisconnected(); notifyDisconnected();
} }
expectDisconnected = false; // 重置标志
} }
break; break;
@@ -321,14 +431,17 @@ public class EspProvisionManager {
} }
} }
private void resetState() { private void resetState(boolean clearDevice) {
mainHandler.removeCallbacks(connectionTimeoutTask); mainHandler.removeCallbacks(connectionTimeoutTask);
mainHandler.removeCallbacks(provisionTimeoutTask); mainHandler.removeCallbacks(provisionTimeoutTask);
connecting = false; connecting = false;
connected = false; connected = false;
provisioning = false; provisioning = false;
ignoreNextDisconnectEvent = false; ignoreNextDisconnectEvent = false;
// expectDisconnected 保持不变,用于断开回调判断 expectDisconnected = false;
if (clearDevice) {
espDevice = null;
}
} }
private ESPConstants.SecurityType parseSecurityType(int securityType) { private ESPConstants.SecurityType parseSecurityType(int securityType) {