Developing mobile applications on Android often requires organizing transitions between screens, external resources, or even other applications. One of the key scenarios is link processing: be it opening a web page in a browser, navigating to a specific screen within an application, or integrating with Deep Link for marketing campaigns. Without the correct implementation of these mechanisms, the user experience suffers, and the application loses functionality.
In this article we will analyze 5 ways to organize clicks on links in Android Studio - from the simplest Intent for opening a URL in the browser to complex schemes with PendingIntent and dynamic links Firebase. We will pay special attention to typical errors (for example, android.content.ActivityNotFoundException), code optimization for performance, and the nuances of working with Android 12+, where security policies have become more stringent. If you are just starting to develop software Android or want to systematize your knowledge, this guide will help you avoid pitfalls.
1. Basic transition: opening a link in a browser
The easiest way is to redirect the user to a web page through the device's standard browser. For this purpose it is used Intent.ACTION_VIEW with a URI parameter. This method is suitable for external links (for example, to a support site, terms of use or social networks).
Example code for a button in Activity:
val url = "https://example.com"val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
It is important to consider two points:
- ๐น Checking browser availability: before calling
startActivitycheck whether there is an application on the device that can handleIntent, otherwise the application will crash with an error. Useintent.resolveActivity(packageManager) != null. - ๐น HTTPS vs HTTP: starting from Android 9 (API 28), insecure connections (HTTP) are blocked by default. If your link does not support HTTPS, add
android:usesCleartextTraffic="true"toAndroidManifest.xml.
โ ๏ธ Attention: If your application targets Android 12 (API 31) and above, working withIntentto external resources may require a declaration<queries>in the manifest. For example, to open links in Chrome add:<queries><intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
2. Switching between screens within the application
If you need to open another screen (for example, a user profile or product details) by clicking on a link in the text or a button, use explicit Intent (Explicit Intent). This method is suitable for navigation within one application.
Example of transition from MainActivity to DetailActivity:
val intent = Intent(this, DetailActivity::class.java)intent.putExtra("KEY_ID", 123) // Data transfer
startActivity(intent)
To process links in the text (for example, in TextView) use android:text="User profile" and configure the handler:
textView.movementMethod = LinkMovementMethod.getInstance()textView.setOnClickListener {
val uri = Uri.parse("detail://user/123")
if (uri.scheme == "detail" && uri.host == "user") {
val intent = Intent(this, ProfileActivity::class.java)
intent.putExtra("USER_ID", uri.lastPathSegment?.toInt())
startActivity(intent)
}
}
- ๐ Data transfer: use
putExtrato pass primitives orParcelablefor complex objects. Avoid transferring large data throughIntentas this may lead toTransactionTooLargeException. - ๐ Processing the result: if you need to get data back (for example, after editing a profile), use
startActivityForResult(obsolete since API 30) orActivity Result API.
โ๏ธ Preparing for the transition between screens
3. Deep Link: following custom links
Deep Link allows you to open specific screens of your application using universal links (for example, myapp://product/42 or https://example.com/product/42). This is critical for marketing campaigns, push notifications and integration with other services.
To configure Deep Link:
- Add
intent-filtertoAndroidManifest.xmlfor targetActivity:<activity android:name=".DetailActivity"><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:host="example.com"
android:pathPrefix="/product"
android:scheme="https" />
</intent-filter>
</activity> - Process incoming
IntentinActivity:override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
handleIntent(intent)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntent(intent)
}
private fun handleIntent(intent: Intent?) {
val data = intent?.data
if (data != null && data.pathSegments.size > 1) {
val productId = data.lastPathSegment
// Load data for productId
}
}
| Deep Link Type | Link Format | Does the installed application require? | Support in Android |
|---|---|---|---|
| Custom scheme | myapp://product/42 |
Yes | All versions |
| HTTP/HTTPS | https://example.com/product/42 |
No (opens in the browser) | All versions |
| Android App Links | https://example.com/product/42 |
No (the system automatically redirects to application). data-i="115">. Without this, the system will not trust your links. | Android 6.0+ (API 23+) |
| Firebase Dynamic Links | https://myapp.page.link/product/42 |
No (works even if the application is not installed) | All versions |
โ ๏ธ Attention: Starting from Android 12 (API 31), to work with Android App Links requires signing with a digital certificate and confirmation of domain ownership via Digital Asset Links. Without this, the system will not trust your links.
What are Digital Asset Links?
This is a JSON file hosted on your domain (for example, https://example.com/.well-known/assetlinks.json) that confirms the connection between a website and an Android application. It must be generated via Android Studio (Tools โ App Links Assistant) and uploaded to the server.
4. Firebase Dynamic Links: universal links
Firebase Dynamic Links is a solution from Googlethat allows you to create "smart" links that work in any scenario:
- ๐ If the application is installed, it opens a specific screen.
- ๐ If the application is not installed, it redirects to Play Market or to a web page.
- ๐ฑ Supports delayed deep linking (for example, after installing an application).
An example of creating a dynamic link:
val dynamicLink = Firebase.dynamicLinks.dynamicLink {link = Uri.parse("https://example.com/product/42")
domainUriPrefix = "https://myapp.page.link"
androidParameters("com.example.app") {
minimumVersion = 123
}
socialMetaTagParameters {
title = "Check out this product!"
description = "50% off today only"
imageUrl = Uri.parse("https://example.com/image.png")
}
}
val dynamicLinkUri = dynamicLink.uri
// Send a dynamicLinkUri to the user (for example, in a push notification)
To process an incoming link in the application:
FirebaseDynamicLinks.getInstance().getDynamicLink(intent)
.addOnSuccessListener { pendingDynamicLinkData ->
val deepLink = pendingDynamicLinkData?.link
if (deepLink != null) {
// Process a deepLink (for example, retrieve productId)
}
}
Use Firebase Console to create short links and track conversion statistics. This will help analyze the effectiveness of marketing campaigns.
5. Handling links in WebView
If your application uses WebView to display content, you may want to intercept link clicks and process them within the application (for example, open some URLs in WebViewand others in the browser or deep links).
Example settings WebViewClient:
webView.webViewClient = object : WebViewClient() {override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
val url = request?.url.toString()
return when {
url.startsWith("https://example.com/") -> {
// Open in WebView
false
}
url.startsWith("myapp://") -> {
// Process as Deep Link
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
true
}
else -> {
// Open in browser
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
startActivity(intent)
true
}
}
}
}
Important nuances:
- ๐ก๏ธ Security: always check the URL before processing to avoid Open Redirect type vulnerabilities (for example, when an attacker replaces a link to a phishing site).
- ๐ Navigation back: if
WebViewsupports history, implement processing of the "Back" button throughwebView.canGoBack().
6. Typical errors and their solutions
When working with link transitions, developers often encounter the following problems:
| Error | Cause | Solution |
|---|---|---|
ActivityNotFoundException |
There is no application on the device that can process Intent (for example, there is no browser). |
Check availability through resolveActivity() or suggest installing a browser. |
| Deep Link does not work | Incorrectly configured intent-filter or not confirmed Digital Asset Links. |
Check the manifest and file assetlinks.json via Statement List Tester. |
Links in TextView not clickable |
Not installed MovementMethod or incorrect HTML format. |
Use LinkMovementMethod and the correct syntax <a href="...">. |
TransactionTooLargeException |
Too large data is transmitted through Intent. |
Use ViewModeldatabase or SharedPreferences for storing data. |
Another common problem is incorrect processing of links in Android 11+. Starting API 30, access to files and packages of other applications is limited. If your link leads to a local file (for example, file:///storage/emulated/0/...), use FileProvider or MediaStore API.
Always test link clicks on real devices running different versions of Android. Emulators may not show problems related to manufacturers (for example, Xiaomi or Huawei some Intents are blocked).
FAQ: Frequently asked questions about clicking links
How to check if a device supports Deep Link?
Use PackageManager to check availability Intent:
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://test"))val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
val isSupported = activities.isNotEmpty()
If isSupported == false, prompt the user to update the application or install it.
Is it possible to open the link in a specific browser (for example, only in Chrome)?
Yes, but this is not recommended, as it violates the principles Android (the user must select the application by default). If you still need, specify an explicit package:
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://example.com"))intent.setPackage("com.android.chrome") // Chrome package
startActivity(intent)
Please note that the browser may not be installed, so process ActivityNotFoundException.
How to make the link open in the application and not in the browser?
Use Android App Links (see section 3). To do this:
- Set up
intent-filterwithhttpsscheme. - Confirm domain rights via
Digital Asset Links. - Test via
adb:adb shell am start -a android.intent.action.VIEW -d "https://example.com/product/42"
If everything configured correctly, the system will offer to open the link in your application.
Why do Firebase Dynamic Links not work on some devices?
Problems may be associated with:
- ๐ฅ Lack of Google Play Services (relevant for devices in China or with custom firmware).
- ๐ก๏ธ Blocking Firebase firewall or VPN.
- ๐ฑ Manufacturer restrictions (for example, Huawei uses its own AppGallery instead Play Market).
Solution: add a fallback mechanism (for example, opening a web version of the link) and test on devices without Google Services.
How to transfer data between screens without using Intent?
If the data is too large for Intent, use:
- ๐๏ธ ViewModel + LiveData (for UI-related data).
- ๐ Room Database or SharedPreferences (for permanent storage).
- ๐ Singleton or Dependency Injection (for example, Dagger Hilt).
Example with ViewModel:
class SharedViewModel : ViewModel() {private val _data = MutableLiveData<String>()
val data: LiveData<String> = _data
fun setData(value: String) {
_data.value = value
}
}
// In the first Activity:
viewModel.setData("Hello");
// In the second Activity:
viewModel.data.observe(this) { value ->
textView.text = value
}