'Intent Filter with android:autoVerify="true" - never verified at installation, default app links don't work
I'm using branch.io SDK in my Android app and want to make my app a default handler for branch links on Android 6 as described here(Android guide) and here(Branch.io guide)
This is my activity's declaration in AndroidManifest.xml:
<activity android:name="com.mypackage.MyActivity"
android:launchMode="singleTask">
<intent-filter tools:node="merge" android:autoVerify="true">
<data android:scheme="@string/url_scheme" android:host="open"/>
<data android:scheme="https"
android:host="@string/branch_io_host"
android:pathPrefix="@string/branch_io_path_prefix"/>
<data android:scheme="http"
android:host="@string/branch_io_host"
android:pathPrefix="@string/branch_io_path_prefix"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
However when I install a build on my device, I still keep seeing the chooser dialog when I click on a link with proper host and path. After readin through this extensive guide on app linking, I believe this is happening because my device never verifies my app's intent filter. E.g. when I install a Twitter app from the play store, I see these messages in LogCat:
03-24 15:04:27.231: D/IntentFilterVerificationReceiver(16965): Received ACTION_INTENT_FILTER_NEEDS_VERIFICATION.
03-24 15:04:27.248: I/IntentFilterIntentService(16965): Verifying IntentFilter. verificationId:2 scheme:"https" hosts:"twitter.com www.twitter.com ads.twitter.com" package:"com.twitter.android".
03-24 15:04:30.134: I/IntentFilterIntentService(16965): Verification 2 complete. Success:true. Failed hosts:.
But I don't see messages like this when I install my app. I tried both release and debug builds, tried uploading it to Alpha testing in the play store and installing from there, same result. Why does Android not verify my Intent filter?
Solution 1:[1]
Fixed this by moving this data tag into a separate intent filter:
<data android:scheme="@string/url_scheme" android:host="open"/>
This is what AndroidManifest looks like now:
<activity android:name="com.mypackage.MyActivity"
android:launchMode="singleTask">
<intent-filter tools:node="merge" android:autoVerify="true">
<data android:scheme="https"
android:host="@string/branch_io_host"
android:pathPrefix="@string/branch_io_path_prefix"/>
<data android:scheme="http"
android:host="@string/branch_io_host"
android:pathPrefix="@string/branch_io_path_prefix"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
<intent-filter>
<data android:scheme="@string/url_scheme" android:host="open"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
Messages from IntentFilter now show up in the log as intended.
Solution 2:[2]
For Deeplink to work without user prompt
Suppose your app manifest declares multiple hosts like myhost1.com, myhost2.com & myhost3.com,
<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="myhost1.com"
android:pathPrefix="/start" />
</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"
android:host="myhost2.com"
android:pathPrefix="/start" />
</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"
android:host="myhost3.com"
android:pathPrefix="/start" />
</intent-filter>
and deploys assetlinks.json for each one
https://myhost1.com/.well-known/assetlinks.json
https://myhost2.com/.well-known/assetlinks.json
https://myhost3.com/.well-known/assetlinks.json
While Installing the app from ADB or Google Play store keep checking your Logcat for IntentFilterIntentOp tag as follows
I/IntentFilterIntentOp: Verifying IntentFilter. verificationId:9 scheme:"https" hosts:"myhost1.com myhost2.com myhost3.com" package:"com.mydeeplink.app". [CONTEXT service_id=244 ]
On installation, the manifest declaration is verified if ANYONE host fails your DIRECT opening of the deep link will not work. Failure means the user will be prompted to choose either your app or browser.
NOTE NOTE NOTE: If you declare any test environment in the manifest which will be removed in the future. It will cause IntentFilterIntentOp FAILURE for your apps. It will break the direct opening of the deep link.
For the test environments, which will be removed later do not use android:autoVerify="true". Otherwise your production app deep link direct opening might be broken for the new installations.
Solution 3:[3]
For anyone who might be as careless as I am, according to https://developer.android.com/training/app-links:
Android App Links on Android 6.0 (API level 23) and higher allow an app to designate itself as the default handler of a given type of link.
I have happened to test it on an Android 5.1 device randomly and below Android 6, intent filter will work but android:autoVerify="true"
won't. You will NOT see IntentFilterIntentSvc
logs in adb logcat
, meaning that the url verification won't take place. In that case, Android will open the default app selection panel.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Anton Cherkashyn |
Solution 2 | |
Solution 3 | f4z3k4s |