I'm creating a native iOS module for Expo (after this guide) to intercept bluetooth headphones controls (like play/pause, etc.)
The problem is that the event listeners set by playCommand.addTarget aren't called when the remote command is received. At the same time the native code (MyListener functionality) works well (remote events are printed in logs) if I use it in a pure iOS/Swift app.
I can prove that the native module is visible on the JS side because when I call MyHeadsetControlsModule.startListening() I see that the native side is called - the logs
startListening! and setting listeners are printed. But the listeners themselves are not called by the remote commands.
My native module code is:
public class MyHeadsetControlsModule: Module {
var myListener: MyListener?
public func definition() -> ModuleDefinition {
Name("MyHeadsetControls")
Function("startListening") {
print("startListening!")
self.myListener = MyListener()
}
}
}
class MyListener: NSObject {
let commandCenter = MPRemoteCommandCenter.shared()
init() {
print("setting listeners")
commandCenter.playCommand.addTarget { [weak self] event in
print(event)
if event.command.isEnabled {
print("Toggle play/pause state or perform any action")
return .success
}
return .commandFailed
}
// the rest of remote controls commands: pause, next track, previous track are similar, omitted here
}
}
index.ts is simple:
import MyHeadsetControlsModule from './MyHeadsetControlsModule';
export const startListening = () => {
MyHeadsetControlsModule.startListening();
};
I've checked the MyListener object exists & not deallocated with logging in init/deinit like this:
override init() {
super.init()
print("MyListener init \(self.hash)")
}
deinit {
print("MyListener DEinit \(self.hash)")
}
Also, setting a breakpoint & inspecting MyListener.commandCenter from the debugger shows that the remote commands do have targets set.
So after trying all this stuff I'm just wondering if I'm facing some iOS Swift API not supported by Expo modules? Can anyone give me a hint to where dig on?
EDIT: Tested with a bare React Native flow - the same results: native module's connected (proved by native logs), remote commands aren't triggered.