diff --git a/app/src/main/java/com/abbidot/tracker/adapter/ScanDeviceAdapter.kt b/app/src/main/java/com/abbidot/tracker/adapter/ScanDeviceAdapter.kt new file mode 100644 index 0000000..1cc569c --- /dev/null +++ b/app/src/main/java/com/abbidot/tracker/adapter/ScanDeviceAdapter.kt @@ -0,0 +1,44 @@ +package com.abbidot.tracker.adapter + +import android.content.Context +import android.view.View +import androidx.core.content.ContextCompat +import com.abbidot.baselibrary.constant.ConState +import com.abbidot.baselibrary.list.BaseRecyclerAdapter +import com.abbidot.baselibrary.list.RecyclerViewHolder +import com.abbidot.tracker.R +import com.abbidot.tracker.bean.DeviceBean + +/** + *Created by .yzq on 2025/12/19/周五. + * @link + * @description: + */ +class ScanDeviceAdapter( + ctx: Context, list: MutableList? +) : BaseRecyclerAdapter(ctx, list) { + + var isConnect = false + + override fun getEmptyLayoutId(viewType: Int) = 0 + + override fun getItemLayoutId(viewType: Int) = R.layout.layout_san_device_item + + override fun bindData(holder: RecyclerViewHolder?, position: Int, item: DeviceBean) { + holder?.let { + it.getTextView(R.id.tv_add_new_tracker3_device_out_id_item).apply { + text = item.deviceOutId + val tColor = if (isConnect) { + R.color.line_color1 + } else { + R.color.data_black_color + } + setTextColor(ContextCompat.getColor(mContext, tColor)) + } + + holder.getView(R.id.ld_add_new_tracker3_connect_state).visibility = + if (item.conState == ConState.CONNECTING) View.VISIBLE + else View.GONE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt index 3b14216..652ed42 100644 --- a/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt +++ b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt @@ -26,9 +26,11 @@ import androidx.core.view.WindowInsetsCompat import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import androidx.viewbinding.ViewBinding +import com.abbidot.baselibrary.constant.MMKVKey import com.abbidot.baselibrary.network.exception.ErrorCode import com.abbidot.baselibrary.util.AppUtils import com.abbidot.baselibrary.util.LogUtil +import com.abbidot.baselibrary.util.MMKVUtil import com.abbidot.tracker.R import com.abbidot.tracker.constant.ConstantInt import com.abbidot.tracker.constant.GetResultCallback @@ -94,6 +96,7 @@ abstract class BaseActivity(val inflater: (inflater: LayoutInfl //防止按钮多次点击 private var mLimitExecutionTime = 0L + var checkCrash = true override fun onCreate(savedInstanceState: Bundle?) { isFrontRunning = true @@ -195,6 +198,11 @@ abstract class BaseActivity(val inflater: (inflater: LayoutInfl * 初始化 */ open fun initData() { + if (checkCrash) { + //出现闪退,退出当前页面 + val isCrash = MMKVUtil.getBoolean(MMKVKey.isCrash, false) + if (isCrash) finish() + } //沉浸式状态栏 QMUIStatusBarHelper.translucent(window) //判断是否是深色模式 @@ -560,6 +568,7 @@ abstract class BaseActivity(val inflater: (inflater: LayoutInfl //拦截请求异常code if (netErrorCodeTips(exceptionCode)) { //已经处理相关错误码就直接返回 + getResultCallback.onErrorCode() return } } diff --git a/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt b/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt index 43ec746..6341cd9 100644 --- a/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt +++ b/app/src/main/java/com/abbidot/tracker/constant/GetResultCallback.kt @@ -9,5 +9,6 @@ interface GetResultCallback { fun onResult(any: Any) //默认可以不重写,相当于java中的default修饰的 - fun onRequestError(exceptionCode:String?) {} + fun onRequestError(exceptionCode: String?) {} + fun onErrorCode() {} } \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt index 1618f2f..1a43f9b 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt @@ -124,6 +124,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding override fun initData() { isEdgeToEdgeAdapterNavigationBars = false + checkCrash=false super.initData() setStatusBarLight() @@ -168,7 +169,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding MMKVUtil.putBoolean(MMKVKey.isCrash, false) showToast(R.string.txt_show_crash) mCountdownType = ConstantInt.Type0 - mCountDownTimerViewModel.startCountDown(5) + mCountDownTimerViewModel.startCountDown(4) } else { val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager val networkCallback: ConnectivityManager.NetworkCallback = diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker1Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker1Activity.kt index cd28245..272be71 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker1Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker1Activity.kt @@ -94,7 +94,7 @@ class AddNewTracker1Activity : */ private fun checkPermissions() { Util.checkBluetoothPermissionsEnabled(mContext, { - val intent = Intent(mContext, AddNewTracker2Activity::class.java) + val intent = Intent(mContext, AddNewTracker3Activity::class.java) intent.putExtra(ConstantString.isFirstBind, isFirstBind) startActivity(intent) }) diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker3Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker3Activity.kt index d7b45c6..676b061 100644 --- a/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker3Activity.kt +++ b/app/src/main/java/com/abbidot/tracker/ui/activity/device/AddNewTracker3Activity.kt @@ -1,144 +1,236 @@ package com.abbidot.tracker.ui.activity.device +import android.animation.AnimatorSet import android.content.Intent import android.text.TextUtils import android.view.View -import android.widget.NumberPicker import androidx.activity.viewModels import com.abbidot.baselibrary.constant.ConState import com.abbidot.baselibrary.constant.EventName import com.abbidot.baselibrary.eventbus.XEventBus +import com.abbidot.baselibrary.list.BaseRecyclerAdapter +import com.abbidot.baselibrary.util.LogUtil import com.abbidot.tracker.R +import com.abbidot.tracker.adapter.ScanDeviceAdapter import com.abbidot.tracker.base.BaseActivity +import com.abbidot.tracker.base.BaseDialog import com.abbidot.tracker.bean.BleTrackDeviceBean -import com.abbidot.tracker.bean.DataBean -import com.abbidot.tracker.constant.ConstantInt +import com.abbidot.tracker.bean.DeviceBean import com.abbidot.tracker.constant.ConstantString import com.abbidot.tracker.constant.GetResultCallback import com.abbidot.tracker.databinding.ActivityAddNewTracker3Binding -import com.abbidot.tracker.util.Util import com.abbidot.tracker.util.ViewUtil import com.abbidot.tracker.util.bluetooth.SRBleUtil import com.abbidot.tracker.vm.ConnectionDeviceViewModel import com.abbidot.tracker.vm.TrackerSetViewModel +import com.clj.fastble.BleManager +import com.clj.fastble.callback.BleScanCallback +import com.clj.fastble.data.BleDevice +import com.clj.fastble.scan.BleScanRuleConfig +import com.clj.fastble.utils.HexUtil +import com.qmuiteam.qmui.util.QMUIDisplayHelper class AddNewTracker3Activity : - BaseActivity(ActivityAddNewTracker3Binding::inflate), - NumberPicker.OnValueChangeListener { + BaseActivity(ActivityAddNewTracker3Binding::inflate) { private val mTrackerSetViewModel: TrackerSetViewModel by viewModels() private val mConnectionDeviceViewModel: ConnectionDeviceViewModel by viewModels() private var isFirstBind = false - private var mDeviceOutId = "" private var mDeviceId = "" - private var mScanDeviceList: ArrayList? = null + private var mDeviceOutId = "" private var mConBleMac = "" + private lateinit var mScanDeviceAdapter: ScanDeviceAdapter + + private var mAnimatorSet: AnimatorSet? = null + override fun getTopBar() = mViewBinding.ilAddNewTracker3TopBar.titleTopBar override fun initData() { super.initData() setTopBarTitle(R.string.txt_add_new_tracker) setLeftBackImage(R.drawable.icon_white_back_svg) - mRightImageButton = addRightImageButton(R.drawable.icon_refresh) intent.extras?.apply { isFirstBind = getBoolean(ConstantString.isFirstBind, false) - mDeviceOutId = getString(ConstantString.DeviceOutId, "") - mScanDeviceList = Util.getParcelableArrayListAdaptive( - intent, ConstantString.DeviceInfo, DataBean::class.java - ) } - if (null == mScanDeviceList) finish() - - mViewBinding.apply { - - mScanDeviceList?.let { - if (it.size == 1) { - mDeviceOutId = it[0].name - tvAddNewTracker3DeviceOutId.visibility = View.VISIBLE - rlAddNewTracker3DeviceLayout.visibility = View.GONE - tvAddNewTracker3DeviceOutId.text = mDeviceOutId - } else if (it.size > 1) { - mDeviceOutId = it[0].name - val deviceOutIds = mutableListOf() - for (d in it) { - deviceOutIds.add(d.name) - } - tvAddNewTracker3DeviceOutId.visibility = View.GONE - rlAddNewTracker3DeviceLayout.visibility = View.VISIBLE - npAddNewTracker3DeviceList.let { np -> - ViewUtil.instance.setNumberPickerAttributes( - mContext, - np, - 0, - it.size - 1, - 0, - 26, - valueChangeListener = this@AddNewTracker3Activity, - removeUpDownLine = true, - loopSelector = false - ) - np.displayedValues = deviceOutIds.toTypedArray() - } - } - } - - setOnClickListenerViews(btnPairTrackerNo, btnPairTrackerYes, mRightImageButton) - } - } - - override fun liveDataObserve() { - //接收蓝牙连接状态 - XEventBus.observe(this, EventName.ConnectDeviceState) { ble: BleTrackDeviceBean -> - setButtonEnabled(mViewBinding.btnPairTrackerYes, ConstantInt.Type1) - if (ble.conState == ConState.CONNECTED) { - mConBleMac = ble.mac - val intent = Intent(mContext, AddPairedSuccessActivity::class.java) - intent.putExtra(ConstantString.DeviceOutId, mDeviceOutId) - intent.putExtra(ConstantString.isFirstBind, isFirstBind) - intent.putExtra(ConstantString.DeviceId, mDeviceId) - intent.putExtra(ConstantString.Mac, ble.mac) - startActivity(intent) - } - } - //搜索蓝牙的设备状态 - XEventBus.observe(this, EventName.ActionConDeviceState) { conState: Int -> - if (conState == ConState.DEVICE_NOT_FOUND) { - setButtonEnabled(mViewBinding.btnPairTrackerYes, ConstantInt.Type1) - showToast(R.string.txt_ble_connect_fail) - } - } - - XEventBus.observe(this, EventName.RefreshDevice) { - finish() - } - - mTrackerSetViewModel.mAddBindDeviceLiveData.observe(this) { - setButtonEnabled(mViewBinding.btnPairTrackerYes, ConstantInt.Type1) - dealRequestResult(it, object : GetResultCallback { - override fun onResult(any: Any) { - it.getOrNull()?.apply { - mDeviceId = deviceId - setButtonEnabled(mViewBinding.btnPairTrackerYes, ConstantInt.Type0) - //连接蓝牙,方便发送激活指令 - mConnectionDeviceViewModel.connectDeviceToDeviceOutId( + mScanDeviceAdapter = ScanDeviceAdapter(mContext, mutableListOf()).apply { + setOnItemClickListener(object : BaseRecyclerAdapter.OnItemClickListener { + override fun onItemClick(itemView: View?, pos: Int) { + if (isConnect) return + SRBleUtil.instance.cancelBleScan("AddNewTracker2Activity,开始连接蓝牙,取消蓝牙扫描") + disconnectBle() + getData().let { + isConnect = true + it[pos].conState = ConState.CONNECTING + notifyItemRangeChanged(0, it.size) + mDeviceOutId = it[pos].deviceOutId + mConBleMac = it[pos].macId + mTrackerSetViewModel.bindDevice( this@AddNewTracker3Activity, mDeviceOutId ) } } }) } + mViewBinding.apply { + ViewUtil.instance.setRecyclerViewVerticalLinearLayout( + mContext, + rvAddNewTracker3DeviceList, + mScanDeviceAdapter, + top = QMUIDisplayHelper.dpToPx(12) + ) + + setOnClickListenerViews(ivAddNewTracker3RefreshBtn) + } + startScanBle() } - override fun onValueChange(picker: NumberPicker?, oldVal: Int, newVal: Int) { - mScanDeviceList?.let { - mDeviceOutId = it[newVal].name + override fun liveDataObserve() { + //接收蓝牙连接状态 + XEventBus.observe(this, EventName.ConnectDeviceState) { ble: BleTrackDeviceBean -> + if (mConBleMac == ble.mac) { + if (ble.conState == ConState.CONNECTED) { + setNoConnectState() + val intent = Intent(mContext, AddPairedSuccessActivity::class.java) + intent.putExtra(ConstantString.DeviceOutId, mDeviceOutId) + intent.putExtra(ConstantString.isFirstBind, isFirstBind) + intent.putExtra(ConstantString.DeviceId, mDeviceId) + intent.putExtra(ConstantString.Mac, ble.mac) + startActivity(intent) + } else if (ble.conState == ConState.CONNECTION_FAIL) { + setNoConnectState() + } + } + } + //搜索蓝牙的设备状态 +// XEventBus.observe(this, EventName.ActionConDeviceState) { conState: Int -> +// if (conState == ConState.DEVICE_NOT_FOUND) { +// setNoConnectState() +// showToast(R.string.txt_ble_connect_fail) +// } +// } + + XEventBus.observe(this, EventName.RefreshDevice) { + finish() + } + + mTrackerSetViewModel.mAddBindDeviceLiveData.observe(this) { + dealRequestResult(it, object : GetResultCallback { + override fun onResult(any: Any) { + it.getOrNull()?.apply { + mDeviceId = deviceId + //连接蓝牙,方便发送激活指令 + mConnectionDeviceViewModel.connectDeviceToMac( + this@AddNewTracker3Activity, mConBleMac + ) + } + } + + override fun onErrorCode() { + super.onErrorCode() + setNoConnectState() + } + }) } } + private fun setNoConnectState() { + mScanDeviceAdapter.apply { + getData().let { + if (it.size > 0) { + isConnect = false + for (device in it) { + if (device.conState == ConState.CONNECTING) device.conState = + ConState.DISCONNECTED + } + notifyItemRangeChanged(0, it.size) + } + } + } + } + + private fun startScanBle() { + SRBleUtil.instance.cancelBleScan("AddNewTracker2Activity,已经在扫描蓝牙,取消蓝牙扫描") + + mScanDeviceAdapter.getData().let { list -> + mScanDeviceAdapter.notifyItemRangeRemoved(0, list.size) + list.clear() + mViewBinding.rvAddNewTracker3DeviceList.visibility = View.GONE + } + mViewBinding.ivAddNewTracker3RefreshBtn.let { + it.isEnabled = false + + if (null == mAnimatorSet) { + mAnimatorSet = ViewUtil.instance.viewAlphaAndRotationObjectAnimator(it, true) + } else { + mAnimatorSet!!.start() + } + } + // 扫描超时时间,可选 + val scanRuleConfig = BleScanRuleConfig.Builder().setScanTimeOut(15 * 1000).build() + BleManager.getInstance().initScanRule(scanRuleConfig) + BleManager.getInstance().scan(object : BleScanCallback() { + override fun onScanStarted(success: Boolean) { + LogUtil.e("开始扫描...$success") + } + + override fun onScanning(bleDevice: BleDevice?) { + LogUtil.d("onScanning....$bleDevice") + bleDevice?.apply { + if (null != name && name.contains(SRBleUtil.instance.trackDeviceBleStartName)) { + val start = 45 + val end = start + 6 + val subArray = scanRecord.sliceArray(start until end) + LogUtil.e("截取后的外显id广播=${HexUtil.formatHexString(subArray, true)}") + val deviceOutId = subArray.decodeToString() + DeviceBean().let { + it.deviceOutId = deviceOutId + it.macId = mac + mScanDeviceAdapter.getData().let { list -> + ViewUtil.instance.viewShow(mViewBinding.rvAddNewTracker3DeviceList) + list.add(it) + mScanDeviceAdapter.notifyItemRangeInserted(list.size - 1, 1) + } + } + } + } + } + + override fun onScanFinished(scanResultList: MutableList?) { + LogUtil.e("automaticConnection--扫描完成...${scanResultList?.size}") + scanFinished() + } + }) + } + + private fun scanFinished() { + mAnimatorSet?.cancel() + mViewBinding.ivAddNewTracker3RefreshBtn.isEnabled = true + if (mScanDeviceAdapter.getData().size == 0) { + ViewUtil.instance.showDialog( + mContext, + R.string.txt_no_search_device, + object : BaseDialog.OnDialogOkListener { + override fun onOkClick(dialog: BaseDialog<*>) { + dialog.dismiss() + startScanBle() + } + }, + okTextResId = R.string.txt_ok, + cancelTextResId = R.string.txt_cancel, + cancelListener = object : BaseDialog.OnDialogCancelListener { + override fun onCancelClick(dialog: BaseDialog<*>) { + dialog.dismiss() + finish() + } + }) + } + } + + override fun leftBackOnClick() { disconnectBle() super.leftBackOnClick() @@ -156,29 +248,11 @@ class AddNewTracker3Activity : override fun onClick(v: View?) { mViewBinding.apply { when (v!!) { - btnPairTrackerNo -> { - val intent = Intent(mContext, AddNewTracker4Activity::class.java) - intent.putExtra(ConstantString.isFirstBind, isFirstBind) - startActivity(intent) - } - - btnPairTrackerYes -> { + ivAddNewTracker3RefreshBtn -> { disconnectBle() - setButtonEnabled(mViewBinding.btnPairTrackerYes, ConstantInt.Type0) - mTrackerSetViewModel.bindDevice( - this@AddNewTracker3Activity, mDeviceOutId - ) - } - - mRightImageButton -> { - disconnectBle() - val intent = Intent(mContext, AddNewTracker2Activity::class.java) - intent.putExtra(ConstantString.isFirstBind, isFirstBind) - startActivityFinish(intent) + startScanBle() } } } } - - } \ No newline at end of file diff --git a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt index 8b7d41f..cd70799 100644 --- a/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt +++ b/app/src/main/java/com/abbidot/tracker/util/ViewUtil.kt @@ -34,6 +34,7 @@ import android.widget.ProgressBar import android.widget.RelativeLayout import android.widget.TextView import androidx.annotation.DrawableRes +import androidx.core.animation.doOnCancel import androidx.core.content.ContextCompat import androidx.core.view.isGone import androidx.core.view.isInvisible @@ -728,6 +729,11 @@ class ViewUtil private constructor() { } val animatorSet = AnimatorSet().apply { play(objectAnimator).with(objectAnimator2) + //取消动画,状态恢复原来状态 + doOnCancel { + view.alpha = 1f + view.rotation = 0f + } start() } return animatorSet diff --git a/app/src/main/java/com/abbidot/tracker/vm/GeoCoderViewModel.kt b/app/src/main/java/com/abbidot/tracker/vm/GeoCoderViewModel.kt index 27fce1c..6b62cf4 100644 --- a/app/src/main/java/com/abbidot/tracker/vm/GeoCoderViewModel.kt +++ b/app/src/main/java/com/abbidot/tracker/vm/GeoCoderViewModel.kt @@ -70,8 +70,7 @@ class GeoCoderViewModel : ViewModel() { if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) { baiduMapReverseGeocoder(latitude, longitude) } else { -// baiduMapReverseGeocoder(-110.95, 44.65) -// mapBoxReverseGeocoder(42.23, -103.18) +// baiduMapReverseGeocoder(latitude, longitude) mapBoxReverseGeocoder(latitude, longitude) } } diff --git a/app/src/main/res/layout/activity_add_new_tracker3.xml b/app/src/main/res/layout/activity_add_new_tracker3.xml index 7863db5..bf42210 100644 --- a/app/src/main/res/layout/activity_add_new_tracker3.xml +++ b/app/src/main/res/layout/activity_add_new_tracker3.xml @@ -32,8 +32,7 @@ @@ -48,74 +47,98 @@ android:layout_height="@dimen/dp_200" android:layout_alignParentEnd="true" android:src="@drawable/icon_pair_tracker_image2" /> - - - - - - - - + android:layout_alignParentEnd="true" + android:layout_marginTop="@dimen/dp_210" + android:layout_marginEnd="@dimen/dp_18" + android:src="@drawable/icon_refresh" /> + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_san_device_item.xml b/app/src/main/res/layout/layout_san_device_item.xml new file mode 100644 index 0000000..c8581bd --- /dev/null +++ b/app/src/main/res/layout/layout_san_device_item.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index e545693..74d2cea 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -46,6 +46,7 @@ 180dp 190dp 200dp + 210dp 220dp 255dp 260dp