TL;DR my singleton BLEManager managing Bluetooth communication keeps getting re-initialised (see console log). How should I prevent this?
Using Swift 5.9 for iOS in Xcode 15.1
My code finds multiple BT devices, and lists them for selection, also building an array of devices for reference.
Most code examples connect each device immediately. I am trying to connect later, when a specific device is selected and its View opens.
I pass the array index of the device to the individual Model to serve as a reference, hoping to pass that back to BLEManager to connect and do further communication.
After scanning has completed, the log message shows there is 1 device in it, so its not empty.
As soon as I try and pass a reference back to BLEManager, the app crashes saying the array reference is out of bounds. The log shows that BLEManager is being re-initialised, presumably clearing and emptying the array.
How should I be declaring the relationship to achieve this?
Console log showing single device found:
ContentView init
BLEManager init
didDiscover id: 39D43C90-F585-792A-5BD6-8749BA0B5385
In didDiscover devices count is 1
stopScanning
After stopScanning devices count is 1
<-- selection made here
DeviceModel init to device id: 0
BLEManager init
BLEManager connectToDevice id: 0
devices is empty
Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range
2023-12-28 11:45:55.149419+0000 BlueTest1[20773:1824795] Swift/ContiguousArrayBuffer.swift:600: Fatal error: Index out of range
BlueTest1App.swift
import SwiftUI
@main
struct BlueTest1App: App {
var body: some Scene {
WindowGroup {
ContentView(bleManager: BLEManager())
}
}
}
ContentView.swift
import SwiftUI
struct TextLine: View {
@State var dev: Device
var body: some View {
HStack {
Text(dev.name).padding()
Spacer()
Text(String(dev.rssi)).padding()
}
}
}
struct PeripheralLineView: View {
@State var devi: Device
var body: some View {
NavigationLink(destination: DeviceView(device: DeviceModel(listIndex: devi.id))) {
TextLine(dev: devi)
}
}
}
struct ContentView: View {
@StateObject var bleManager = BLEManager.shared
init(bleManager: @autoclosure @escaping () -> BLEManager) {
_bleManager = StateObject(wrappedValue: bleManager())
print("ContentView init")
}
var body: some View {
VStack (spacing: 10) {
if !bleManager.isSwitchedOn {
Text("Bluetooth is OFF").foregroundColor(.red)
Text("Please enable").foregroundColor(.red)
}
else {
HStack {
Spacer()
if !bleManager.isScanning {Button(action: self.bleManager.startScanning){ Text("Scan ")
}
} else { Text("Scanning")
}
}
NavigationView {
List(bleManager.devices) { peripheral in
PeripheralLineView(devi: peripheral)
}.frame(height: 300)
}
}
}
}
}
//@available(iOS 15.0, *)
struct DeviceView: View {
var device: DeviceModel
var body: some View {
ZStack {
VStack {
Text("Data Window")
Text("Parameters")
}
}.onAppear(perform: {
device.setUpModel()
})
}
}
BLEManager.swift
import Foundation
import CoreBluetooth
struct Device: Identifiable {
let id: Int
let name: String
let rssi: Int
let peri: CBPeripheral
}
class BLEManager: NSObject, ObservableObject, CBCentralManagerDelegate, CBPeripheralDelegate {
static let shared: BLEManager = {
let instance = BLEManager()
return instance
}()
var BleManager = BLEManager.self
var centralBE: CBCentralManager!
@Published var isSwitchedOn = false
@Published var isScanning = false
var devices = [Device]()
var deviceIds = [UUID]()
private var activePeripheral: CBPeripheral!
override init() {
super.init()
print(" BLEManager init")
centralBE = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
isSwitchedOn = true
}
else { isSwitchedOn = false }
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String {
if !deviceIds.contains(peripheral.identifier) {
print("didDiscover id: \(peripheral.identifier)")
deviceIds.append(peripheral.identifier)
let newPeripheral = Device(id: devices.count, name: name, rssi: RSSI.intValue, peri: peripheral)
devices.append(newPeripheral)
print("didDiscover devices count now \(devices.count)")
}
}
}
/// save as activePeripheral and connect
func connectToDevice(to index: Int) {
print("BLEManager connectToDevice id: \(index)")
if devices.isEmpty {print ("devices is empty")}
activePeripheral = devices[index].peri
activePeripheral.delegate = self
centralBE.connect(activePeripheral, options: nil)
}
func startScanning() {
centralBE.scanForPeripherals(withServices: nil, options: nil)
isScanning = true
// Stop scan after 5.0 seconds
let _: Timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(stopScanning), userInfo: nil, repeats: false)
}
@objc func stopScanning() { // need @objc for above Timer selector
print("stopScanning")
centralBE.stopScan()
isScanning = false
print("After stopScanning devices count is \(devices.count)")
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { }
func disconnect(peripheral: Int) { }
func discoverServices(peripheral: CBPeripheral) { }
func discoverCharacteristics(peripheral: CBPeripheral) { }
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { }
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { }
}
DeviceModel.swift
import Foundation
import CoreBluetooth
class DeviceModel: BLEManager {
var index: Int //CBPeripheral position in found array
init(listIndex: Int) {
index = listIndex
print("DeviceModel init to device id: \(index)")
}
func setUpModel() {
connectToDevice(to: index)
}
}
Core Bluetooth
RSS for tagCommunicate with Bluetooth 4.0 low energy devices using Core Bluetooth.
Posts under Core Bluetooth tag
175 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello everyone,
Like so many others, I am a very newbie App developer. To my own detriment, I acknowledge I am trying to shortcut things a bit by using and modifying other pieces of code. Always easier to modify something that is already working, rather than staring at a blank screen not knowing how to begin.
So this leads me to this problem I am having. This is a Bluetooth application. And the Bluetooth runs just fine in both of my views. However, when the Bluetooth is linked and active, and I am receiving data, a Timer will not run. As soon as I stop the Bluetooth source (using an Arduino nano), the time begins to count again. There are no errors flagged in Xcode, just does not work properly. I was hoping someone could take a look and find the issue, and let me know how to fix it. Hopefully it is something easy, but without any errors being thrown, hard to know what to look for. Thanks...
So this is my Bluetooth Code:
import Foundation
import CoreBluetooth
enum ConnectionStatus: String {
case connected
case disconnected
case scanning
case connecting
case error
}
let BarrelBaristaService: CBUUID = CBUUID(string: "4FAFC201-1FB5-459E-8FCC-C5C9C331914B")
//Temperature F
let TemperatureCharacteristic: CBUUID = CBUUID(string: "5D54D470-8B08-4368-9E8F-03191A0314A5")
//Humidity %
let HumidityCharacteristic: CBUUID = CBUUID(string: "B2F5E988-C50F-4200-A1D9-5884F9417DEF")
//Weight %
let WeightCharacteristic: CBUUID = CBUUID(string: "BEB5483E-36E1-4688-B7F5-EA07361B26A8")
class BluetoothService: NSObject, ObservableObject {
private var centralManager: CBCentralManager!
var BarrelBarristaPeripheral: CBPeripheral?
@Published var peripheralStatus: ConnectionStatus = .disconnected
@Published var TempValue: Float = 0
@Published var HumidValue: Float = 0
@Published var WeightValue: Float = 0
@Published var Connected: Bool = false
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func scanForPeripherals() {
peripheralStatus = .scanning
centralManager.scanForPeripherals(withServices: nil)
}
}
extension BluetoothService: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .poweredOn {
print("CB Powered On")
scanForPeripherals()
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
if peripheral.name == "Barrel Barista" {
print("Discovered \(peripheral.name ?? "no name")")
BarrelBarristaPeripheral = peripheral
centralManager.connect(BarrelBarristaPeripheral!)
peripheralStatus = .connecting
}
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
peripheralStatus = .connected
Connected = true
peripheral.delegate = self
peripheral.discoverServices([BarrelBaristaService])
centralManager.stopScan()
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
peripheralStatus = .disconnected
Connected = false
}
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
peripheralStatus = .error
print(error?.localizedDescription ?? "no error")
}
}
extension BluetoothService: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service in peripheral.services ?? [] {
if service.uuid == BarrelBaristaService {
print("found service for \(BarrelBaristaService)")
peripheral.discoverCharacteristics([TemperatureCharacteristic], for: service)
peripheral.discoverCharacteristics([HumidityCharacteristic], for: service)
peripheral.discoverCharacteristics([WeightCharacteristic], for: service)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics ?? [] {
peripheral.setNotifyValue(true, for: characteristic)
print("found characteristic, waiting on values.")
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic.uuid == TemperatureCharacteristic {
guard let data = characteristic.value else {
print("No data received for \(characteristic.uuid.uuidString)")
return
}
let TempData: Float = data.withUnsafeBytes { $0.pointee }
TempValue = TempData
}
if characteristic.uuid == HumidityCharacteristic {
guard let data = characteristic.value else {
print("No data received for \(characteristic.uuid.uuidString)")
return
}
let HumidData: Float = data.withUnsafeBytes { $0.pointee }
HumidValue = HumidData
}
if characteristic.uuid == WeightCharacteristic {
guard let data = characteristic.value else {
print("No data received for \(characteristic.uuid.uuidString)")
return
}
let WeightData: Float = data.withUnsafeBytes { $0.pointee }
WeightValue = WeightData
}
}
}
Hello everyone,
I've developed an application using ElectronJS and NodeJS, utilizing the Web Bluetooth API for connecting to and streaming data from peripherals. Initially, this was built and tested on macOS Ventura, where everything worked as expected. However, I've encountered a couple of issues post the Sonoma update.
Issue 1: Slower Streaming Speed Post-Sonoma Update
After updating to Sonoma, the streaming speed from peripherals significantly decreased. This is perplexing because the app continues to perform well on Ventura. To troubleshoot, I even developed a version using Rust with the btleplug library, hoping for improved Bluetooth performance. However, this did not lead to any noticeable difference; both the Electron and Rust versions perform nearly the same. Has anyone experienced similar issues or knows what might be causing this slowdown?
Issue 2: GATT Operation Error Resolved, but Streaming Speed Affected
On Ventura, one specific command consistently failed with a GATT operation error. Interestingly, post-Sonoma update, this command works without error, but this seems to have affected the streaming speed. The improved GATT operation seems to come at the cost of decreased streaming performance. Is there a known connection between these two aspects, or has anyone observed a similar trade-off?
I'm looking for insights or suggestions to resolve these issues, particularly the streaming speed degradation post-Sonoma. The application needs to maintain consistent performance across different macOS versions, and these discrepancies are quite challenging.
Thank you in advance for your help and insights!
Best regards,
Hello,
I had trouble with bluetooth on my MacBook Air running macOs Sonoma 14.2.1.
I could not find some bluetooth devices, like my iPad for instance, so I decided to delete the plist file to "reset" bluetooth settings. Unfortunately bluetooth still behaves the same and additionally PacketLogger stopped working. It stays empty and does not show any traffic. Anybody knows what to do here?
I have used this example to create the following code:
import Foundation
import CoreLocation
let monitorName = "BeaconMonitor"
let testBeaconId = UUID(uuidString: "EDFA3FFA-D80A-4C23-9104-11B5B0B8E8F3")!
@MainActor
public class ObservableMonitorModel: ObservableObject {
private let manager: CLLocationManager
public var monitor: CLMonitor?
init() {
self.manager = CLLocationManager()
self.manager.requestWhenInUseAuthorization()
self.manager.requestAlwaysAuthorization()
}
func startMonitoringConditions() {
Task {
monitor = await CLMonitor(monitorName)
await monitor!.add(getBeaconIdentityCondition(), identifier: "Beacon")
for identifier in await monitor!.identifiers {
guard let lastEvent = await monitor!.record(for: identifier)?.lastEvent else { continue }
print(identifier, lastEvent.state)
}
for try await event in await monitor!.events {
print("Event", event.identifier, event)
}
}
}
}
func getBeaconIdentityCondition() -> CLMonitor.BeaconIdentityCondition {
CLMonitor.BeaconIdentityCondition(uuid: testBeaconId)
}
Unfortunately, running this on my iPhone only prints "Beacon CLMonitoringState". I don't see anything from the for try await block starting with "Event".
Any ideas where I've gone wrong?
I would like to know how to check the Bluetooth version on macOS.
There have been similar questions in the past, and the answers suggested checking the LMP Version in the system profile to find this information.
However, in the latest macOS (Sonoma - 14.2.1), this method no longer seems to work. According to other posts on platforms like Reddit, it appears that this change has persisted at least until version 12.
I considered using terminal commands for more detailed information, but the results were similar.
❯ system_profiler -detailLevel full SPBluetoothDataType
Bluetooth:
Bluetooth Controller:
Address: 3C:06:30:0F:92:18
State: On
Chipset: BCM_4378
Discoverable: Off
Firmware Version: 21.1.527.3724
Product ID: 0x4A01
Supported services: 0x392039 < HFP AVRCP A2DP HID Braille LEA AACP GATT SerialPort >
Transport: PCIe
Vendor ID: 0x004C (Apple)
Wanted to check if anyone here has insights or alternative methods to determine the Bluetooth version on the latest macOS. If there's a command-line solution or any other approach that works with recent macOS versions, I would greatly appreciate the guidance.
I scan my ble device with the code below.
centralManager.scanForPeripherals(withServices: [connectionServiceUUID], options: nil)
and the call back method is called when the device is scaned.
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { ... }
I have 2 questions with the value of advertisementData[CBAdvertisementDataLocalNameKey] from the callback method.
Suppose there is connections, and the localNameKey of the device is A. When it is scanned and connected at first, the advertisementData[CBAdvertisementDataLocalNameKey] I get is not A but something else. Here, if I do the same then I get A.
Now, I change the localNameKey of the device to B. And when it is scanned, the advertisementData[CBAdvertisementDataLocalNameKey] is still A, and I do the same, now it is B. Why?
When the screen is off, advertisementData[CBAdvertisementDataLocalNameKey] never changes, why?
I have a BLE device and the centralManger scans with "centralManager.scanForPeripherals(withServices: [connectionServiceUUID], options: nil)"
Then
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { ... } is called.
Here, I could get the advertisementData[CBAdvertisementDataLocalNameKey].
I have set my BLE device to change its local name key for every connections.
The BLE communication is repeated in the background.(scan, connect, stop scan, disconnect, ... etc)
It works well, but when the screen is off, the value of advertisementData[CBAdvertisementDataLocalNameKey] in didDiscover does not change. Why?
Hello,
I'm looking for an end-to-end example project that shows a correct implementation for the new iBeacon CoreLocation APIs in iOS 17.0 (CLMonitor, etc.). Ideally the example would cover background waking as that is the area in which I am facing the largest challenges.
Perhaps there's an Open Source project or an official Apple example?
Thanks for pointing me in the right direction.
Jeremy
objectC program: iOS all : iPhone ~
swift program. : iOS 13 ~ : iPhone 6s ~
swiftUI Program : iOS 13 ~ : iPhone 6s ~
bluetooth classic : ~ iPhone 4s
Bluetooth Low Engery : iPhone 5 ~
are All above content right?
i am making iOS app with swiftUI app, and Bluetooth Low Energy.
after making app, i found that my app can run on greater than iOS13 , iPhone 6s.
how many is ther number of above iPhone6s User ?
Hello everyone:
I used corebluetooth, but currently I cannot connect Airpods headphones.
details as following:
Unable to scan to unconnected devices.
If the device is already linked, it can be searched, but the connection cannot be made successfully.
I searched Google for related posts but couldn't find a website that can solve the problem. I need to ask if there are any relevant restrictions on Airpods or if there are other real solutions that I can link to.
thank you all.
I am using nRF52840, and have set up BLE 5 extended advertising. I was able to connect with the nRF Connect app to nrf52840 device using iPhone 11, 12, 13 running iOS 16.
Recently after updating to iOS 17, I can only discover the BLE device, but can't manage to connect to the device from the app. I can only connect to the device via iPhone 11, running iOS 17. However, all the other later versions of iPhone do not permit me to connect with the nrf device. As a test switching to BLE4 advertising, devices are both discoverable and connectable, on these same iPhone versions running iOS 17. I need to use BLE5 and can't switch to BLE 4 for production release.
Also, the same devices can be both discovered and connected to, using Android phones that support BLE 5.
While trying to connect with iPhone running iOS 17, I don't get a response to the connection from the BLE5 advertisement. This was confirmed by Wireshark capture while trying to connect on the iPhone. Nordic has confirmed that the issue is not on their side and hence would like your help to investigate this further.
I am detecting problems with the volume level with the Bluetooth connection after the iOS 17.2 update. Before this problem persisted on the iPhone 11 and the iPhone 15 Pro, after the 17.2 update it seems that the problem was fixed on the iPhone 11 but still It persists on the iPhone 15 Pro. I have never had problems with the volume level in my car, but something Apple has changed that continues to affect it. How can it be corrected? Thank you very much for your support. I did a test with the same song and the same volume level (maximum volume on the smartphone and volume 12 on my Suzuki Swift) and these were the decibels results obtained. The Iphone 11 and 15 Pro has updated to iOS 17.2
Hello,
I've been trying to debug a Bluetooth issue with an app I'm working with. Is there a way to capture the LE Set Scan Parameters HCI event?
I've downloaded the Bluetooth debug profile and managed to capture the HCI traffic using the Packet Logger tool. The problem is that I don't see the Scan Parameters event occurring. I can see Advertisement parameters being set (which is odd that the iPhone is doing so, even with Airdrop and BLE disabled).
I can see lots of Advertising Reports which indicate that the device is scanning; but I can never catch when the parameters are set for that.
I've attached a sample log of me just toggling the Bluetooth off and on. Any insight is appreciated.
Thank you
When I ran the same code with the same Bluetooth device
On iPhone 15 promax
Corebluetooth CentralManager's willRestoreState delegate method is not called.
iPhone 15 promax: iOS 17.1.1
iPhone 12 promax : iOS 17.0.3
I tested on both devices and it works fine on 12.
Note: CBCentralManagerOptionRestoreIdentifierKey is of course specified.
I have a custom framework that allows you to handle all Bluetooth actions, such as connect, scan, etc. Additionally, I have two applications using this framework: a test app and a real app. I'm trying to implement auto-reconnection for turning Bluetooth off/on and out of range. While it works well in my test app, it doesn't in the real app. Here is my logic:
Firstly, I scan for a peripheral with a specific service UUID:
manager.scanForPeripherals(withServices: [self.targetUuid], options: scanOptions)
As a result, I have a CoreBluetooth callback response:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
Then I connect to the peripheral:
connect(cbPeripheral, options: options)
And as a result:
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
After that, I save the UUID as a String. Then, I try to disconnect the peripheral from the phone (turn BT off/on or go out of range) and connect back.
I've investigated different behaviours and found that in my test app, I have the same peripheral UUID even after disconnection, but in the real app, the UUID changes.
I found this:
The UUID will stay constant for a peripheral with randomized addresses for paired devices only for the lifetime of the pairing.
If a device is not paired, according to the LE Privacy rules (RRA), the UUID will change as a peer unit is neither capable nor supposed to track a device across changing addresses.
And this:
Connection attempts do not time out (as stated in the Apple documentation: [link]). Just be sure to also keep a reference to the peripheral object; otherwise, the connection gets canceled.
Here is my logic for reconnection in case of being out of range:
centralManager(_:didDisconnectPeripheral:error:)
[ERROR] - Peripheral was disconnected error -> Optional(Error Domain=CBErrorDomain Code=6 "The connection has timed out unexpectedly." UserInfo={NSLocalizedDescription=The connection has timed out unexpectedly.})
connect(cbPeripheral, options: options)
My question is:
What can affect UUID changing? Do I need to store a whole Peripheral Device object instead of UUID string?
Hi developers,
I am trying this code to read from 3 bluetooth beacon:
class BeaconScanner0: NSObject, CBCentralManagerDelegate {
var centralManager: CBCentralManager!
var shouldContinueScanning = true // Add a flag to control scanning
var i=0
var BeaconRSSI = [0, 0, 0]
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
if central.state == .unauthorized {
print("Bluetooth access is unauthorized. Requesting permission...")
centralManager.delegate = self
}
else if central.state == .poweredOn {
print("Bluetooth is powered on. Scanning for beacons...")
// Start scanning for all peripherals
centralManager.scanForPeripherals(withServices: nil, options: nil)
} else {
print("Bluetooth is not powered on or available.")
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi: NSNumber)->[Int] {
print("BeaconRSSI: \(BeaconRSSI)")
if let name = peripheral.name {
if name.contains("BlueCharm") {
if name.contains("79") {
BeaconRSSI[0] = rssi.intValue
// i += 1
}
if name.contains("67") {
BeaconRSSI[1] = rssi.intValue
// j += 1
}
if name.contains("96") {
BeaconRSSI[2] = rssi.intValue
// k += 1
}
}
}
return BeaconRSSI
}
}
it got back the error (bug!) like below:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'String does not represent a valid UUID'
*** First throw call stack:
(0x1b361e69c 0x1ab8d7c80 0x1b2b7cdd8 0x1d8062634 0x1d80628a8 0x1d8025130 0x1d8024cd8 0x104a95140 0x104a8baa0 0x104a8b970 0x104a8bac4 0x104a8b818 0x104a8caf0 0x1057c2b34 0x1057c4690 0x104a8cb54 0x104a8cb6c 0x1057c2b34 0x1057c4690 0x104a8cc0c 0x104a8cc68 0x1057c2b34 0x1057c4690 0x104a8cd28 0x104a8cfc0 0x1057c2b34 0x1057c4690 0x104a8d064 0x104a8d61c 0x1057c2b34 0x1057c4690 0x104a8d6c4 0x104a93d98 0x104a93c74 0x1b80c709c 0x1b839a624 0x1b8ac2b68 0x1b8ac0300 0x1b8b308e8 0x1b8b30948 0x1b5794fe0 0x1b4ba9aa8 0x1b4ba9630 0x1b4bafb60 0x1b4ba8e3c 0x1b5a7e03c 0x1b35691b8 0x1b35679ac 0x1b35658ac 0x1b3565478 0x1f6abe4f8 0x1b598f360 0x1b598e99c 0x1b83a04b8 0x1b83a02fc 0x1b8010e90 0x104a9eb3c 0x104a9ec84 0x1d629ddcc)
libc++abi: terminating due to uncaught exception of type NSException
*** Assertion failure in -[CBUUID initWithString:safe:], CBUUID.m:219
could anyone help me with this problem.
Thanks beforehand.
使用苹果X手机,版本号16.3.1,连接不同android 10 平台上集成的carplay都能连接成功,但是其中一个平台苹果X手机的蓝牙详情中不显示carpaly车载选项按钮,忽略蓝牙也没有办法断开carpaly连接。
let session = AVAudioSession.sharedInstance()
do {
try session.setCategory(AVAudioSession.Category.playback)
try session.setActive(true)
//playAndRecord <AVAudioSessionPortDescription: 0x2828dc2b0, type = Speaker; name = 扬声器; UID = Speaker; selectedDataSource = (null)>
//playback <AVAudioSessionPortDescription: 0x28204c1a0, type = BluetoothA2DPOutput; name = M2; UID = 00:02:5C:22:22:11-tacl; selectedDataSource = (null)>
print(session.currentRoute.outputs)
} catch {
print(error)
}
when I ssession.setCategory(AVAudioSession.Category.playback) audio play output a2dp ble devices.
session.currentRoute.outputs print bellow
`<AVAudioSessionPortDescription: 0x28204c1a0, type = BluetoothA2DPOutput; name = M2; UID = 00:02:5C:22:22:11-tacl; selectedDataSource = (null)>
when I ssession.setCategory(AVAudioSession.Category.playAndRecord)
output
<AVAudioSessionPortDescription: 0x2828dc2b0, type = Speaker; name = 扬声器; UID = Speaker; selectedDataSource = (null)>
BluetoothA2DPOutput is gone.
but it is normal in ios15-16.
Is there any solution? I want to record audio and play music at the same time. And the music is output from the Bluetooth speaker
When I set the AVAudioSessionCategory avAudioSessionCategory: AVAudioSessionCategory.playAndRecord, sound to come out of the built-in speaker instead of Bluetooth headphones。ios17 。It is normal in IOS 16 or 15
final session = await AudioSession.instance; await session.configure(AudioSessionConfiguration( avAudioSessionCategory: AVAudioSessionCategory.playAndRecord, avAudioSessionCategoryOptions:AVAudioSessionCategoryOptions.allowBluetooth | AVAudioSessionCategoryOptions.allowBluetoothA2dp, avAudioSessionMode: AVAudioSessionMode.defaultMode, avAudioSessionRouteSharingPolicy: AVAudioSessionRouteSharingPolicy.defaultPolicy, avAudioSessionSetActiveOptions: AVAudioSessionSetActiveOptions.none, androidAudioAttributes: const AndroidAudioAttributes( contentType: AndroidAudioContentType.music, flags: AndroidAudioFlags.none, usage: AndroidAudioUsage.media, ), androidAudioFocusGainType: AndroidAudioFocusGainType.gain, androidWillPauseWhenDucked: true, ));
How to make sound output from Bluetooth instead of speakers in IOS 17?
How to make sound output from Bluetooth instead of speakers in IOS 17?