android icon indicating copy to clipboard operation
android copied to clipboard

Rework MyActivity to support Invite and improve UX

Open TimoPtr opened this issue 8 months ago • 4 comments

Summary

This PR enhances deep link handling in MyActivity by:

  1. Introducing support for https://my.home-assistant.io/invite#url=... universal links, directing users to the server onboarding flow with the specified URL.
  2. Improving the user experience for https://my.home-assistant.io/redirect/... universal links by navigating directly to the relevant content within the app, instead of opening a WebView with a button.

Motivation & Background:

  • Invite Links: To streamline server setup by allowing users to directly onboard via a shared link containing the server URL. The server URL is passed in the URL fragment for security (to prevent it from being sent to my.home-assistant.io) so we have to manipulate the fragment and transform it into a query.
  • Redirect Links UX: Previously, redirect links opened a WebView as a security measure. After discussion with the frontend team, it was determined that since the frontend already validates these links and user interaction is expected, a more seamless in-app navigation is preferable. This change also ensures these links work even if my.home-assistant.io is temporarily unavailable or the user doesn't have internet (on their local network).
  • Task Affinity Bug: Resolved an issue where MyActivity, due to its standard launchMode, would incorrectly appear as part of the calling app's task (e.g., Home Assistant appearing within Google Keep's task in the recents screen). MyActivity now correctly launches in its own task.
  • URL Parameter Encoding: Dedicated effort was made to ensure URLs with percent-encoded parameters are handled correctly throughout the linking process, preventing the generation of invalid URLs from valid incoming links.

Impact:

  • Users can now be invited to a Home Assistant instance via a simple link, automatically pre-filling the server URL for onboarding.
  • Navigating via redirect links from my.home-assistant.io will feel more integrated, taking users directly to the content within the app.
  • Fixes a bug where the app could be incorrectly grouped with the launching app in the Android task switcher.

Checklist

  • [x] New or updated tests have been added to cover the changes following the testing guidelines.
  • [x] The code follows the project's code style and best_practices.
  • [x] The changes have been thoroughly tested, and edge cases have been considered.
  • [x] Changes are backward compatible whenever feasible. Any breaking changes are documented in the changelog for users and/or in the code for developers depending on the relevance.

Screenshots

Before: Home Assistant shown as part of the calling app's task (e.g., Google Keep) and opening a WebView. https://github.com/user-attachments/assets/0982b09d-032b-4e89-bed7-015c4086ee51

Now: Home Assistant correctly opens in its own task and supports invite without opening an intermediate WebView. https://github.com/user-attachments/assets/6e42f506-0e58-4a1c-ac41-dba62ed5bd65

Any other notes

It was added on iOS in https://github.com/home-assistant/iOS/pull/3591 using deep link but I prefered the universal link way since it feels more native. FailFast has been extended to add a simpler method to handle more cases.

This functionality mirrors a similar feature added on iOS (see https://github.com/home-assistant/iOS/pull/3591), though this PR implements it using Android Universal Links for a more native feel compared to custom URL schemes. The FailFast utility has been extended with a simpler method fail to cover more use cases.

TimoPtr avatar Jun 17 '25 15:06 TimoPtr

I made a mistake in the implementation it should support deep link rather than universal link, that is different from the iOS impl. It means that it doesn't open the my website.

Also another mistake is that I should treat the fragment as an URI not using simple string manipulation.

I decided to make it better and introduce another class that will be agnostic from the activity so that I can write Unit Test about it. I don't think it needs to be a ViewModel but it could.

TimoPtr avatar Jun 19 '25 06:06 TimoPtr

Test Results

 43 files   43 suites   4m 27s ⏱️ 142 tests 142 ✅ 0 💤 0 ❌ 152 runs  152 ✅ 0 💤 0 ❌

Results for commit 9179ef9c.

:recycle: This comment has been updated with latest results.

github-actions[bot] avatar Jun 19 '25 14:06 github-actions[bot]

is there an easy way to test this? For some reason the debug build does not register teh deep links nor allows me to select them, so the browser keeps opening telling me to install the app.

image

image

Testing this by saving links in gmail and clicking on them to trigger the process

dshokouhi avatar Jun 20 '25 15:06 dshokouhi

It's because your production app already captures the links. We should have universal links for debug but that's a bigger task.

TimoPtr avatar Jun 20 '25 16:06 TimoPtr

This seems incomplete to me for the flow where a user is completely new and doesn't have the app. My page opens in browser (because there is no app) > user taps Google Play badge to install the app > user returns to browser > tapping 'Accept invite' doesn't do anything because you haven't added support for homeassistant://invite#url=http%3A%2F%2Fhomeassistant.local%3A8123. So this either needs a change on the my page, or in the app. I'm guessing changing the app is easier and backwards compatible ;)

jpelgrom avatar Jun 23 '25 06:06 jpelgrom