当前位置: 首页 > news >正文

代做ppt网站好做手机网站哪家好

代做ppt网站好,做手机网站哪家好,菲斯曼售后服务中心,学做美食去哪个网站好Ble蓝牙App#xff08;七#xff09;扫描过滤 前言目录正文一、增加菜单二、使用MMKV① 添加依赖② 封装MMKV③ 使用MMKV 三、过滤空设备名四、过滤Mac地址五、过滤RSSI六、源码 前言 在上一篇文章中了解了MTU的相关知识以及对于设备操作信息的展示#xff0c;本篇文章中将增… Ble蓝牙App七扫描过滤 前言目录正文一、增加菜单二、使用MMKV① 添加依赖② 封装MMKV③ 使用MMKV 三、过滤空设备名四、过滤Mac地址五、过滤RSSI六、源码 前言 在上一篇文章中了解了MTU的相关知识以及对于设备操作信息的展示本篇文章中将增加扫描设备的过滤功能让你更方便的扫描想要找的低功耗蓝牙设备。 目录 Ble蓝牙App一扫描Ble蓝牙App二连接与发现服务Ble蓝牙App三特性和属性Ble蓝牙App四UI优化和描述符Ble蓝牙App五数据操作Ble蓝牙App六请求MTU与显示设备信息Ble蓝牙App七扫描过滤 正文 增加扫描过滤主要就是让扫描设备的时候更方便找到想要的设备下面我们来看有哪些功能的增加。 一、增加菜单 为了不占用扫描页面的空间我打算通过添加菜单来进行扫描的过滤操作那么首先我们在menu下增加一个menu_scan.xml文件代码如下所示 menu xmlns:androidhttp://schemas.android.com/apk/res/androiditemandroid:idid/item_filter_nullandroid:checkabletrueandroid:title过滤空设备名 /itemandroid:idid/item_filter_macandroid:checkabletrueandroid:title过滤Mac地址 /itemandroid:idid/item_filter_rssiandroid:checkabletrueandroid:title过滤RSSI //menu菜单中有三个Item看一下预览效果图 三个Item都是选中Item选中表示这个过滤功能项启用可以全部都选中也可以任意选择之后我们进入到ScanActivity首先是创建菜单和菜单选中修改地方有三处 第一处在onCreate()函数中增加支持ActionBar代码如下所示 override fun onCreate(savedInstanceState: Bundle?) {...setSupportActionBar(binding.toolbar)...}第二处在ScanActivity中重写onCreateOptionsMenu()函数代码如下所示 private lateinit var mMenu: Menuoverride fun onCreateOptionsMenu(menu: Menu): Boolean {menuInflater.inflate(R.menu.menu_main, menu)mMenu menureturn true}创建选项菜单再创建一个mMenu变量在后面会用到的这个变量。 第三处在ScanActivity中重写onOptionsItemSelected()函数代码如下所示 override fun onOptionsItemSelected(item: MenuItem): Boolean {when(item.itemId) {R.id.item_filter_null - { // 过滤空设备名称}R.id.item_filter_mac - { // 过滤Mac地址}R.id.item_filter_rssi - { // 过滤RSSI}}return true}现在三个Item的点击事件中什么都不做我们一步一步给它加上现在菜单就创建好了。 二、使用MMKV 因为我们修改的菜单项会涉及到保存过滤设置的功能所以需要将一些参数报错到手机中那么我们可以使用SP、DataStore等方式但是这里我是用MMKV主要是因为用起来比较的方便下面我们来使用MMKV。 ① 添加依赖 MMKV是腾讯的一个开源项目已经发布在mavenCentral()仓库中了我们在App中使用只需要在app模块下的build.gradle中的dependencies{}闭包中添加如下依赖代码即可 dependencies {...//mmkvimplementation com.tencent:mmkv:1.2.14 }然后点击Sync Now同步一下添加依赖就完成了。 ② 封装MMKV 针对于MMKV的使用其实非常简单就是两步先初始化然后使用就好了那么为了使用的更方便我们可以简单封装一下MMKV做成一个工具类下面我们在com.llw.goodble包下新建一个utils包utils包下新建一个MVUtils类代码如下所示 object MVUtils {val mmkv MMKV.defaultMMKV()fun put(key: String, value: Any): Boolean {return when (value) {is String - mmkv.encode(key, value)is Float - mmkv.encode(key, value)is Boolean - mmkv.encode(key, value)is Int - mmkv.encode(key, value)is Long - mmkv.encode(key, value)is Double - mmkv.encode(key, value)is ByteArray - mmkv.encode(key, value)is Parcelable - mmkv.encode(key, value)else - false}}fun put(key: String, sets: SetString?): Boolean {if (sets null) {return false}return mmkv.encode(key, sets)}fun getInt(key: String, defaultValue: Int 0) mmkv.decodeInt(key, defaultValue)fun getDouble(key: String, defaultValue: Double 0.00) mmkv.decodeDouble(key, defaultValue)fun getLong(key: String, defaultValue: Long 0L) mmkv.decodeLong(key, defaultValue)fun getBoolean(key: String, defaultValue: Boolean false) mmkv.decodeBool(key, defaultValue)fun getFloat(key: String, defaultValue: Float 0F) mmkv.decodeFloat(key, defaultValue)fun getByteArray(key: String) mmkv.decodeBytes(key)fun getString(key: String, defaultValue: String ) mmkv.decodeString(key, defaultValue)inline fun reified T : Parcelable getParcelable(key: String) mmkv.decodeParcelable(key, T::class.java)fun getStringSet(key: String) mmkv.decodeStringSet(key, Collections.emptySet())fun removeKey(key: String) mmkv.removeValueForKey(key)fun clearAll() mmkv.clearAll() }这里实际上大体就分为三个部分首先是初始化然后是数据的存和取最后是清除数据是不是很简单呢 ③ 使用MMKV 使用MMKV首先需要做的就是初始化我们需要在BleApp的onCreate()函数中进行初始化代码如下所示 override fun onCreate() {...//mmkv初始化MMKV.initialize(this)}使用MMKV同样是采用键值对的形式那么基于我们的菜单功能我们需要增加一些键在BleConstant中增加如下常量代码如下所示 //过滤RSSIconst val FILTER_RSSI_FLAG filterRssiFlag//RSSI 值const val FILTER_RSSI_VALUE filterRssiValue//过滤空设备名const val FILTER_NULL_FLAG filterNullFlag//是否过滤Mac地址const val FILTER_MAC_FLAG filterMacFlag//需要过滤的Mac地址const val FILTER_MAC_VALUE filterMacValue下面我们修改ScanActivity中的onCreateOptionsMenu()函数代码如下所示 override fun onCreateOptionsMenu(menu: Menu): Boolean {menuInflater.inflate(R.menu.menu_scan, menu)mMenu menumMenu.findItem(R.id.item_filter_rssi).isChecked MVUtils.getBoolean(FILTER_RSSI_FLAG)if (MVUtils.getBoolean(FILTER_RSSI_FLAG)) {mMenu.findItem(R.id.item_filter_rssi).title 过滤RSSI- MVUtils.getInt(FILTER_RSSI_VALUE, 100)}mMenu.findItem(R.id.item_filter_null).isChecked MVUtils.getBoolean(FILTER_NULL_FLAG)mMenu.findItem(R.id.item_filter_mac).isChecked MVUtils.getBoolean(FILTER_MAC_FLAG)return true}在这里的代码就是在创建菜单的时候判断一下保存的参数是否需要选中Item可以修改Item的选中状态和标题内容这里就是获取参数。 三、过滤空设备名 下面我们来保存参数修改onOptionsItemSelected()函数中的代码 R.id.item_filter_null - { // 过滤空设备名称if (bleCore.isScanning()) stopScan()val filterNull MVUtils.getBoolean(FILTER_NULL_FLAG)MVUtils.put(FILTER_NULL_FLAG, !filterNull)mMenu.findItem(R.id.item_filter_null).isChecked MVUtils.getBoolean(FILTER_NULL_FLAG)showMsg(if (MVUtils.getBoolean(FILTER_NULL_FLAG)) 过滤空设备名称的设备 else 保留空设备名称的设备)if (!bleCore.isScanning()) startScan()}这里看到就是在点击过滤空设备Item时首先停止扫描然后获取参数值再保存根据值设置Item是否选中最后开始扫描那么我们怎么过滤这个空设备名称的设备呢还需要修改扫描回调中的代码 override fun onScanResult(result: ScanResult) {//过滤空设备名if (MVUtils.getBoolean(FILTER_NULL_FLAG)) {if (result.scanRecord!!.deviceName null) {return}if (result.scanRecord!!.deviceName!!.isEmpty()) {return}}...}这里我们只需要在原有的条件上再增加一个判断即可因为缺省值是false所以如果是不过滤空设备名就不会执行判断里面空处理和空设备名处理看一下运行的效果。 我们看到默认是不过滤空设备名称的当选中过滤空设备名后就会过滤设备名称为空的设备只不过我们这里对于空设备名称的设备显示的UI还没有处理的很好下面我们简单改一下将onScanResult()函数中的这一行代码 val bleDevice BleDevice(result.scanRecord!!.deviceName, result.device.address, result.rssi, result.device)改成 val realName result.scanRecord?.deviceName?.let { it.ifEmpty { BleConstant.UNKNOWN_DEVICE } } ?: BleConstant.UNKNOWN_DEVICEval bleDevice BleDevice(realName, result.device.address, result.rssi, result.device)这里改的目的就是首先判断获取的设备名是否为空如果为空则返回一个Unknown device作为设备名称不为空则检查是否为空字符串是的话也返回Unknown device不是则返回本身设备名称再运行一下就可以了。 四、过滤Mac地址 下面我们要做过滤Mac地址那么要过滤Mac地址首先要输入Mac地址那么我们可以写一个弹窗来进行输入的工作在layout下创建一个dialog_settings_mac.xml作为弹窗布局代码如下所示 ?xml version1.0 encodingutf-8? androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autostylestyle/Widget.MaterialComponents.TextInputLayout.OutlinedBoxandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:backgroundcolor/whitecom.google.android.material.appbar.MaterialToolbarandroid:idid/toolbarandroid:layout_widthmatch_parentandroid:layout_height?attr/actionBarSizeapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparentapp:title过滤Mac地址 /com.google.android.material.textfield.TextInputLayoutandroid:idid/data_layoutstylestyle/Widget.MaterialComponents.TextInputLayout.OutlinedBoxandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:layout_marginStart16dpandroid:layout_marginEnd16dpapp:boxStrokeColorcolor/blackapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/toolbarcom.google.android.material.textfield.TextInputEditTextandroid:idid/et_dataandroid:layout_widthmatch_parentandroid:layout_heightwrap_contentandroid:hintMac Addressandroid:lines1android:singleLinetrue //com.google.android.material.textfield.TextInputLayoutCheckBoxandroid:idid/cb_format_checkandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textMac地址格式检查app:layout_constraintStart_toStartOfid/data_layoutapp:layout_constraintTop_toBottomOfid/data_layout /Buttonandroid:idid/btn_negativeandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginEnd18dpandroid:layout_weight1android:text取消app:layout_constraintEnd_toStartOfid/btn_positiveapp:layout_constraintTop_toTopOfid/btn_positive /Buttonandroid:idid/btn_positiveandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginBottom16dpandroid:layout_weight1android:text确定app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfid/data_layoutapp:layout_constraintTop_toBottomOfid/cb_format_check //androidx.constraintlayout.widget.ConstraintLayout这个布局中有一个检查Mac地址正确性的复选框同样我们需要在BleUtils中增加一个函数代码如下所示 fun isValidMac(macStr: String) Regex(([A-Fa-f0-9]{2}[:]){5}[A-Fa-f0-9]{2}).matches(macStr)下面我们回到ScanActivity中写一个showSettingMacDialog()函数代码如下所示 private fun showSettingMacDialog() {val dialog BottomSheetDialog(this, R.style.BottomSheetDialogStyle)val macBinding DialogSettingMacBinding.inflate(layoutInflater)macBinding.btnPositive.setOnClickListener {val inputData macBinding.etData.text.toString()if (inputData.isEmpty()) {macBinding.dataLayout.error 请输入Mac地址returnsetOnClickListener}if (macBinding.cbFormatCheck.isChecked) {if (!BleUtils.isValidMac(inputData)) {macBinding.dataLayout.error 请输入正确的Mac地址returnsetOnClickListener}}if (bleCore.isScanning()) stopScan()MVUtils.put(FILTER_MAC_VALUE, inputData)MVUtils.put(FILTER_MAC_FLAG, true)mMenu.findItem(R.id.item_filter_mac).isChecked trueshowMsg(过滤Mac地址)if (!bleCore.isScanning()) startScan()dialog.dismiss()}macBinding.btnNegative.setOnClickListener {dialog.dismiss()}dialog.setContentView(macBinding.root)dialog.show()}弹窗中点击确定按钮就会先检查一遍然后就会保存Mac地址再保存过滤标识然后我们修改一下过滤Mac地址Item的点击事件代码如下所示 R.id.item_filter_mac - { // 过滤Mac地址if (MVUtils.getBoolean(FILTER_MAC_FLAG)) {mMenu.findItem(R.id.item_filter_mac).isChecked falseMVUtils.put(FILTER_MAC_FLAG, false)MVUtils.put(FILTER_MAC_VALUE, )showMsg(不过滤设备地址)} else {showSettingMacDialog()}}首先判断是否过滤有的话就不再过滤没有的话就显示输入Mac地址弹窗如果过滤了我们就需要在扫描回调函数中增加一个过滤的选项。 override fun onScanResult(result: ScanResult) {//过滤空设备名...//过滤Mac地址if (MVUtils.getBoolean(FILTER_MAC_FLAG)) {val filterMac: String? MVUtils.getString(FILTER_MAC_VALUE, )if (filterMac!!.isNotEmpty()) {if (!result.device.address.contains(filterMac)) return}}...}过滤的位置可以放在过滤空设备名称之后或者之前都可以最后还需要修改onCreateOptionsMenu()函数中的代码如下所示 override fun onCreateOptionsMenu(menu: Menu): Boolean {menuInflater.inflate(R.menu.menu_scan, menu)mMenu menumMenu.findItem(R.id.item_filter_null).isChecked MVUtils.getBoolean(FILTER_NULL_FLAG)mMenu.findItem(R.id.item_filter_mac).isChecked MVUtils.getBoolean(FILTER_MAC_FLAG)return true}增加了一个对于Mac地址Item项是否选中的判断下面我们可以运行看看我们的过滤是否有效果。 这样过滤Mac地址就做好了下面过滤RSSI信号强度。 五、过滤RSSI 与过滤Mac地址一样过滤RSSI首先要做的就是设置RSSI对此我们同样在layout下创建一个dialog_settings_rssi.xml作为弹窗的布局文件代码如下所示 ?xml version1.0 encodingutf-8? androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroid:backgroundcolor/whitecom.google.android.material.appbar.MaterialToolbarandroid:idid/toolbarandroid:layout_widthmatch_parentandroid:layout_height?attr/actionBarSizeapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparentapp:title过滤RSSI /TextViewandroid:idid/textViewandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginStart16dpandroid:layout_marginTop16dpandroid:textRSSI:android:textColorcolor/blackapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/toolbar /androidx.appcompat.widget.AppCompatSeekBarandroid:idid/sb_rssiandroid:layout_width0dpandroid:layout_heightwrap_contentandroid:layout_weight1android:max100android:min35android:progress100android:progressTintcolor/orangeandroid:thumbTintcolor/dark_orangeapp:layout_constraintBottom_toBottomOfid/textViewapp:layout_constraintEnd_toStartOfid/tv_rssiapp:layout_constraintStart_toEndOfid/textViewapp:layout_constraintTop_toTopOfid/textView /TextViewandroid:idid/tv_rssiandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginEnd16dpandroid:text-100 dBmandroid:textColorcolor/blackapp:layout_constraintBottom_toBottomOfid/textViewapp:layout_constraintEnd_toEndOfparent /Buttonandroid:idid/btn_negativeandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginEnd18dpandroid:layout_weight1android:text取消app:layout_constraintEnd_toStartOfid/btn_positiveapp:layout_constraintTop_toTopOfid/btn_positive /Buttonandroid:idid/btn_positiveandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginTop16dpandroid:layout_weight1android:text确定app:layout_constraintEnd_toEndOfid/tv_rssiapp:layout_constraintTop_toBottomOfid/tv_rssi / /androidx.constraintlayout.widget.ConstraintLayout然后就是在ScanActivity中增加一个showSettingRssi()函数代码如下所示 private fun showSettingRssi() {val dialog BottomSheetDialog(this, R.style.BottomSheetDialogStyle)val rssiBinding DialogSettingRssiBinding.inflate(layoutInflater)var progress 100rssiBinding.sbRssi.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {SuppressLint(SetTextI18n)override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {rssiBinding.tvRssi.text -$progress dBm}override fun onStartTrackingTouch(seekBar: SeekBar) {}override fun onStopTrackingTouch(seekBar: SeekBar) {progress seekBar.progress}})val rssi: Int MVUtils.getInt(FILTER_RSSI_VALUE, 100)rssiBinding.sbRssi.progress rssirssiBinding.tvRssi.text String.format(-%s dBm, rssi)rssiBinding.btnPositive.setOnClickListener {//保存if (bleCore.isScanning()) stopScan()MVUtils.put(FILTER_RSSI_FLAG, true)//保存设置的RSSI值MVUtils.put(FILTER_RSSI_VALUE, progress)mMenu.findItem(R.id.item_filter_rssi).isChecked truemMenu.findItem(R.id.item_filter_rssi).title 过滤RSSI-$progressshowMsg(过滤RSSI- progress dBm)if (!bleCore.isScanning()) startScan()dialog.dismiss()}rssiBinding.btnNegative.setOnClickListener { dialog.dismiss() }dialog.setContentView(rssiBinding.root)dialog.show()}在点击确定按钮的时候保存设置的RSSI信号强度值如果没有设置就是默认的值然后我们修改一下过滤RSSI Item的点击事件代码如下所示 R.id.item_filter_rssi - { // 过滤RSSIif (MVUtils.getBoolean(FILTER_RSSI_FLAG)) {if (bleCore.isScanning()) stopScan()//关闭过滤RSSIMVUtils.put(FILTER_RSSI_FLAG, false)mMenu.findItem(R.id.item_filter_rssi).isChecked falseMVUtils.put(FILTER_RSSI_VALUE, 100)showMsg(取消过滤RSSI)if (!bleCore.isScanning()) startScan()} else {showSettingRssi()}}当前已有过滤RSSI再次点击时就会取消过滤的信息知道你再次设置RSSI过滤值接下来就是扫描回调中根据这个设置项进行一次过滤 override fun onScanResult(result: ScanResult) {//过滤Mac地址...//过滤RSSIif (MVUtils.getBoolean(FILTER_RSSI_FLAG)) {val rssi: Int -MVUtils.getInt(FILTER_RSSI_VALUE, 100)if (result.rssi rssi) {return}}...}最后为了保存设置项是我们再次打开App时UI上是正确的我们修改onCreateOptionsMenu()函数代码如下所示 override fun onCreateOptionsMenu(menu: Menu): Boolean {menuInflater.inflate(R.menu.menu_scan, menu)mMenu menumMenu.findItem(R.id.item_filter_null).isChecked MVUtils.getBoolean(FILTER_NULL_FLAG)mMenu.findItem(R.id.item_filter_mac).isChecked MVUtils.getBoolean(FILTER_MAC_FLAG)mMenu.findItem(R.id.item_filter_rssi).isChecked MVUtils.getBoolean(FILTER_RSSI_FLAG)if (MVUtils.getBoolean(FILTER_RSSI_FLAG)) {mMenu.findItem(R.id.item_filter_rssi).title 过滤RSSI- MVUtils.getInt(FILTER_RSSI_VALUE, 100)}return true}运行一下看看效果 关于扫描过滤的功能就写好了本文内容介绍。 六、源码 如果对你有所帮助的话不妨 Star 或 Fork山高水长后会有期~ 源码地址GoodBle
http://www.dnsts.com.cn/news/182164.html

相关文章:

  • 建筑人才网官方网站中国建筑科学院有限公司认证中心自己创建app
  • 网站程序的构成网站及管理系统
  • 网站标题与关键词入门网站分析应该怎么做
  • html做网站头部山东公司注册网上核名
  • 网站开速度几秒山东省城乡住房建设厅网站
  • html5国内网站网站推广途径
  • 怎么建立一个小说网站深圳微信网站运营
  • 设计网站 知乎线下教育机构
  • 用ps做网站切片网站建设与运维预算
  • 上海网络推广方法惠州百度关键词优化
  • 网站数据统计工具python 做网站教程
  • 网站支付模块四川建设网报名系统
  • 容桂做网站汕头政务发布
  • 白云区同和网站建设做网站赚钱吗 怎么赚钱
  • 营销型网站方案ppt模板我们是谁 网站运营
  • 织梦网站图标更换wordpress的模板文件
  • 移动端企业网站网站建设哪家好万维科技
  • 网站数据库模版唐山房产网站建设
  • 山东住房和建设庭官网站官军队工程建设项目招投标网站
  • 汕头网站推广费用代发货网站系统建设
  • ps外包网站鲜花网站建设店
  • 交通建设集团网站项目经理接到网站开发怎么开展
  • 杭州蒙特网站建设求人做网站
  • 建永久网站网站网址前的小图标怎么做的
  • 免费创建虚拟网站升阳广州做网站公司
  • 凡科建站的建站后如何管理erp系统长什么样
  • 手机app客户端做网站wordpress访问满
  • wordpress 仿站wordpress 性能
  • 建设网站推广贷款业务津seo快速排名
  • 响应式外贸网站建设办公室设计风格