17

I have setup assetlinks.json and AndroidManifest.xml so that the desired App Links are verified in all previous versions of Android. However, the verification no longer works in Android 12 (currently Beta 2). adb shell pm get-app-links <PACKAGE_NAME> returns legacy_failure.

There seems to be some changes for App Links verification in Android 12, but the documentation isn't very explicit about what needs to be changed and whether the change is backward compatible.

Mars Lan
  • 471
  • 1
  • 4
  • 7
  • Works fine for me on Android 12 Beta 3 and even when putting scheme and host into one data tag. Maybe you just needed to give the request some time to complete? – ubuntudroid Aug 04 '21 at 15:27
  • I was facing same issue due to the different package name inside assertlink.json file. Make sure your package name will be same in assertlink.json file. – Rao Arsalan Nov 09 '21 at 13:28

8 Answers8

30

Turns out that if you break

<data android:scheme="http" android:host="www.example.com" />

into 2 tags

<data android:scheme="http" />
<data android:host="www.example.com" />

in AndroidManifest.xml, the app link will get verified successfully on Android 12. This change also seems backward compatible on older versions of Android, even though the documentation didn't say so explicitly.

Mars Lan
  • 471
  • 1
  • 4
  • 7
  • how to test this ?? – RockyGlobal Feb 01 '23 at 13:03
  • Important note: In my case I had example.com added as the host (because that's how it's explained everywhere) but since I was redirecting all requests from example.com to www.example.com due to SEO reasons it didn't work until adding the www. – Manuel Mar 06 '23 at 17:53
14

I faced the same issue.

sha256_cert_fingerprints of debug & release keystore are different.

if you register only release fingerprints on assetlinks.json, the verification doesn't work on debug version. so adb shell pm get-app-links <PACKAGE_NAME> returns legacy_failure.

It will work if you add both fingerprints (debug & release) on assetlinks.json

elegwance
  • 141
  • 1
  • 4
  • 1
    how to add both fingerprint , like comma separated in sha256 array – dastan Mar 17 '22 at 07:40
  • @dastan Did you figure how to add both together? – hushed_voice Mar 29 '22 at 14:36
  • Yes, we updated our sha256 in assetlinks.json, and use above command to check fingerprint, if your build is signed with same keystore which fingerprint you added in assetlinks.json, then it will work otherwise it will always give legacy_failure, and I used Android Studio Asset Link tool to verify and test deep link – dastan Mar 30 '22 at 07:40
  • https://stackoverflow.com/a/71676088/6341943 This is how I added both the keys. and it started working for me. Thanks guys – hushed_voice Mar 30 '22 at 11:09
7

In addition to the other answers which detail the need to:

  • ensure you are using the correct sha256_cert_fingerprints value for the type of build you are testing, noting that this may differ based on whether you are using a Debug or Release build
  • use separate scheme and host data tags entries for your intent-filter definition

It is also important to ensure that your intent-filter with android:autoVerify="true" does not contain any custom uri schemes (i.e. launch://myapp/screen) since these can cause the verifier to fail.

A new intent-filter can be provided solely for the custom uri scheme in which you do not set the autoVerify flag to true.

Check logcat whilst running the following commands to confirm if verification is working, as per the docs here.

adb shell pm verify-app-links --re-verify <PACKAGE_NAME>

Look for the term IntentFilterIntentOp where it will state if verification succeeded or failed, i.e.:

I/IntentFilterIntentOp: Verification 23 complete. Success:true. Failed hosts:. [CONTEXT service_id=244 ]

If one or more of the intent-filter definitions cannot be verified you may see the following in Logcat instead:

"D/ProcessState: Binder ioctl to enable oneway spam detection failed: Invalid argument" and no mention of IntentFilterIntentOp

Jadent
  • 974
  • 8
  • 14
5

What changed?

As from Android 12 they have introduced a new way of checking for supported web domains.

Lower versions of android remain unchanged.

How does verification in android 12 works?

On installing the application android sends async requests to domains inside intent links to check if .well-known/assetlinks.json exists and is valid.

How to generate assetlinks.json?

I recommend using this tool google provides for generating that file. It can also check if assetlinks.json is present and setup correctly. Generator: https://developers.google.com/digital-asset-links/tools/generator

Where to get SHA-256 form?

  1. Open Android Studio
  2. Open your Project
  3. Click on Gradle (From Right Side Panel, you will see Gradle Bar)
  4. Click on Refresh (Click on Refresh from Gradle Bar, you will see List
  5. Gradle scripts of your Project)
  6. Click on Your Project (Your Project Name form List (root))
  7. Click on Tasks
  8. Click on Android
  9. Double Click on signingReport (You will get SHA1 and MD5 in Run Bar(Sometimes it will be in Gradle Console))
  10. Select app module from module selection dropdown to run or debug your application

After you have generated .json file, at put it inside root of domain (.well-known/assetlinks.json). I recommend opening it manually just to make sure. https://my.domain.com/.well-known/assetlinks.json

Setting up Intent links in application

To your AndroidManifest.xml add

<!-- Make sure you have explicitly set autoVerify to 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" />
 <!-- If a user clicks on a shared link that uses the "http" scheme, your
     app should be able to delegate that traffic to "https". -->
<data android:scheme="http" />
<data android:scheme="https" />

<!-- Include one or more domains that should be verified. -->
  <data
          android:scheme="https"
          android:host="**my.domain.com**"
          android:pathPrefix="/test" />
</intent-filter>

Manually test if intent link is working:

You can run this command with your emulator running and it should open the application:

adb shell am start -W -a android.intent.action.VIEW -d "https://my.domain.com/test?code=abcde"

Manually test intent link

  1. Support the updated domain verification process

    adb shell am compat enable 175408749 PACKAGE_NAME

  2. Reset the state of Android App Links on a device

adb shell pm set-app-links --package PACKAGE_NAME 0 all

  1. Invoke the domain verification process

adb shell pm verify-app-links --re-verify PACKAGE_NAME

After running this command, it is CRUCIAL to wait for at least a minute for app to verify your domain.

  1. Review the verification results

adb shell pm get-app-links PACKAGE_NAME

The output of this command is similar to the following:

com.example.pkg:
ID: 01234567-89ab-cdef-0123-456789abcdef
Signatures: [***]
Domain verification state:
  my.domain.com: verified
  sub.example.com: legacy_failure
  example.net: verified
  example.org: 1026

After that you're good to go, your intent links will work on android 12 and lower.

Final test to check if you have set up everything properly Run:

 adb shell am start -W -a android.intent.action.VIEW -d "https://my.domain.com/test?code=abcde"

Source: https://developer.android.com/training/app-links/verify-site-associations

iammtander
  • 111
  • 1
  • 2
4

Tested on Android 12, all the points mentioned by Jadent are valid, however breaking data declaration in host and scheme doesn't really matters.

Also I was using a wildcard in the 'host' attribute

android:host="*.example.com"

That's supposed to be supported in the documentation

However when I run the domain verification process

adb shell pm verify-app-links --re-verify PACKAGE_NAME

I got a legacy_failure error :( even if the assetlinks.json was placed in the root domain as required.

If the host is explicit:

android:host="www.example.com"

I didn't have such issue.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Paolo Moschini
  • 352
  • 3
  • 3
  • 1
    Was assetlinks.json at the root domain directly without redirects? That turned out to be my problem. assetlinks.json was at www.example.com, and example.com redirected to www.example.com. The assetlinks.json file is required to be directly accessible without going through a redirect (for security reasons, according to the docs.) – Jim E-H May 02 '22 at 21:29
  • Finally solved it, the problem was only in Android 12 and the solution was adding "www." in front of the link. The only problem now is that the link is first opened in a browser and then it switches to the app, not sure if this is the wanted behaviour but at least it works so good enough for me, thanks! – Cosmin Vacaru Jun 21 '22 at 07:52
  • @CosminVacaru in the manifest where host is defined?? – Awais Saifi Sep 28 '22 at 12:22
  • @AwaisSaifi yes, in my case i had and by changing it to it started working – Cosmin Vacaru Sep 29 '22 at 08:51
  • @JimE-H Machan, I really don't know who you are, Your comment helped me a lot. Finally, the app link is auto-verified. I wish to have a coffee with you. Thanks a lot, man. – Rethinavel Nov 30 '22 at 06:10
2

I had the same issue before.

It turns out that I used Play App signing service. The sha256_cert_fingerprints should be the one printed in Play Console (Release > Setup > App integrity), not the one on my hand. In fact, Play console generates the assetlinks.json in the "App integrity" page.

Ref for Play App signing https://developer.android.com/training/app-links/verify-site-associations#web-assoc

wMaN
  • 309
  • 4
  • 10
1

I tried all of the solutions above but none of those worked for me. I only changed on silly thing just to test and it worked. May be it's an obvious requirement but I didn't know so writing it down to help the others.

sha256_cert_fingerprints should always be uppercase in assetlinks.json file. I copied it off the terminal with lowercase letters and it didn't work but after changing it to uppercase, working flawlessly now.

0

None of the above worked for me. I was initially getting

ID: xxxx
Signatures: [XX:XX:XX:XX]
Domain verification state:
  xxx.xxxxxxx.eu-central-1.on.aws: 1024. 

In my https://xxxxxxxxxx/.well-known/assetlinks.json file I hosted on my domain, I put 3 Signatures, one from release, another from debug and the last from the playstore (So I dont know which did the magic). But What changed verification state to: 'verified' was running this adb shell pm verify-app-links --re-verify package-name command and waiting for 1 minute. After that everything worked well.

Fedor
  • 17,146
  • 13
  • 40
  • 131
Azeem
  • 33
  • 7