Native support for Android TV / Android devices

That seems to happen from time to time, maybe once a week to once a month if I had to guess. Aside from toggling ADB off and then back on, restarting the device should fix it.

If someone posts a debug log, I’ll take a look. But that might just be the way it is.

I’m having a few problems with AndroidTV (in my case a TV-Stick from german provider Telekom) for a few months now, but since a few days ago, I have one more error message, that annoys me very much, as it comes up a lot (meaning yesterday within 15 hours around 6000 messages in the log…).

So here we go, I got a few error messages:

  • This is the “new one”
    Traceback (most recent call last):
    File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 272, in async_update_ha_state
      await self.async_device_update()
    File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 463, in async_device_update
      await self.async_update()  # type: ignore
    File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 357, in _adb_exception_catcher
      return await func(self, *args, **kwargs)
    File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 658, in async_update
      ) = await self.aftv.update(self._get_sources)
    File "/usr/local/lib/python3.8/site-packages/androidtv/androidtv/androidtv_async.py", line 73, in update
      screen_on, awake, audio_state, wake_lock_size, current_app, media_session_state, audio_output_device, is_volume_muted, volume, running_apps = await self.get_properties(get_running_apps=get_running_apps, lazy=lazy)
    File "/usr/local/lib/python3.8/site-packages/androidtv/androidtv/androidtv_async.py", line 125, in get_properties
      output = await self._adb.shell(constants.CMD_ANDROIDTV_PROPERTIES_LAZY_RUNNING_APPS)
    File "/usr/local/lib/python3.8/site-packages/androidtv/adb_manager/adb_manager_async.py", line 498, in shell
      return await self._adb_device.shell(cmd)
    File "/usr/local/lib/python3.8/site-packages/androidtv/adb_manager/adb_manager_async.py", line 43, in shell
      return await asyncio.get_running_loop().run_in_executor(None, self._device.shell, cmd)
    AttributeError: 'NoneType' object has no attribute 'shell'
    
  • These are “old ones”
    Traceback (most recent call last):
    File "/usr/local/lib/python3.8/site-packages/aiohttp/web_protocol.py", line 418, in start
      resp = await task
    File "/usr/local/lib/python3.8/site-packages/aiohttp/web_app.py", line 458, in _handle
      resp = await handler(request)
    File "/usr/local/lib/python3.8/site-packages/aiohttp/web_middlewares.py", line 119, in impl
      return await handler(request)
    File "/usr/src/homeassistant/homeassistant/components/http/real_ip.py", line 39, in real_ip_middleware
      return await handler(request)
    File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 73, in ban_middleware
      return await handler(request)
    File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 127, in auth_middleware
      return await handler(request)
    File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 129, in handle
      result = await result
    File "/usr/src/homeassistant/homeassistant/components/media_player/__init__.py", line 882, in get
      data, content_type = await player.async_get_media_image()
    File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 357, in _adb_exception_catcher
      return await func(self, *args, **kwargs)
    File "/usr/src/homeassistant/homeassistant/components/androidtv/media_player.py", line 500, in async_get_media_image
      media_data = await self.aftv.adb_screencap()
    File "/usr/local/lib/python3.8/site-packages/androidtv/basetv/basetv_async.py", line 149, in adb_screencap
      return await self._adb.screencap()
    File "/usr/local/lib/python3.8/site-packages/androidtv/adb_manager/adb_manager_async.py", line 476, in screencap
      return await self._adb_device.screencap()
    File "/usr/local/lib/python3.8/site-packages/androidtv/adb_manager/adb_manager_async.py", line 39, in screencap
      return await asyncio.get_running_loop().run_in_executor(None, self._device.screencap)
    File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
      result = self.fn(*self.args, **self.kwargs)
    File "/usr/local/lib/python3.8/site-packages/ppadb/command/transport/__init__.py", line 48, in screencap
      if result[5] == 0x0d:
    IndexError: bytearray index out of range
    
    and
    Updating androidtv media_player took longer than the scheduled update interval 0:00:10
    
    and
    Failed to execute an ADB command. ADB connection re-establishing attempt in the next update. Error: ERROR: 'FAIL' 0006closed
    

All things seem to work as expected, beside the possibility to turn on/off the Magenta-TV-Stick. I can circumvent this by turning on/off the TV itself (another AndroidTV-SonyBravia) and CEC does the rest. Correction, since the “new” error message I can’t control the MagentaTV-Stick in any way, it simply doesn’t work (what I’d have expected after the shell error).

And here we go with the config:

- platform: braviatv_psk
  host: !secret host_sony-bravia
  name: Sony Bravia TV
  psk: sony
  mac: !secret mac_sony-bravia
  amp: True
  android: True
- platform: androidtv
  name: MagentaTV Stick
  host: !secret host_magentatv-stick
  adb_server_ip: 127.0.0.1
  adb_server_port: 5037
  apps:
    [...skipped...]
  exclude_unnamed_apps: true
  state_detection_rules:
    [...skipped...]

Is there anything I can do to debug this further, or does someone have other ideas how to solve this, I would appreciate any input.

Thanks! :slight_smile:

I fixed that here, it will be in 0.113.1: Bump androidtv to 0.0.46 by JeffLIrion ¡ Pull Request #38090 ¡ home-assistant/core ¡ GitHub

You should file an issue here: Issues ¡ Swind/pure-python-adb ¡ GitHub

Updating androidtv media_player took longer than the scheduled update interval 0:00:10

I suspect that is due to the fact that you have the screencap option enabled.

Failed to execute an ADB command. ADB connection re-establishing attempt in the next update. Error: ERROR: ‘FAIL’ 0006closed

I’m not sure about that one, but it could be a bug with pure-python-adb

Just a guess, but the last two issues could be related: the device could be unresponsive, causing the update command to hang forever, causing the next update command to fail. I use the Python ADB implementation, so maybe this doesn’t apply, but every few weeks or so my Fire TV stick stops responding to ADB commands sent by HA and I have to restart the Fire TV, after which HA successfully reconnects.

1 Like

You are a genius! :slight_smile: Thanks a lot, my total respect, you know your code base! :+1: :slight_smile:

I disabled the screencapture (must have overlooked that setting), and all errors are gone. It’s now running for a good 45 minutes without any error message, even the “new one” seems to be gone. All is responsible and working as expected. I can switch, play, pause, turn on or off, all good… :+1:

Thanks a lot and have a nice weekend! :slight_smile:

EDIT: After around one and a half hours the error that you already have fixed is back, but that’s not a problem, I’ll wait for 0.113.1 and report back. :slight_smile:

Having used Apple TV’s in the past and recently switched to Android TV I do miss one thing. On the ATV (and the HA component) it was able to determine whether the device was playing or paused. I find that with the SHIELD TV and the Xiaomi MiBox S they both show a playing state when browsing apps like Disney+ or Netflix, the state would simply change to playing after a few seconds even if you were just browsing these apps. This makes automating anything based on play/paused states quite difficult which was not the case for my ATV’s. Also updating the state takes over 5 seconds which makes the automations feel kinda clunky. I wonder there is a way to change the polling speed or something so that at least the states update in realtime.

For my movies I use the Plex integration to automate on (which surprisingly does update the state in real-time. Even more surprisingly, my ATV had correct states and real-time play/pause state changes, but the Plex integration had that same 5-8 seconds delay which my Android TV has on all other apps XD).

I wonder if this is a limitation of the ADB implementation and if there is a way to work around it (which I am thinking it isn’t possible). Too bad if it can’t get better than this, I actually like the Android TV experience in conjunction with other Google services as opposed to the Apple TV. Though currently I think the ATV HA component works slightly better in this regard.

I am fairly new to the Android ecosystem and thus also fairly new to this component. If there is anything I should know or something I have missed please correct me XD.

Are you using the state_detection_rules and apps part of the configuration for androidTV (in the component)? Check these out here, https://www.home-assistant.io/integrations/androidtv/#custom-state-detection

Depending on the apps you use, you should/could try intents as well. This page gives a little glimps: https://gist.github.com/mcfrojd/9e6875e1db5c089b1e3ddeb7dba0f304

This should give you some reading time and a better understanding, what is going on with androidTV. :slight_smile: In my understanding, there are two ways to communicate with your TV (or whatever androidTV device you are running). One is to send a command through the adb shell directly via a service or you use the custom state detection rules. I would start with the later, and if these don’t work or something isn’t supported, I’d take a look if there is a shell command, you can use. :slight_smile: At least that is my understanding how it works, but I’m in no way an expert. :wink:

1 Like

@JeffLIrion I have an existing shield 2017 that has been working great with the python implementation of the androidtv integration. I recently bought a second 2019 shield and enabled network debugging then added it to my configuration. This time I let HA generate the adb key but the old one is still using the one I generated a while back. I get the popup asking to allow the adb connection and tick the box saying to always allow. For whatever reason, every time I restart home assistant, the box “allow connection” box pops up on the shield even if I have that “always allow” box ticked.

Any thoughts?

Which device always prompts you, the old Shield using the existing key or the new Shield using the key that HA generated?

The 2019 Shield (new one) that has an auto generated key.

I think this pull request will fix it: https://github.com/home-assistant/core/pull/38344

In particular, I think this pair of commits is the fix:

If you know how to use custom components, you can grab these files and test it out: https://github.com/JeffLIrion/home-assistant/tree/androidtv-bump2/homeassistant/components/androidtv

So I copied those files into custom_components named the dir androidtv_test, and changed my config section for the 2019 shield to reference the androidtv_test platform (left the old one on androidtv). Restarted HA a few times and the popup keeps coming up.

I may have done the custom component thing wrong, would it pull the new versions of adb_shell and python-androidtv?

I also tried building a new docker image with just your commit cherry-picked but it appears I need to wait for the new versions of your libraries to appear in the HA base image?

Just call the custom component androidtv. I think there are multiple places where you would need to rename it. Also, the requirements are different for the native vs. custom component, so I think that could create issues. Speaking of which…

I’m not sure how HA handles custom component requirements that conflict with native component requirements. It’s possible that it’s not updating those packages. Unfortunately, I think it’s difficult to tell.

It might be necessary to delete the androidtv_adbkey and androidtv_adbkey.pub files in the .storage folder, restart HA, and re-approve the connection. WARNING: in general, deleting files in the .storage folder is a bad idea! (But deleting these two files won’t mess up anything.)

That pull request should be in release 0.113.3, if/when that gets released. So you’ll be able to try it then without needing to fuss with a custom component.

1 Like

0.113.3 has been released. Let me know if you still experience the issue. I expect that when you restart, you’ll need to approve it again. But after that, you shouldn’t need to.

If you do still need to approve it every time, delete the key files that I mentioned previously and see if it’s fixed after that.

Just updated. Popup still came up after restarts so I deleted the key pair from .storage. Unfortunately, the popup is still coming up. One thing I did notice is the RSA key fingerprint is the same in the popup even after deleting the key pairs from .storage. I did double check the new key pair is different. Shouldn’t the “RSA key fingerprint” be different each time the key is generated?

I am having the same issues. Asked each time the fireTV starts.

Did you first connect to this device from HA version 0.113 (not an earlier release)?

What is your Android device and which version of Android are you running? (@kylehendricks can you also let me know what version of Android you’re running)

It could be due to this: https://github.com/google/python-adb/pull/152#discussion_r306312516

But I’m just guessing at this point.

Two things you can try:

  1. If your HA installation permits, make this edit in adb_shell/adb_device_async.py: https://github.com/JeffLIrion/adb_shell/pull/83/files#diff-f27635d2c39efc12ac6521e3fb51af85
  2. If you have a different key (as @kylehendricks does), use that key in the config for your Android TV device.

You can try this custom component that incorporates the change I mentioned above: https://github.com/JeffLIrion/ha-androidtv

FYI, it’s entirely possible that made a a typo or other mistake and it won’t work.

Both shields are Android 9. I’ll try making that change or using that custom component.

So I think this has something to do with my “2017 Shield” androidtv entry that has the adbkey field set. I just got the RSA fingerprint of my existing key and it has the same fingerprint that keeps showing up on my new Shield. Here is my config for reference (Basement Shield TV is the shield with the issue):

media_player:
  - platform: androidtv
    name: Shield TV
    device_class: androidtv
    host: shieldtv.home
    adbkey: "/config/adbkey"
    apps:
      "com.plexapp.android": "Plex"
      "com.netflix.ninja": "Netflix"
      "com.google.android.youtube.tv": "YouTube"
      "com.amazon.amazonvideo.livingroom": "Prime Video"
      "com.alexvas.dvr.pro": "tinyCam"
      "org.jellyfin.androidtv": "Jellyfin"
      "com.liskovsoft.videomanager": "Smart Youtube"
      "com.google.android.youtube.tvunplugged": "Youtube TV"
  - platform: androidtv
    name: Basement Shield TV
    device_class: androidtv
    host: 192.168.1.34
    apps:
      "com.plexapp.android": "Plex"
      "com.netflix.ninja": "Netflix"
      "com.google.android.youtube.tv": "YouTube"
      "com.amazon.amazonvideo.livingroom": "Prime Video"
      "com.alexvas.dvr.pro": "tinyCam"
      "org.jellyfin.androidtv": "Jellyfin"
      "com.liskovsoft.videomanager": "Smart Youtube"
      "com.google.android.youtube.tvunplugged": "Youtube TV"

I think I’m going to try just using the auto-generated key for both Shields.

OK nevermind. I think I’m confused about this RSA fingerprint thing. When I run:

awk '{print $1}' < .storage/androidtv_adbkey | openssl base64 -A -d -a | openssl md5 -c

I always get back that same fingerprint, even when I regenerate the key pair and verify they’re different.