Skip to content

Conversation

@senolmurat
Copy link

Implemented Bluetooth Live Activities using IOBluetooth

Live Activities

Live activities will be shown when a device connects or disconnects.

live_activity_connect_1 mov

live_activity_disconnect mov

Connection displays device type on the left and battery percentage on the right with changing colors depending on the percentage (0=red -> 100=green)

  • Altough I could not test it, device Icon supports many unique devices like AirPods, Beats etc.
  • Device Icon is gathered automatically using device name fallbacks to device MajorClass and MinorClass
  • Custom SFSymbol Icons for devices can be set for not recognized devices.
  • Device Icon is tintable with accent color

Sneak Peek

Sneak Peek is available and can be toggled on/off with 2 different styles, Default and Inline; similar to Media Sneak Peek

inline_sneak_peek mov

standart_sneak_eek_1 mov

More Examples

live_activity_connect_2 mov

standart_sneak_peek_2 mov

standart_sneak_peek_3 mov

Settings

settings

Notes

Any feedback is welcome.
IOBluetooth is somewhat inconsistent with device information. I have failed to gather battery information consistently on multiple devices and finally I've decided to use pmset -g accps command and captured the output to display battery percentages.

Device classes are similar stor. Some devices I've tried did not broadcast class info so I opted for name matching and finally custom images so that users can anter a keyword and set a custom image for their unrecognized devices. I've initially used system_profiler SPBluetoothDataType command output to gather device MinorClass but realized app needs to be un-sandboxed for this command to give output inside an app so I just scraped it as I think it was not worth to un-sandbox this app just for this.

Tried to keep it lightweight its all event driven by Notifications. Only polling is for battery levels when a device connects to wait for pmset -g accps output to refresh and that timeouts after 2 seconds

Issues

  • Some devices do not broadcast disconnect signal and disconnect animation does not trigger because of this. I've failed to find a solution for it.
  • I've not tested with many devices , I only have a bluetooth keyboard, headphones and xbox gamepad.
  • User has to enter the SFSymbol name as text for the custom images. I did not implemented a SFSymbolPicker. I could have used something similar like https://github.com/xnth97/SymbolPicker but I didn't want to bloat it just for this.

@senolmurat
Copy link
Author

Related to #620 and #694
Resolves #620
Somewhat Resolves #694 , except animation

@senolmurat senolmurat marked this pull request as draft November 22, 2025 10:37
@senolmurat senolmurat marked this pull request as ready for review November 22, 2025 11:01
@Alexander5015
Copy link
Member

I think a thinner circle might look better for the battery life, let me know what you think. It may also look better if you rounded the ends of the colored segment.

If you want to use unsandboxed apis, you can update the BoringNotchXPCHelper to make those calls for you, which allows the app to remain sandboxed. If the current solution is working fine, then no need but thought I would point it out. This is being utilized by the HUD already.

For custom symbols, I think the storage increase is definitely worth it, unless it really adds a lot of extra size to the app. The user experience is the most important thing, there is no need to save a few MB of storage space here imo.

@senolmurat
Copy link
Author

Okey these are some really good feedback thank you. Did some improvements based on your feedback.

  • BatteryRing circle made a bit thinner with 2px width. For rounded line cap the problem is with circle this small percentages > 95 pretty much looks like 100

.rounded
Screenshot 2025-11-24 at 13 59 23
.butt
Screenshot 2025-11-24 at 14 00 00
What you think ? I think we can still go with .rounded since most devices does not broadcast battery level that precisely tbh.

  • Implemented minor class fetching with XPCHelper for bluetooth devices. This will improve the device class detection.
  • Implemented https://github.com/xnth97/SymbolPicker for choosing SFSymbols, users can now just search and choose a symbol for their devices. app size increased ≈900kb so its deff worth it imo.

@Kevlar35
Copy link

Kevlar35 commented Nov 25, 2025

For the ring, if you divide the percentage by 102 instead of 100, it should make a full ring at 100% instead of the current 98%.

@Alexander5015
Copy link
Member

I think the code architecture could use some work. Ideally you would have data model(s) with fields for the different properties of bluetooth devices. And then its probably best to also split up the bluetooth discovery code from the battery code as well, and maybe icon can be its own thing as well. We also need a better way to manage the live activities but that's on me to implement. I think we should wait to merge this until I get that done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants