Native support for Android TV / Android devices

Yes :slight_smile:

Does anyone know how to control the Android TV (Xiaomi Mi Box S specifically) through ip/tcp and/or Bluetooth? I cannot use the ADB because of the restrictions in combination with the USB port (with an ethernet adapter)
I thought my google skills were on point, but I am having a hard time finding the network api, while there are some Android apps that do control it over the network.

nmap shows some open ports:

Nmap scan report for xxx.xxx.xxx.xxx
Host is up (0.0011s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
8008/tcp open  http
8009/tcp open  ajp13
8080/tcp open  http-proxy
8443/tcp open  https-alt
9000/tcp open  cslistener
9090/tcp open  zeus-admin

Where 8008 and 8009 seem to be for the build-in Chromecast (according to google)

1 Like

How? I am only able to turn off. But after that the entity becomes unavailable. So i am not able to turn on

Hi, api was finnaly able to get this working whit both the adb python and adb server options. The component works just but there is a huge delay at any interaction (pause, launch apps, recovery states…) like a good 5 to 7 seconds

I have other media players added from the same tv and the actions are instant. Is this a specific adb problem? Any way to fix it ?

Is this delay present with both the Python ADB and ADB server configurations? Is one approach faster than the other?

Now I see where you’re getting… :wink:

AndroidTV has problems on some devices, that aren’t able to handle wake-on-lan. In my case the tv component (Sony Bravia with PSK) takes this into account.

My only idea would be to set up a wakelock. Not ideal, but better than nothing. :slight_smile:

Yes. I did more testing and the delay (5-9 seconds) is present on everything related whit the media player (update device status, play/pause, switch sources, volumen up/down/mute).
The delay is there interacting whit the media players cards or calling one of the media player functions whit services

I can confirm that sending anything whit the adb_command is instant. Also i cant see a diference of speed whit python adb or server adb because the delay is not always consistent ( goes from sometimes 3 seconds to 9 seconds).

How the ‘“select source” service launch the apps? If i try to open netflix from the sources takes like 3 to 5 seconds, whit adb command -> am start -n com.netflix.ninja/.MainActivity is instant

Also, i have just tried this beta version https://github.com/JeffLIrion/ha-androidtv whit unfortunately the same results :confused:

@Sxkre, How would I go about sending commands via adb instead of the regular way, which are awfully slow? Also, anyway to merge this with Google Cast integration card, and pull the metadata?

Thanks

Go to services —> androidtv.adb _command. For netflix the example is am start -n com.netflix.ninja/.MainActivity

I find the package name to launch whit this ( u need to adb shell on your tv first)—> dumpsys package | grep hbo | grep Activity (change hbo for the app name and a couple of process will show up. Just try one of them whit am start -n and the app will launch

Hi, I’m using below code in a glance card configured to open app with tap_action and close the app with hold_action

type: glance
entities:
  - entity: script.start_netflix
    icon: 'mdi:netflix'
    tap_action:
      action: call-service
      service: script.start_netflix
    hold_action:
      action: call-service
      service: script.stop_netflix
  - entity: script.start_primevideo
    icon: 'mdi:amazon'
    tap_action:
      action: call-service
      service: script.start_primevideo
    hold_action:
      action: call-service
      service: script.stop_primevideo
  - entity: script.start_playmusic
    icon: 'mdi:play-circle-outline'
    tap_action:
      action: call-service
      service: script.start_playmusic
    hold_action:
      action: call-service
      service: script.stop_playmusic
show_name: false
show_state: false
columns: 3

my script

start_netflix:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: com.netflix.ninja
    service: media_player.select_source
  alias: Start Netflix
stop_netflix:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: '!com.netflix.ninja'
    service: media_player.select_source
  alias: Stop Netflix
start_primevideo:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: com.amazon.amazonvideo.livingroom
    service: media_player.select_source
  alias: Start Prime Video
stop_primevideo:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: '!com.amazon.amazonvideo.livingroom'
    service: media_player.select_source
  alias: Stop Prime Video
start_playmusic:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: com.google.android.music
    service: media_player.select_source
  alias: Start Play Music
stop_playmusic:
  sequence:
  - data:
      entity_id: media_player.android_tv
      source: '!com.google.android.music'
    service: media_player.select_source
  alias: Stop Play Music

Netflix is working fine, but Amazon Prime Video and Google play music is just closing, but not opening.

One more thing, how can I use the hold action in original remote to get more options like context menu when I press the middle enter button?

That’s odd that the androidtv.adb_command service is almost instant but the other controls are slow. The command is sent the same way. For example, hitting volume up is equivalent to sending the command input keyevent 24. A list of key events can be found here.

But if you’re just referring to how fast the state in HA updates, then I think that’s just a matter of the state getting updated after the androidtv.adb_command service.

Ah okay, I thought there was a more practical way of executing it via lovelace, no worries thanks.

Is there a way to force a quicker status update for the media player? I dont mind the delay selecting sources, but the volume, play/pause and specially the states is a deal breaker for me.
I have a automation to turn on my lights at night if any media is paused and match the light color whit the app color (Ej: pausing youtube turn light red, kodi blue, etc), and another one to turn the lights off whenever the media resumes.

That automation using the androitv component takes 5 to 6 seconds to do it, and for example using the kodi component everything is seamless and instant

That’s just how it is with a polling integration.

https://www.home-assistant.io/integrations/androidtv/#custom-state-detection

You can provide a scan_interval parameter to make it update more often. The default is10.

But when media is playing and you press pause in HA, does the media pause right away? (On the device, not in HA)

Hi there,

I’ve been struggling with setting up the connection to my Sony Android TV (KD-55X8505C) for a while now. I’ve tried the ADB Server approach and the Python ADB Implementation.
Both approaches end up in connection issues after running OK for around 3 hours.

You’ll find the debug logs attached. Do you have any advise what to do and how to fix it, based on the logs?

2020-01-29 03:19:02 DEBUG (SyncWorker_14) [androidtv.adb_manager] Sending command to 192.168.0.11:5555 via adb-shell: (dumpsys power | grep 'Display Power' | grep -q 'state=ON' || dumpsys power | grep -q 'mScreenOn=true') && echo -e '1\c' && dumpsys power | grep mWakefulness | grep -q Awake && echo -e '1\c' && (dumpsys audio | grep paused | grep -qv 'Buffer Queue' && echo -e '1\c' || (dumpsys audio | grep started | grep -qv 'Buffer Queue' && echo '2\c' || echo '0\c')) && dumpsys power | grep Locks | grep 'size=' && CURRENT_APP=$(dumpsys window windows | grep mCurrentFocus) && CURRENT_APP=${CURRENT_APP#*{* * } && CURRENT_APP=${CURRENT_APP%%/*} && echo $CURRENT_APP && (dumpsys media_session | grep -A 100 'Sessions Stack' | grep -A 100 $CURRENT_APP | grep -m 1 'state=PlaybackState {' || echo) && dumpsys audio | grep '\- STREAM_MUSIC:' -A 12
2020-01-29 03:19:02 DEBUG (SyncWorker_14) [adb_shell.adb_device] bulk_write: b'OPEN\x01\x00\x00\x00\x00\x00\x00\x00\xe2\x02\x00\x00\x19\xeb\x00\x00\xb0\xaf\xba\xb1'
2020-01-29 03:19:02 DEBUG (SyncWorker_14) [adb_shell.adb_device] bulk_write: b"shell:(dumpsys power | grep 'Display Power' | grep -q 'state=ON' || dumpsys power | grep -q 'mScreenOn=true') && echo -e '1\\c' && dumpsys power | grep mWakefulness | grep -q Awake && echo -e '1\\c' && (dumpsys audio | grep paused | grep -qv 'Buffer Queue' && echo -e '1\\c' || (dumpsys audio | grep started | grep -qv 'Buffer Queue' && echo '2\\c' || echo '0\\c')) && dumpsys power | grep Locks | grep 'size=' && CURRENT_APP=$(dumpsys window windows | grep mCurrentFocus) && CURRENT_APP=${CURRENT_APP#*{* * } && CURRENT_APP=${CURRENT_APP%%/*} && echo $CURRENT_APP && (dumpsys media_session | grep -A 100 'Sessions Stack' | grep -A 100 $CURRENT_APP | grep -m 1 'state=PlaybackState {' || echo) && dumpsys audio | grep '\\- STREAM_MUSIC:' -A 12\x00"
2020-01-29 03:19:03 ERROR (MainThread) [homeassistant.helpers.entity] Update for media_player.sony_tv fails
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 281, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 461, in async_device_update
    await self.hass.async_add_executor_job(self.update)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 271, in _adb_exception_catcher
    return func(self, *args, **kwargs)
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 471, in update
    ) = self.aftv.update()
  File "/usr/local/lib/python3.7/site-packages/androidtv/androidtv.py", line 79, in update
    screen_on, awake, audio_state, wake_lock_size, current_app, media_session_state, device, is_volume_muted, volume = self.get_properties(lazy=True)
  File "/usr/local/lib/python3.7/site-packages/androidtv/androidtv.py", line 225, in get_properties
    output = self._adb.shell(constants.CMD_ANDROIDTV_PROPERTIES_LAZY)
  File "/usr/local/lib/python3.7/site-packages/androidtv/adb_manager.py", line 165, in shell
    return self._adb.shell(cmd)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 212, in shell
    return b''.join(self._streaming_command(b'shell', command.encode('utf8'), timeout_s, total_timeout_s)).decode('utf8')
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 506, in _streaming_command
    local_id, remote_id = self._open(b'%s:%s' % (service, command), timeout_s, total_timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 269, in _open
    _, remote_id, their_local_id, _ = self._read([constants.OKAY], timeout_s, total_timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 319, in _read
    msg = self._handle.bulk_read(constants.MESSAGE_SIZE, timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/tcp_handle.py", line 107, in bulk_read
    return self._connection.recv(numbytes)
ConnectionResetError: [Errno 104] Connection reset by peer
2020-01-29 03:19:13 DEBUG (SyncWorker_8) [androidtv.adb_manager] Sending command to 192.168.0.11:5555 via adb-shell: (dumpsys power | grep 'Display Power' | grep -q 'state=ON' || dumpsys power | grep -q 'mScreenOn=true') && echo -e '1\c' && dumpsys power | grep mWakefulness | grep -q Awake && echo -e '1\c' && (dumpsys audio | grep paused | grep -qv 'Buffer Queue' && echo -e '1\c' || (dumpsys audio | grep started | grep -qv 'Buffer Queue' && echo '2\c' || echo '0\c')) && dumpsys power | grep Locks | grep 'size=' && CURRENT_APP=$(dumpsys window windows | grep mCurrentFocus) && CURRENT_APP=${CURRENT_APP#*{* * } && CURRENT_APP=${CURRENT_APP%%/*} && echo $CURRENT_APP && (dumpsys media_session | grep -A 100 'Sessions Stack' | grep -A 100 $CURRENT_APP | grep -m 1 'state=PlaybackState {' || echo) && dumpsys audio | grep '\- STREAM_MUSIC:' -A 12
2020-01-29 03:19:13 DEBUG (SyncWorker_8) [adb_shell.adb_device] bulk_write: b'OPEN\x01\x00\x00\x00\x00\x00\x00\x00\xe2\x02\x00\x00\x19\xeb\x00\x00\xb0\xaf\xba\xb1'
2020-01-29 03:19:13 ERROR (SyncWorker_8) [homeassistant.components.androidtv.media_player] Failed to execute an ADB command. ADB connection re-establishing attempt in the next update. Error: [Errno 32] Broken pipe
2020-01-29 03:19:13 ERROR (MainThread) [homeassistant.helpers.entity] Update for media_player.sony_tv fails
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 271, in _adb_exception_catcher
    return func(self, *args, **kwargs)
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 471, in update
    ) = self.aftv.update()
  File "/usr/local/lib/python3.7/site-packages/androidtv/androidtv.py", line 79, in update
    screen_on, awake, audio_state, wake_lock_size, current_app, media_session_state, device, is_volume_muted, volume = self.get_properties(lazy=True)
  File "/usr/local/lib/python3.7/site-packages/androidtv/androidtv.py", line 225, in get_properties
    output = self._adb.shell(constants.CMD_ANDROIDTV_PROPERTIES_LAZY)
  File "/usr/local/lib/python3.7/site-packages/androidtv/adb_manager.py", line 165, in shell
    return self._adb.shell(cmd)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 212, in shell
    return b''.join(self._streaming_command(b'shell', command.encode('utf8'), timeout_s, total_timeout_s)).decode('utf8')
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 506, in _streaming_command
    local_id, remote_id = self._open(b'%s:%s' % (service, command), timeout_s, total_timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 268, in _open
    self._send(msg, timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 472, in _send
    self._handle.bulk_write(msg.pack(), timeout_s)
  File "/usr/local/lib/python3.7/site-packages/adb_shell/tcp_handle.py", line 136, in bulk_write
    return self._connection.send(data)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 281, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 461, in async_device_update
    await self.hass.async_add_executor_job(self.update)
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 278, in _adb_exception_catcher
    self.aftv.adb_close()
  File "/usr/local/lib/python3.7/site-packages/androidtv/basetv.py", line 150, in adb_close
    self._adb.close()
  File "/usr/local/lib/python3.7/site-packages/androidtv/adb_manager.py", line 66, in close
    self._adb.close()
  File "/usr/local/lib/python3.7/site-packages/adb_shell/adb_device.py", line 95, in close
    self._handle.close()
  File "/usr/local/lib/python3.7/site-packages/adb_shell/tcp_handle.py", line 63, in close
    self._connection.shutdown(socket.SHUT_RDWR)
OSError: [Errno 107] Socket not connected
2020-01-29 03:19:24 DEBUG (SyncWorker_12) [androidtv.adb_manager] ADB command not sent to 192.168.0.11:5555 because adb-shell connection is not established: (dumpsys power | grep 'Display Power' | grep -q 'state=ON' || dumpsys power | grep -q 'mScreenOn=true') && echo -e '1\c' && dumpsys power | grep mWakefulness | grep -q Awake && echo -e '1\c' && (dumpsys audio | grep paused | grep -qv 'Buffer Queue' && echo -e '1\c' || (dumpsys audio | grep started | grep -qv 'Buffer Queue' && echo '2\c' || echo '0\c')) && dumpsys power | grep Locks | grep 'size=' && CURRENT_APP=$(dumpsys window windows | grep mCurrentFocus) && CURRENT_APP=${CURRENT_APP#*{* * } && CURRENT_APP=${CURRENT_APP%%/*} && echo $CURRENT_APP && (dumpsys media_session | grep -A 100 'Sessions Stack' | grep -A 100 $CURRENT_APP | grep -m 1 'state=PlaybackState {' || echo) && dumpsys audio | grep '\- STREAM_MUSIC:' -A 12

I’ve noticed one main difference between the two approaches.
While the ADB Server approach seems trying to recover itself for a few seconds in between,


the Python ADB approach remains in broken / unavailable state.
It won’t connect anymore to my TV, but instead throws the above seen error message in my HA logs.

I’m running HASSio as Docker installation on RPi 4. Currently installed version is 103.3
RPi and TV are both connected to the network by wire.

Any help would be highly appreciated :slight_smile:

Thanks for the logs!

There are two issues with the HA integration. One is fixed in 0.104, the other will be fixed in 0.105. If you don’t want to wait, you can use this custom component in the meantime: https://github.com/JeffLIrion/ha-androidtv

But the real problem is that your TV goes into deep sleep mode, breaking the ADB connection. You could try installing a Wakelock utility. See #6 here: https://www.home-assistant.io/integrations/androidtv/#adb-troubleshooting

If I may ask you as a specialist. If the TV goes to deep sleep, how is it possible, to wake it up via Bluetooth (that’s what I do with my remote)? Can one (me) use that BT to avoid the unavailable state or start it with a BT command?

And on a second, not unrelated question: I’m using a new device in Germany, from Telekom. It’s called MagentaTV stick. It’s basically a normal stick like FireTV, with a launcher for the MagentaTV services and the possibility, to install apps via playstore. This is a unit, that will get broad attention, when it leaves the beta stadium. That brings me to the point: right now there is a very good communication between beta users and the development team from Telekom. How do I explain them, things like the wakelock_size or audio_state and what we, as users, want them to show to make the stick work good to very good with HA? Are there any related documents I could dive into?

Thanks for your help and for the component, it is imho one of the key components in HA. :slight_smile: Controlling a TV is essential. :slight_smile:

Thanks for the kind words! But I’m no expert. Regarding your first question, all I can say is that the TV must always be listening for Bluetooth signals, but at some point it decides that it doesn’t need to keep running ADB.

Regarding your second point, what the Android TV integration does is parse properties from the output of ADB commands. I think it’s all standard Android stuff. Media session state is probably the best of these properties for determining state. The commands used to get these properties can be found here.

If this MagentaTV Stick is an Android device with ADB, then the Android TV integration will probably work for it.

hi, recently i am experiencing an error that i can’t fix while loading androidtv component:

Error while setting up platform androidtv
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 158, in _async_setup_platform
    await asyncio.wait_for(asyncio.shield(task), SLOW_SETUP_MAX_WAIT)
  File "/usr/local/lib/python3.7/asyncio/tasks.py", line 442, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 207, in setup_platform
    state_detection_rules=config[CONF_STATE_DETECTION_RULES],
  File "/usr/local/lib/python3.7/site-packages/androidtv/__init__.py", line 52, in setup
    aftv = BaseTV(host, port, adbkey, adb_server_ip, adb_server_port, state_detection_rules, auth_timeout_s)
  File "/usr/local/lib/python3.7/site-packages/androidtv/basetv.py", line 100, in __init__
    self.device_properties = self.get_device_properties()
  File "/usr/local/lib/python3.7/site-packages/androidtv/basetv.py", line 206, in get_device_properties
    constants.CMD_MAC_ETH0)
  File "/usr/local/lib/python3.7/site-packages/androidtv/adb_manager.py", line 435, in shell
    return self._adb_device.shell(cmd)
  File "/usr/local/lib/python3.7/site-packages/ppadb/command/transport/__init__.py", line 20, in shell
    conn = self.create_connection(timeout=timeout)
  File "/usr/local/lib/python3.7/site-packages/ppadb/device.py", line 45, in create_connection
    self.transport(conn)
  File "/usr/local/lib/python3.7/site-packages/ppadb/command/transport/__init__.py", line 15, in transport
    connection.send(cmd)
  File "/usr/local/lib/python3.7/site-packages/ppadb/connection.py", line 77, in send
    return self._check_status()
  File "/usr/local/lib/python3.7/site-packages/ppadb/connection.py", line 83, in _check_status
    raise RuntimeError("ERROR: {} {}".format(repr(recv), error))
RuntimeError: ERROR: 'FAIL' 000edevice offline

no changes has been done from my side apart from updating home assistant from 0.103 to 0.104 (latest), anyone knows how to fix it and what it really means?

i have tried using custom component as provided couple of posts before - but that didn’t help.

thank you in advance!

Thanks for the help. And no when i pause (or anything) is also takes a a few seconds to pause the tv. Idk what is causing the closest comparison i can do ( as i don’t know the adb shell command to pause tv) is launching netflix selecting from media player source list (3 to 8 seconds to start) and launching it from androidtv.adb_command or adb shell which is instant

ill try to change the scan_interval, but i think this will only solve the states delay, the delay will still be present when launching anything. I don’t see more people whit this problem so something has to be wrong on my setup? I even facory rest my tv and do a fresh install for home assitant only for this >_<