Skip to content

Commit c8766eb

Browse files
committed
Add SensorEventQueue
1 parent 90f470a commit c8766eb

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
//
2+
// SensorEventQueue.swift
3+
// SwiftAndroid
4+
//
5+
// Created by Alsey Coleman Miller on 7/6/25.
6+
//
7+
8+
#if os(Android)
9+
import Android
10+
import AndroidNDK
11+
#endif
12+
13+
/// An event queue for receiving sensor events.
14+
///
15+
/// Create via `SensorManager.createEventQueue(looper:)`.
16+
/// The queue is automatically destroyed when this value is deinitialized.
17+
public struct SensorEventQueue: ~Copyable {
18+
19+
internal let queue: OpaquePointer
20+
21+
/// Retained to call `ASensorManager_destroyEventQueue` on deinit.
22+
internal let manager: OpaquePointer
23+
24+
internal init(queue: OpaquePointer, manager: OpaquePointer) {
25+
self.queue = queue
26+
self.manager = manager
27+
}
28+
29+
deinit {
30+
ASensorManager_destroyEventQueue(manager, queue)
31+
}
32+
}
33+
34+
// MARK: - Methods
35+
36+
public extension SensorEventQueue {
37+
38+
/// Enables the sensor at the default sampling rate.
39+
///
40+
/// Prefer ``register(_:samplingPeriod:maxReportLatency:)`` for more control.
41+
func enable(_ sensor: Sensor) throws(AndroidSensorError) {
42+
let result = ASensorEventQueue_enableSensor(queue, sensor.pointer)
43+
guard result >= 0 else {
44+
throw .enableSensor(result)
45+
}
46+
}
47+
48+
/// Disables the sensor so it no longer posts events to this queue.
49+
func disable(_ sensor: Sensor) throws(AndroidSensorError) {
50+
let result = ASensorEventQueue_disableSensor(queue, sensor.pointer)
51+
guard result >= 0 else {
52+
throw .disableSensor(result)
53+
}
54+
}
55+
56+
/// Registers a sensor with this queue, enabling it and setting the desired
57+
/// sampling period and batch latency.
58+
///
59+
/// - Parameters:
60+
/// - sensor: The sensor to register.
61+
/// - samplingPeriod: Desired sampling period in microseconds.
62+
/// Use `SensorDelay.normal`, `.game`, `.ui`, or `.fastest` as starting points.
63+
/// - maxReportLatency: Maximum delay in microseconds before an event must be
64+
/// reported. Pass `0` to disable batching.
65+
func register(
66+
_ sensor: Sensor,
67+
samplingPeriod: Int32 = SensorDelay.normal,
68+
maxReportLatency: Int64 = 0
69+
) throws(AndroidSensorError) {
70+
let result = ASensorEventQueue_registerSensor(
71+
queue, sensor.pointer, samplingPeriod, maxReportLatency
72+
)
73+
guard result >= 0 else {
74+
throw .registerSensor(result)
75+
}
76+
}
77+
78+
/// Sets the delivery rate for a sensor that is already registered.
79+
///
80+
/// - Parameters:
81+
/// - sensor: The registered sensor.
82+
/// - usec: Desired event interval in microseconds.
83+
func setEventRate(for sensor: Sensor, usec: Int32) throws(AndroidSensorError) {
84+
let result = ASensorEventQueue_setEventRate(queue, sensor.pointer, usec)
85+
guard result >= 0 else {
86+
throw .setEventRate(result)
87+
}
88+
}
89+
90+
/// Returns `true` if there are pending events in the queue.
91+
var hasEvents: Bool {
92+
ASensorEventQueue_hasEvents(queue) > 0
93+
}
94+
95+
/// Reads up to `maxCount` pending events from the queue.
96+
///
97+
/// - Parameter maxCount: Maximum number of events to read per call.
98+
/// - Returns: An array of `SensorEvent` values (may be empty).
99+
func getEvents(maxCount: Int = 16) throws(AndroidSensorError) -> [SensorEvent] {
100+
var buffer = [ASensorEvent](repeating: ASensorEvent(), count: maxCount)
101+
let count = ASensorEventQueue_getEvents(queue, &buffer, maxCount)
102+
guard count >= 0 else {
103+
throw .getEvents(Int32(count))
104+
}
105+
return buffer.prefix(count).map { SensorEvent($0) }
106+
}
107+
}

0 commit comments

Comments
 (0)