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

网站制作 价格必应搜索

网站制作 价格,必应搜索,做影视外包的网站,邯郸网络教研平台前言 上一篇文章给大家分享了Kotlin版的Android蓝牙的基础知识和基础用法,不过上一篇都是一些零散碎片化的程序,,这一篇给大家分享Android蓝牙开发实战项目KotlinCompose的初步使用 效果演示 : Android Compose 蓝牙开发 Android蓝牙实战开发…

前言

上一篇文章给大家分享了Kotlin版的Android蓝牙的基础知识和基础用法,不过上一篇都是一些零散碎片化的程序,,这一篇给大家分享Android蓝牙开发实战项目Kotlin+Compose的初步使用

效果演示 : 

Android Compose 蓝牙开发

Android蓝牙实战开发步骤

1.新建Android项目添加蓝牙权限

下图所示:MyBluetoothDemo为刚刚创建的Android空项目,我们现在清单文件中把我们需要用到的权限声明一下,其中定位权限还需要做动态申请

2.封装BluetoothAdapter类

BluetoothAdapter类提供了常用的蓝牙API,我这里创建了一个BlueToothController类,小编这里是先将这些API封装到了一个BlueToothController类中,方便后续使用和操作

package com.example.bluetoothcomposeimport android.annotation.SuppressLint
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.content.Context
import android.content.Intentobject BlueToothController {val mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()/*** 检查设备是否支持蓝牙*/fun isBluetoothSupport(): Boolean {return mBluetoothAdapter !=null}/*** 检查该设备蓝牙是否开启*/@SuppressLint("MissingPermission")fun isBluetoothEnabled(): Boolean {return mBluetoothAdapter.enable()}/*** 打开蓝牙*/@SuppressLint("MissingPermission")fun turnOnBlueTooth(activity: Activity, requestCode: Int) {val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)activity.startActivityForResult(intent, requestCode)}/*** 打开蓝牙可见性*/@SuppressLint("MissingPermission")fun enableVisibily(context: Context) {val intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300)context.startActivity(intent)}/*** 停止查找设备*/@SuppressLint("MissingPermission")fun cancelFindDevice() {mBluetoothAdapter.cancelDiscovery()}/*** 判断当前设备是否在查找蓝牙设备*/@SuppressLint("MissingPermission")fun isStartDiscovering(): Boolean {return mBluetoothAdapter.isDiscovering}/*** 判断当前设备是否未在查找蓝牙设备*/@SuppressLint("MissingPermission")fun isCancelDiscovering(): Boolean {return !mBluetoothAdapter.isDiscovering}/*** 查找设备*/@SuppressLint("MissingPermission")fun findDevice() {mBluetoothAdapter.startDiscovery()}/*** 获取已绑定设备*/@SuppressLint("MissingPermission")fun getBondedDeviceList(): List<BluetoothDevice?>? {return ArrayList(mBluetoothAdapter.bondedDevices)}/*** 判断蓝牙是否连接*/@SuppressLint("MissingPermission")fun isConnectBlue(bluetoothSocket: BluetoothSocket?): Boolean {return bluetoothSocket != null && bluetoothSocket.isConnected}
}

3. 编写Compose UI页面

这里的UI样式,在后面我给出了完整版的,大家可以去复制一下

MainScreen:这是我们MainActivity的UI,放置了一个Column(竖向布局)和Menu

    @Composablefun MainScreen() {var expanded = remember {mutableStateOf(false)}Column(modifier = Modifier.fillMaxSize()){Row(modifier = Modifier.fillMaxWidth().background(Blue).padding(vertical = 12.dp).height(35.dp),verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.Start) {Text(text = "可用设备",modifier = Modifier.weight(1f).offset(10.dp))if(isRefresh.value){CircularProgressIndicator(modifier = Modifier.size(25.dp),color = White)}Box() {Icon(painter = painterResource(id = R.drawable.ic_setting),contentDescription = null,modifier = Modifier.width(50.dp).fillMaxHeight().clickable {expanded.value = true},)if(expanded.value){DropdownMenu(expanded = expanded.value,onDismissRequest = {expanded.value = false}) {data.forEachIndexed{ index: Int, s: String ->DropdownMenuItem(onClick = {when (index) {0 -> {if(BlueToothController.isBluetoothSupport()){Toast.makeText(this@MainActivity,"本机支持蓝牙功能",Toast.LENGTH_SHORT).show()}else{Toast.makeText(this@MainActivity,"本机暂不支持蓝牙功能",Toast.LENGTH_SHORT).show()}}1 -> {if(BlueToothController.isBluetoothEnabled()){Toast.makeText(this@MainActivity,"用户允许开启蓝牙",Toast.LENGTH_SHORT).show()}else{Toast.makeText(this@MainActivity,"用户拒绝开启蓝牙",Toast.LENGTH_SHORT).show()}}2 -> {selected.value = 3Log.d(TAG,"查看已绑定设备")if(BlueToothController.isStartDiscovering()){BlueToothController.cancelFindDevice()}deviceList.clear()for (device in BlueToothController.getBondedDeviceList()!!){deviceList.add(device!!)}}3 -> {if(BlueToothController.isStartDiscovering()){Log.d(TAG,"停止查找")BlueToothController.cancelFindDevice()deviceList!!.clear()}selected.value = 4BlueToothController.findDevice()Log.d(TAG,"开始查找")}}Log.d(TAG,selected.value.toString())expanded.value = false}) {Text(text = s)}}}}}}DeviceListView()}if(openDialog.value){AlterDialog()}}

AlterDialog:    用来显示弹窗

    @Composablefun AlterDialog() {AlertDialog(onDismissRequest = { openDialog.value = false },title = { Text(text = text.value) },text = {Text(text = "0c 11 09 41 23 00 01 03 FF")}, confirmButton = {TextButton(onClick = {openDialog.value = falsesendMessage()}) {Text(text = "发送")}}, dismissButton = {TextButton(onClick = { openDialog.value = false }) {Text(text = "取消")}})}

DeviceListView: 这是一个列表控件,相当于RecycleView  

@Composablefun DeviceListView(){LazyColumn(Modifier.fillMaxSize(),contentPadding =  PaddingValues(5.dp,1.dp),verticalArrangement = Arrangement.spacedBy(5.dp)){items(deviceList!!.size){ index->ListItem(index, deviceList[index])}}}

ListItem:这是每个LazyColumn中每个列表的UI样式

@Composablefun ListItem(index: Int, blueToothDevice: BluetoothDevice){Card(shape = RoundedCornerShape(4.dp),elevation = 2.dp) {Row(modifier = Modifier.height(50.dp).fillMaxWidth().clickable {openDialog.value = trueif (blueToothDevice.name == null) {text.value = "N/A"} else {text.value = blueToothDevice.name}//Gatt协议连接蓝牙var bluetoothGatt =blueToothDevice.connectGatt(this@MainActivity, true, mGattCallback)bluetoothGatt.connect()Log.d(TAG, "点击了第$index 个item")},verticalAlignment = Alignment.CenterVertically,) {Image(painter = painterResource(R.drawable.ic_blue),contentDescription = null,modifier = Modifier.fillMaxHeight().padding(all = 5.dp))Column(modifier = Modifier.fillMaxWidth()) {if(blueToothDevice.name==null){Text(text = "N/A",fontWeight = FontWeight.Bold)}else{Text(text = blueToothDevice.name,fontWeight = FontWeight.Bold)}Text(text = blueToothDevice.address,)}}}}

4. 蓝牙搜索,配对,连接,通信

小编这里为了让大家方便,便将搜索,配对,连接都写在了MainActivity中了,Compose UI也在这里了,大家可以复制直接去运行

package com.example.bluetoothcomposeimport android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.annotation.SuppressLint
import android.bluetooth.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.PermissionChecker.PERMISSION_GRANTED
import com.example.bluetoothcompose.ui.theme.Blue
import com.example.bluetoothcompose.ui.theme.BlueToothComposeTheme
import com.example.bluetoothcompose.ui.theme.White
import java.util.*class MainActivity : ComponentActivity() {private val TAG = "yf"private var deviceList = mutableStateListOf<BluetoothDevice>()private var data = mutableListOf("检查设备是否支持蓝牙","检查设备是否开启蓝牙","查看已配过的蓝牙设备","查找蓝牙设备")var selected = mutableStateOf(0)var openDialog = mutableStateOf(false)var text = mutableStateOf("")var mGatt: BluetoothGatt? = nullvar mWriter: BluetoothGattCharacteristic? = nullprivate var isRefresh = mutableStateOf(false)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {BlueToothComposeTheme {// A surface container using the 'background' color from the themeSurface(modifier = Modifier.fillMaxSize(),color = MaterialTheme.colors.background) {MainScreen()}}}}override fun onStart() {super.onStart()isPermission()registerBluetoothReceiver()}//处理找到蓝牙设备和搜索完成的广播消息var receiver: BroadcastReceiver = object : BroadcastReceiver() {@SuppressLint("MissingPermission")override fun onReceive(context: Context, intent: Intent) {val action = intent.action//开始查找设备when {BluetoothAdapter.ACTION_DISCOVERY_STARTED == action -> {//开始搜索if(deviceList!=null){deviceList!!.clear()}isRefresh.value = true}BluetoothDevice.ACTION_FOUND == action -> {//搜到蓝牙设备val device =intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)//把搜索到的设备添加到已找到列表中,显示它的信息deviceList?.add(device!!)Log.d(TAG,"找到了: ${deviceList.size}")}BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action -> {//搜索完毕isRefresh.value = falsewhen (selected.value) {3 -> {}4 -> {Toast.makeText(this@MainActivity,"选择要配对的蓝牙设备",Toast.LENGTH_SHORT).show()}}}BluetoothDevice.ACTION_BOND_STATE_CHANGED == action -> {val device =intent.getParcelableExtra<BluetoothDevice>(BluetoothDevice.EXTRA_DEVICE)if (device == null) {Toast.makeText(this@MainActivity,"无设备",Toast.LENGTH_SHORT).show()return}val state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 0)when (state) {BluetoothDevice.BOND_BONDED -> {Toast.makeText(this@MainActivity,"已配对",Toast.LENGTH_SHORT).show()}BluetoothDevice.BOND_BONDING -> {Toast.makeText(this@MainActivity,"正在配对",Toast.LENGTH_SHORT).show()}BluetoothDevice.BOND_NONE -> {Toast.makeText(this@MainActivity,"未配对",Toast.LENGTH_SHORT).show()}}}}}}//动态获取位置权限@SuppressLint("WrongConstant")private fun isPermission() {if (checkSelfPermission(ACCESS_COARSE_LOCATION) !== PERMISSION_GRANTED|| checkSelfPermission(ACCESS_FINE_LOCATION) !== PERMISSION_GRANTED) {requestPermissions(arrayOf(ACCESS_COARSE_LOCATION,ACCESS_FINE_LOCATION), 200)}}private fun registerBluetoothReceiver() {//filter注册广播接收器val filter = IntentFilter()//蓝牙当前状态filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED)//开始扫描蓝牙设备广播filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED)//找到蓝牙设备广播filter.addAction(BluetoothDevice.ACTION_FOUND)//扫描蓝牙设备结束广播filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)//蓝牙设备配对状态改变广播filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)//设备扫描模式改变广播filter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)registerReceiver(receiver, filter)}@SuppressLint("MissingPermission")@Composablefun MainScreen() {var expanded = remember {mutableStateOf(false)}Column(modifier = Modifier.fillMaxSize()){Row(modifier = Modifier.fillMaxWidth().background(Blue).padding(vertical = 12.dp).height(35.dp),verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.Start) {Text(text = "可用设备",modifier = Modifier.weight(1f).offset(10.dp))if(isRefresh.value){CircularProgressIndicator(modifier = Modifier.size(25.dp),color = White)}Box() {Icon(painter = painterResource(id = R.drawable.ic_setting),contentDescription = null,modifier = Modifier.width(50.dp).fillMaxHeight().clickable {expanded.value = true},)if(expanded.value){DropdownMenu(expanded = expanded.value,onDismissRequest = {expanded.value = false}) {data.forEachIndexed{ index: Int, s: String ->DropdownMenuItem(onClick = {when (index) {0 -> {if(BlueToothController.isBluetoothSupport()){Toast.makeText(this@MainActivity,"本机支持蓝牙功能",Toast.LENGTH_SHORT).show()}else{Toast.makeText(this@MainActivity,"本机暂不支持蓝牙功能",Toast.LENGTH_SHORT).show()}}1 -> {if(BlueToothController.isBluetoothEnabled()){Toast.makeText(this@MainActivity,"用户允许开启蓝牙",Toast.LENGTH_SHORT).show()}else{Toast.makeText(this@MainActivity,"用户拒绝开启蓝牙",Toast.LENGTH_SHORT).show()}}2 -> {selected.value = 3Log.d(TAG,"查看已绑定设备")if(BlueToothController.isStartDiscovering()){BlueToothController.cancelFindDevice()}deviceList.clear()for (device in BlueToothController.getBondedDeviceList()!!){deviceList.add(device!!)}}3 -> {if(BlueToothController.isStartDiscovering()){Log.d(TAG,"停止查找")BlueToothController.cancelFindDevice()deviceList!!.clear()}selected.value = 4BlueToothController.findDevice()Log.d(TAG,"开始查找")}}Log.d(TAG,selected.value.toString())expanded.value = false}) {Text(text = s)}}}}}}DeviceListView()}if(openDialog.value){AlterDialog()}}@Preview(showBackground = true,group = "Group1",)@Composablefun DefaultPreview() {MainScreen()}@SuppressLint("MissingPermission")@Composablefun DeviceListView(){LazyColumn(Modifier.fillMaxSize(),contentPadding =  PaddingValues(5.dp,1.dp),verticalArrangement = Arrangement.spacedBy(5.dp)){items(deviceList!!.size){ index->ListItem(index, deviceList[index])}}}@SuppressLint("MissingPermission")@Composablefun ListItem(index: Int, blueToothDevice: BluetoothDevice){Card(shape = RoundedCornerShape(4.dp),elevation = 2.dp) {Row(modifier = Modifier.height(50.dp).fillMaxWidth().clickable {openDialog.value = trueif (blueToothDevice.name == null) {text.value = "N/A"} else {text.value = blueToothDevice.name}//Gatt协议连接蓝牙var bluetoothGatt =blueToothDevice.connectGatt(this@MainActivity, true, mGattCallback)bluetoothGatt.connect()Log.d(TAG, "点击了第$index 个item")},verticalAlignment = Alignment.CenterVertically,) {Image(painter = painterResource(R.drawable.ic_blue),contentDescription = null,modifier = Modifier.fillMaxHeight().padding(all = 5.dp))Column(modifier = Modifier.fillMaxWidth()) {if(blueToothDevice.name==null){Text(text = "N/A",fontWeight = FontWeight.Bold)}else{Text(text = blueToothDevice.name,fontWeight = FontWeight.Bold)}Text(text = blueToothDevice.address,)}}}}@SuppressLint("MissingPermission")@Composablefun AlterDialog() {AlertDialog(onDismissRequest = { openDialog.value = false },title = { Text(text = text.value) },text = {Text(text = "0c 11 09 41 23 00 01 03 FF")}, confirmButton = {TextButton(onClick = {openDialog.value = falsesendMessage()}) {Text(text = "发送")}}, dismissButton = {TextButton(onClick = { openDialog.value = false }) {Text(text = "取消")}})}private val mGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() {@SuppressLint("MissingPermission")override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {//连接成功if (newState == BluetoothProfile.STATE_CONNECTED) {//进行服务发现gatt.discoverServices()Log.d(TAG, "连接成功")} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {//连接断开,处理断开逻辑Log.d(TAG, "连接断开")}}@SuppressLint("MissingPermission")override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {Log.d(TAG, "onServicesDiscovered : $status ==>> $gatt")//发现服务成功,处理服务和特征值if (status == BluetoothGatt.GATT_SUCCESS) {//发送消息mGatt = gattval service =gatt.getService(UUID.fromString("0000180a-0000-1000-8000-00805F9B34FB"))mWriter =service.getCharacteristic(UUID.fromString("00002ad9-0000-1000-8000-00805F9B34FB"))//打开消息通知mGatt!!.setCharacteristicNotification(mWriter, true)val descriptor: BluetoothGattDescriptor =mWriter!!.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"))descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUEmGatt!!.writeDescriptor(descriptor)} else {Log.d(TAG, "发现服务失败")}}override fun onCharacteristicRead(gatt: BluetoothGatt,characteristic: BluetoothGattCharacteristic,status: Int) {Log.e(TAG, "onCharacteristicRead $status")//读取特征成功,处理特征值if (status == BluetoothGatt.GATT_SUCCESS) {}}override fun onCharacteristicWrite(gatt: BluetoothGatt,characteristic: BluetoothGattCharacteristic,status: Int) {Log.e(TAG, "onCharacteristicWrite $status")//写入特征成功if (status == BluetoothGatt.GATT_SUCCESS) {Log.d(TAG, "发送成功")} else {Log.d(TAG, "发送失败")}}override fun onCharacteristicChanged(gatt: BluetoothGatt,characteristic: BluetoothGattCharacteristic) {//接收到数据val data = characteristic.value//处理接收到的数据Log.d(TAG, "Received data: " + bytesToHexFun2(data))}override fun onDescriptorRead(gatt: BluetoothGatt,descriptor: BluetoothGattDescriptor,status: Int) {super.onDescriptorRead(gatt, descriptor, status)}override fun onDescriptorWrite(gatt: BluetoothGatt,descriptor: BluetoothGattDescriptor,status: Int) {super.onDescriptorWrite(gatt, descriptor, status)}override fun onReliableWriteCompleted(gatt: BluetoothGatt, status: Int) {super.onReliableWriteCompleted(gatt, status)}override fun onReadRemoteRssi(gatt: BluetoothGatt, rssi: Int, status: Int) {super.onReadRemoteRssi(gatt, rssi, status)}override fun onMtuChanged(gatt: BluetoothGatt, mtu: Int, status: Int) {super.onMtuChanged(gatt, mtu, status)}override fun onServiceChanged(gatt: BluetoothGatt) {super.onServiceChanged(gatt)}override fun onPhyUpdate(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {super.onPhyUpdate(gatt, txPhy, rxPhy, status)}override fun onPhyRead(gatt: BluetoothGatt, txPhy: Int, rxPhy: Int, status: Int) {super.onPhyRead(gatt, txPhy, rxPhy, status)}}private fun bytesToHexFun2(bytes: ByteArray): String? {var result = 0for (i in bytes.indices) {result += bytes[i]}return byte2Hex((result.inv() and 0xFF).toByte())}fun byte2Hex(inByte: Byte?): String //1字节转2个Hex字符{return String.format("%02x", inByte).toUpperCase()}@SuppressLint("MissingPermission")fun sendMessage(){if (null == mWriter) {Log.e("yf123", "ble:发送失败:null == writer !!!!")} else {mWriter!!.value = byteArrayOf(0x0c.toByte(),0x11.toByte(),0x09.toByte(),0x41.toByte(),0x23.toByte(),0x00.toByte(),0x01.toByte(),0x03.toByte(),0xFF.toByte())mGatt!!.writeCharacteristic(mWriter)}}}

到此为止,我们的程序就到这里了,蓝牙搜索,配对,连接,通信便已经成功实现了,大家可以把代码copy一下拿去运行,具体效果演示图在文章最上方,大家还想了解更多关于Android蓝牙开发的可以继续看我下一篇给大家的分享

http://www.dinnco.com/news/30160.html

相关文章:

  • 西宁做网站君博示范在线建站网页制作网站建设平台
  • 网站 建设开发合同模板百度热搜榜排名今日头条
  • 贵阳网络推广哪家靠谱免费seo网站诊断免费
  • 免费wap建站免费下载优化大师
  • 怎样查看网站服务商谷歌优化工具
  • 抚宁网站建设seo整站优化外包公司
  • 深圳华强北封闭了吗常熟seo关键词优化公司
  • 网站建设特点优化关键词排名
  • 网站开发需要学php吗怎么创建网址
  • 烟台违建举报网站哪里有学市场营销培训班
  • 网站建设深广告推广策划方案
  • 网站的维护与更新余姚网站如何进行优化
  • 老外做中文网站seo服务外包
  • 绍兴网站设计优化电池充电什么意思
  • 建设网站创业电子商务网站建设多少钱
  • 快手秒刷自助网站推广文章
  • 建设工程挂网是在那个网站发稿网
  • 旅游微网站建设营销网站建站公司
  • 百度网站优化哪家好新网站百度seo如何做
  • php高级网站开发seo网页优化培训
  • 海外医疗网站建设抖音广告推广
  • 铁岭公司做网站淘宝美工培训推荐
  • 让别人做网站推广需要多少钱网上国网推广
  • 怎么把网站放到百度属性词 关键词 核心词
  • 可以上传图片的网站怎么做站长统计代码
  • 胶州做网站公司免费外链发布平台在线
  • 网站开发 freemarker小说推文推广平台
  • legenda wordpress主题长沙百度seo
  • du制作网站网络优化工程师主要做什么
  • 网站建设与维护ppt图片搜索引擎