В мире 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();
}
}
Заключение
С большим удовольствием отвечу на появившиеся вопросы. Это моя первая статья на Хабре, и любая обратная связь будет очень полезной!
Комментарии (6)
Necessitudo
13.10.2022 07:57+1А причем тут Флаттер?
paamayim
14.10.2022 15:12Большая часть статьи конечно относится к платформам. Но это актуально для флаттера так как это кроссплатформа и можно ориентироваться на статью как мануал, вместо того чтобы читать доки по каждой платформе отдельно. А в конце статьи чисто флаттерский пакет описан для поддержки диплинков. Так что да, статья актуальна именно для флаттера
paamayim
Отличная статья, все разжеванно. Побольше бы таких для флаттера. Как пожелание автору для дальнейших статей было бы интересны ваши подходы к навигации. С диплинками и вложенными роутерами для кроссплтаформы( тобишь веба и мобилок), если есть опыт конечно. Все решения какие пробовал я для своих проектов либо работают с костылями(если использовать готовые пакеты), либо отнимают много времени (если писать что то кастомное на navigator 2.0)
hurray
а пробовали AutoRoute?
paamayim
Пробовал routemaster и немного поковырялся с go_router. AutoRoute мне не понравился тем что там кодогенерация. Routemaster более менее удобный, но там есть моменты которые не разруливаются без костылей и как мне кажется автор подзабил на поддержку. Из перспективных мне кажется go_router, так как поддерживается командой флаттера но там не было полноценных решений для вложенных роутеров внутри табов и снаружи. Возможно это уже допилили.