ios - Voice input in Android TV Remote Control - Stack Overflow

admin2025-05-02  1

I am developing a voice search feature using Android TV Remote Control v2 technology on iOS.
While I can successfully connect to the smart TV, send commands, and modify text in input fields, I am unable to trigger the voice assistant.
Based on my understanding, I need to send a RemoteVoiceBegin packet, which I am already implementing. However, the voice assistant does not activate, and the socket closes with a sessionID of -1.

Here is the code I am using.
Can you help identify what might be going wrong?

 private func createVoiceCommand() {
        // Create the voice message data
        guard let data = createVoiceMessage() else {
            print("Failed to create voice message.")
            return
        }
        
        // Send the data asynchronously in the background
                // Attempt to send the data
                self.remoteManager.sendVoiceData(data: data)
                print("Sending start voice command: \(data)")
        
    }

    func createVoiceMessage() -> Data? {
        
        // Create voice begin with config
        var message = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteMessage()
        let voiceBegin = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteVoiceBegin.with {
            
            $0.voiceConfig = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteVoiceConfig.with {
                $0.sampleRate = Int32(RemoteXVoiceInput.sampleRate)
                $0.channelConfig = Int32(RemoteXVoiceInput.channelConfig)
                $0.audioFormat = Int32(RemoteXVoiceInput.audioFormat.rawValue)
            }
            $0.sessionID = -1
        }

        // Create final message
        message.remoteVoiceBegin = voiceBegin

        print("Voice message created: \(message)")

        // Serialize the message and handle any errors
        do {
            return try message.serializedData()
        } catch {
            print("Failed to serialize voice message: \(error)")
            return nil
        }
    }
func sendVoiceData(data: Data) {
            let varintData = Data(Encoder.encodeVarint(UInt(data.count)))
            print("Encoded length (varint): \(varintData)")
            
            // Combine varint length data and serialized message data
            var combinedData = Data()
            combinedData.append(varintData)
            combinedData.append(data)
            print("Combined data to send: \(combinedData)")
            
            // Now send the data using the provided send method
            self.remoteManager.send(varintData, data)
            print("Data sent successfully")
            print(Array(combinedData))
        
    }

I am developing a voice search feature using Android TV Remote Control v2 technology on iOS.
While I can successfully connect to the smart TV, send commands, and modify text in input fields, I am unable to trigger the voice assistant.
Based on my understanding, I need to send a RemoteVoiceBegin packet, which I am already implementing. However, the voice assistant does not activate, and the socket closes with a sessionID of -1.

Here is the code I am using.
Can you help identify what might be going wrong?

 private func createVoiceCommand() {
        // Create the voice message data
        guard let data = createVoiceMessage() else {
            print("Failed to create voice message.")
            return
        }
        
        // Send the data asynchronously in the background
                // Attempt to send the data
                self.remoteManager.sendVoiceData(data: data)
                print("Sending start voice command: \(data)")
        
    }

    func createVoiceMessage() -> Data? {
        
        // Create voice begin with config
        var message = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteMessage()
        let voiceBegin = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteVoiceBegin.with {
            
            $0.voiceConfig = Com_Multi_Tv_Utils_AndroidTvRemote_RemoteCommunicationTv_RemoteVoiceConfig.with {
                $0.sampleRate = Int32(RemoteXVoiceInput.sampleRate)
                $0.channelConfig = Int32(RemoteXVoiceInput.channelConfig)
                $0.audioFormat = Int32(RemoteXVoiceInput.audioFormat.rawValue)
            }
            $0.sessionID = -1
        }

        // Create final message
        message.remoteVoiceBegin = voiceBegin

        print("Voice message created: \(message)")

        // Serialize the message and handle any errors
        do {
            return try message.serializedData()
        } catch {
            print("Failed to serialize voice message: \(error)")
            return nil
        }
    }
func sendVoiceData(data: Data) {
            let varintData = Data(Encoder.encodeVarint(UInt(data.count)))
            print("Encoded length (varint): \(varintData)")
            
            // Combine varint length data and serialized message data
            var combinedData = Data()
            combinedData.append(varintData)
            combinedData.append(data)
            print("Combined data to send: \(combinedData)")
            
            // Now send the data using the provided send method
            self.remoteManager.send(varintData, data)
            print("Data sent successfully")
            print(Array(combinedData))
        
    }
Share Improve this question edited Jan 2 at 7:19 soundflix 2,93912 gold badges16 silver badges34 bronze badges asked Jan 2 at 5:03 Muhammad UmerMuhammad Umer 477 bronze badges 4
  • did you check why socket is closed? – Jatin Commented Jan 2 at 6:03
  • @Jatin yes.. empty or incomplete data received sending: [242, 1, 20, 8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 18, 7, 8, 192, 62, 16, 16, 24, 2] // hex F2 01 14 08 FF FF FF FF FF FF FF FF FF 01 12 07 08 C0 3E 10 10 18 02 – Muhammad Umer Commented Jan 2 at 7:23
  • hi @Jatin.. do you have any answer to this?? – Muhammad Umer Commented Jan 6 at 5:18
  • No i don't have but i think that's happaning due to socket close that's why commented. – Jatin Commented Jan 6 at 5:23
Add a comment  | 

1 Answer 1

Reset to default 3

I got Voice Input feature working.

To handle VoiceBegin, you have to first listen for a RemoteVoiceBegin message from the TV device. This message is sent in response to sending KEYCODE_SEARCH (84) to initiate the search.

The RemoteVoiceBegin message from the device contains a session_id and a package name, but only the session_id needs to be read, as it will be used in subsequent calls to VoiceBegin, VoicePayload, and VoiceEnd.

Upon receiving the RemoteVoiceBegin, a RemoteVoiceBegin message must be sent back with just the session_id. This step is necessary to enable the reception of Payload messages afterward.

转载请注明原文地址:http://www.anycun.com/QandA/1746133429a92037.html