Как настроить deep links в Android и открывать нужный экран
Deep links в Android — это ссылки, которые открывают приложение сразу на конкретном экране (товар, профиль, сброс пароля). Делается это через intent-filter в манифесте и разбор intent.data (URI) в коде; для https-ссылок лучше использовать Android App Links с подтверждением домена.
Если у вас есть домен — делайте App Links. Custom scheme (myapp://...) оставьте как резервный вариант для тестов или внутренних интеграций.
Оглавление
Какие ссылки использовать: scheme, web, App Links
| Тип | Пример | Когда выбирать |
|---|---|---|
| Custom scheme | myapp://p/123 | Нет домена, быстрый старт, внутренние сценарии |
| Web deep link | https://example.com/p/123 | MVP, когда App Links ещё не готовы (возможен выбор приложения/браузера) |
| **Android App Links** | https://example.com/p/123 | Продакшен: открытие сразу в приложении после верификации домена |
На практике чаще всего поддерживают App Links + fallback (если приложения нет — открывается сайт), а scheme добавляют точечно.
Настройка в AndroidManifest: intent-filter
Минимальная настройка для https:
<activity
android:name=".MainActivity"
android:exported="true">
<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"
android:host="example.com"
android:pathPrefix="/p/" />
</intent-filter>
</activity>
VIEW+BROWSABLE— чтобы ссылка открывалась из браузера/мессенджеров.pathPrefix="/p/"— удобно для однотипных страниц (/p/123,/p/456).- Если нужно матчингов больше (профиль, сброс пароля), добавляйте отдельные
<data>или отдельныеintent-filterпод разные пути.
Частая причина “из браузера не открывается”: забыли android.intent.category.BROWSABLE. Ещё одна — не указан android:exported="true" у Activity с intent-filter.
App Links: assetlinks.json и верификация домена
Чтобы https://example.com/... открывался без выбора приложения, домен нужно “привязать” к приложению через файл:
/.well-known/assetlinks.json
Пример структуры:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["AA:BB:CC:...:11"]
}
}
]
Важно, чтобы совпали:
package_name↔applicationId- SHA‑256 отпечаток ↔ реальный ключ подписи релиза (включая случаи, когда подпись выполняется не локально)
Если App Links “не верифицируются” на релизной сборке, чаще всего виноват неправильный SHA‑256 (взяли debug вместо release или перепутали ключ подписи).
Открытие нужного экрана: разбор URI в Kotlin
Ссылка приходит в intent.data. Обрабатывайте и холодный старт, и повторный интент:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleDeepLink(intent)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleDeepLink(intent)
}
private fun handleDeepLink(intent: Intent) {
val uri = intent.data ?: return
val segments = uri.pathSegments
when (segments.getOrNull(0)) {
"p" -> segments.getOrNull(1)?.let { openProduct(it) } ?: openHome()
"u" -> openProfile(segments.getOrNull(1))
"reset-password" -> openReset(uri.getQueryParameter("token"))
else -> openHome()
}
}
}
Если экран требует авторизацию — делайте “отложенный” переход: сохраните deep link, покажите логин, после успеха выполните навигацию.
Тестирование
Быстрый способ — ADB:
adb shell am start -a android.intent.action.VIEW -d "https://example.com/p/123"
Чтобы исключить выбор приложений, укажите пакет:
adb shell am start -a android.intent.action.VIEW -d "https://example.com/p/123" com.example.app
Дополнительно проверяйте реальные клики из заметок/почты/мессенджеров: они могут добавлять редиректы и параметры, из-за чего меняется итоговый URL.
Частые ошибки
intent-filterнастроен, но нетBROWSABLE→ не открывается из внешних приложений.- Не обработан
onNewIntent()→ при уже запущенном приложении открывается “не тот” экран. - Слишком узкий
pathPrefix/ошибка вhost/scheme→ матчинг не срабатывает. - App Links не подтверждены: неверный SHA‑256, неправильный путь
/.well-known/assetlinks.json, несовпадениеpackage_name. - Небезопасная логика: доверие параметрам из URL (токены/ID) без серверной проверки.
FAQ
Можно ли поддерживать и App Links, и custom scheme одновременно?
Да. Обычно App Links — основной канал, scheme — резерв для тестов и частных интеграций.
Почему иногда появляется окно выбора приложения?
Чаще всего App Links не прошли верификацию, либо пользователь ранее выбрал открытие в браузере по умолчанию.
Нужно ли добавлять http, если есть https?
Только если у вас реально остались старые http-ссылки. В остальных случаях лучше вести всё на https и не расширять поверхность ошибок.