Deeplinks и Flutter

от автора

В мире Android и iOS разработки есть механизм диплинков. Диплинк представляет из себя обычную ссылку, при переходе на которую у вас открывается приложение (если таковое имеется) и зачастую показывается определенный контент. В диплинки мы можем добавлять различные параметры, поскольку это просто ссылка (например, id видео, код подтверждения и т.д.). В этой статье мы разберемся, как заимплементить диплинки для нашего Флатер приложения для двух платформ: Android и iOS.

Где применяются диплинки?

  • Старт приложения на определенном контенте — ссылка на ютуб видео стартует приложение и открывает определенное видео. Стоит упомянуть, что при уже запущенном приложении, новое не будет стартовать, а видео откроется в текущей сессии.

  • Восстановление пароля — стартует приложение с окном на уровне «Введите новый пароль»

  • Любой другой юзкейс, когда надо стартовать приложение (или во время текущей сессии) и добавить какое-то поведение на основе параметров в диплинке

  • Навигация по приложению (в качестве основного способа навигации такой вариант не совсем рациональный)

Во флатере нет единого решения для добавления диплинков, поскольку это платформозависимый механизм и необходимо это реализовывать отдельно для двух платформ. Далее последовательно рассмотрим перехват нашим приложением диплинков на Android и iOS системах и их обработку в флатер приложении.

Android

В Android есть 2 типа ссылок, открывающих приложение — Deep Links и App Links.
Внешние отличия: Deep Links могут иметь кастомную схему либо схему http, а App Links имеют исключительно схему https:

  • http://habr.com и awesome-scheme://habr.com — Deep Links

  • https://habr.com — App Link

Также важно уточнить, что при открытии App Link нас сразу перекинет в приложение, а при открытии же Deep Link появится похожее окошко с выбором приложения, в котором эту ссылку и открыть:

Внутренние отличия:

  • Реализация App Links требует наличие google-developer аккаунта и сайта со схемой https вместе с размещением на нем файла-конфигурации assetlinks.json

  • При отсутствии приложения, обрабатывающего такую ссылку, в случае Deep Link откроется ссылка в браузере по этому пути, в случае App Link — откроется ссылка на это приложение в Play Market’е.

Android Deep Links

В файле android/app/src/main/AndroidManifest.xml внутри <activity>…</activity> необходимо добавить следующий intent-filter:

<intent-filter>     <action android:name="android.intent.action.VIEW" />     <category android:name="android.intent.category.DEFAULT" />     <category android:name="android.intent.category.BROWSABLE" />     <data         android:scheme="my-scheme"         android:host="my-host.com"         android:pathPrefix="/my-prefix" /> </intent-filter>

android:scheme — указывается кастомная схема либо http
android:host — указывается имя хоста
android:pathPrefix — опциональный параметр
Такой интент фильтр будет открывать наше приложение для ссылок вида my-scheme://my-host/my-prefix и my-scheme://my-host/my-prefix*

Чтобы протестировать, что все работает верно, можно ввести в консоль следующую команду:

adb shell am start -a android.intent.action.VIEW -d "my-scheme://my-host.com/my-prefix" your-app-package-name

Android App Links

Для начала необходимо подписать приложение и зарегистрировать его в Google Play Console (необходимо иметь платный google-developer аккаунт). Откуда в project-name->setup->app-integrity можно найти необходмый sha-ключ для конфиг-файла.
Сам конфиг файл выглядит следующим образом, только вместо com.example необходимо вставить свой package-name и вместо 14:6D* необходимо вставить свой sha-ключ:

[{   "relation": ["delegate_permission/common.handle_all_urls"],   "target": {     "namespace": "android_app",     "package_name": "com.example",     "sha256_cert_fingerprints":     ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]   } }]

Потом необходимо добавить файл-конфигурацию на наш сайт с https-схемой. Если сайта нет, можно создать свой посредством сервисов firebase-deploy, heroku или github-pages.
Создаем новую папку .well-known в корне нашего сайта и добавляем туда файл assetlinks.json, чтобы перейдя по ссылке https://my-host.com/.well-known/assetlinks.json можно было посмотреть содержимое этого файла.

В файле android/app/src/main/AndroidManifest.xml внутри <activity>…</activity> необходимо добавить следующий intent-filter:

<intent-filter android:autoVerify="true">     <action android:name="android.intent.action.VIEW" />     <category android:name="android.intent.category.DEFAULT" />     <category android:name="android.intent.category.BROWSABLE" />     <data android:scheme="https" />     <data android:host="my-host.com" /> </intent-filter>

android:scheme — указывается https
android:host — указывается имя существующего хоста
android:pathPrefix — опциональный параметр, как в Deep Links

Чтобы протестировать, что все работает верно, можно ввести в консоль следующую команду:

adb shell am start -a android.intent.action.VIEW -d "https://my-host.com" your-app-package-name

iOS

В iOS также есть 2 типа ссылок: Custom Scheme Links и Uni Links.
Они очень схожи с Deep Links и App Links в андроиде, но Custom Scheme Links могут иметь только кастомные схемы (как неудивительно), а Uni Links только схемы http и https.

  • http://habr.com и https://habr.com — Uni Links

  • awesome-scheme://habr.com — Custom Scheme Link

Внутренние отличия такие же, как для андроидовских линков: необходимо наличие apple-developer аккаунта и сайта с https схемой вместе с конфиг файлом apple-app-site-association для реализации Uni Links + при отсутствии приложения на девайсе ссылка откроется в браузере для Custom Scheme Links и откроется ссылка на приложение в AppStore для Uni Links.

iOS Custom Scheme Links

Для добавления ссылок с кастомными схемами нам достаточно зайти в Xcode и добавить список схем(не http и https), которое приложение может отлавливать:

Чтобы протестировать, что все работает верно, можно ввести в консоль следующую команду:

xcrun simctl openurl booted awesome-scheme://any-text

В данном случае нам хватает указать только схему, потому что исключительно на нее смотрит система при открытии приложения.

iOS Uni Links

Необходим apple-developer аккаунт.

Для начала необходимо добавить соответствующее разрешение в консоли разработчика — Identifiers-> Associated Domains — enabled.

Затем в Xcode добавить Capabilities->Associated Domains и новый домен, имеющий тип applinks и содержащий имя хоста. После добавления должны сгенерироваться файлы Runner.entitlements, RunnerDebug.entitlements, RunnerRelease.entitlements.
Остался последний шаг — добавить конфиг файл apple-app-site-association на наш сайт в папку .well-known, как и в случае с assetlinks.json.
Сам конфиг-файл имеет следующий вид:

{      "applinks": {          "apps": [],         "details": [             {                  "appID": "<TeamId>.<BundleId>",                 "paths": [ "*" ]             }         ]     } }

Чтобы протестировать, что все работает верно, можно ввести в консоль следующую команду:

xcrun simctl openurl booted https://my-host.com

Обработка диплинков в приложении

Для обработки будем использовать плагин uni_links.

Диплинки мы можем получить в двух состояниях: когда приложение активно (Incoming deep links) и когда приложение убито (Initial deep links).

uni_links предоставляет нам два основных компонента — linkStream, по которому мы будем получать диплинки в уже стартовавшем приложении, и метод getInitialLink, через который мы получаем диплинк, стартовавший приложение.

Весь код обработки таких случаев:

class App extends StatefulWidget {   const App({Key? key}) : super(key: key);    @override   State<App> createState() => _AppState(); }  class _AppState extends State<App> {   @override   void initState() {     super.initState();     handleIncomingDeepLinks();     handleInitialDeepLink();   }    void handleIncomingDeepLinks() {     linkStream.listen((link) {       print(link);     });   }    Future<void> handleInitialDeepLink() async {     final link = await getInitialLink();     if (link != null) {       print(link);     }   }    @override   Widget build(BuildContext context) {     return const Scaffold();   } } 

Заключение

С большим удовольствием отвечу на появившиеся вопросы. Это моя первая статья на Хабре, и любая обратная связь будет очень полезной!


ссылка на оригинал статьи https://habr.com/ru/post/692930/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *