android - 在 Android Studio 上的 Fragment 中扫描 BLE 设备 - Kotlin
问题描述
几天来,我试图在我的应用程序中实现 BLE 连接。我在次要片段而不是主要片段中这样做。但是当我扫描找到一个 BLE 设备(使用 startScan( leScanCallback
))时,它永远不会进入回调方法leScanCallback
。我遵循了一些教程,但我不知道为什么它不起作用。
这是我的 MainActivity.kt
package com.example.start
class MainActivity : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
drawerLayout = binding.drawerLayout
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout) //link the navigation controller & drawer layout to the app bar
NavigationUI.setupWithNavController(binding.navView, navController) //allows the user to display the navigation drawer
//PERMISSION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ContextCompat.checkSelfPermission(baseContext,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
val PERMISSION_CODE = 0 //Should be >= 0
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
PERMISSION_CODE)
}
}
//==========================Bluetooth Part==========================================
val REQUEST_ENABLE_BT : Int = 1 //Will stock the result of enabling the bluetooth
//RESULT_OK = -1 (0xffffffff)
//RESULT_CANCELLED = 0 (0x00000000)
//val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter()
val bluetoothAdapter: BluetoothAdapter by lazy {
val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothManager.adapter
}
if (bluetoothAdapter == null) {
// Device doesn't support Bluetooth
}
if (bluetoothAdapter?.isEnabled == false) { //If bluetooth is disable, we active it
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
}
}
}
这是我的 ConnectFragment.kt,我按下按钮“btnScan”开始研究
package com.example.start
private const val SELECT_DEVICE_REQUEST_CODE = 0
class ConnectFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
//return inflater.inflate(R.layout.fragment_connect, container, false)
val binding = DataBindingUtil.inflate<FragmentConnectBinding>(
inflater, R.layout.fragment_connect, container, false
)
binding.btnScan.setOnClickListener {
view : View ->
scanLeDevice()
}
return binding.root
}
private val bluetoothLeScanner: BluetoothLeScanner
get() {
val bluetoothManager = requireContext().getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter = bluetoothManager.adapter
return bluetoothAdapter.bluetoothLeScanner
}
// Device scan callback.
private val leScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
super.onScanResult(callbackType, result)
//TODO TEST TEST TEST
Log.d("ScanDeviceActivity", "leScanCallback >>")
Log.d("ScanDeviceActivity", "onScanResult(): ${result?.device?.address} - ${result?.device?.name}")
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
Log.d("DeviceListActivity","onBatchScanResults:${results.toString()}")
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
Log.d("DeviceListActivity", "onScanFailed: $errorCode")
}
}
private var scanning = false
private val handler = Handler()
// Stops scanning after 10 seconds.
private val SCAN_PERIOD: Long = 10000
fun scanLeDevice() {
if (!scanning) { // Stops scanning after a pre-defined scan period.
handler.postDelayed({
scanning = false
bluetoothLeScanner.stopScan(leScanCallback)
}, SCAN_PERIOD)
scanning = true
//PERMISSION COARSE LOCATION
Log.d("ScanDeviceStart", "startScan()")
when (PermissionChecker.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION)) {
PackageManager.PERMISSION_GRANTED -> bluetoothLeScanner.startScan(leScanCallback)
else -> requestPermissions(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION), 1)
}
} else {
scanning = false
bluetoothLeScanner.stopScan(leScanCallback)
}
}
//Permission
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
1 -> when (grantResults) {
intArrayOf(PackageManager.PERMISSION_GRANTED) -> {
Log.d("ScanDevices", "onRequestPermissionsResult(PERMISSION_GRANTED)")
bluetoothLeScanner.startScan(leScanCallback)
}
else -> {
Log.d("ScanDevices", "onRequestPermissionsResult(not PERMISSION_GRANTED)")
}
}
else -> super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
}
}
按下按钮后,调试控制台以: D/BluetoothLeScanner: Stop Scan with callback结尾
解决方案
推荐阅读
- node.js - 如何在履行对话流中从 Twilio 获取电话号码
- android - 麦克风无法在与自定义 android 应用程序的对话流 Web 集成中工作
- python - 如何让我的 IDE 识别动态添加的功能?
- bash - 用 ffmpeg 分割视频会产生奇怪的输出
- python - Python:如何获取 Active Directory 组成员的电子邮件?
- javascript - 两个 Appium 选择器,其中只有一个接受文本
- java - Aptana Studio 3 不会启动。它只看到 java 1.6 而不是 1.8
- .net - 如何在vb dot net中显示excel文件的所有线程或实例。我想显示excel文件的所有线程和一个主进程
- python - 如何在加载模型并使用一个类进行训练时对类进行编码器转换
- angular - 排序图标不能包含在 mdbTableSort 中