Short answer: assetlinks.json is a list, so it starts with [. Each statement needs a relation array and a target object with namespace: "android_app", package_name and sha256_cert_fingerprints. A top-level object, an empty array or a web namespace will not verify App Links. Check the live file with Google's Statement List tester.
What is happening
assetlinks.json statement: one object in the file's top-level array that grants a relation (such as delegate_permission/common.handle_all_urls) to a target app, identified by package name and signing certificate fingerprint.
Google's App Links documentation shows the file as an array with one or more statements. If the array is missing, empty, or the target is incomplete, Android finds no statement linking your app to the site.
- Top-level object:
{ "relation": ... }without the surrounding[ ]. - Empty array:
[], which declares nothing. - Wrong namespace:
"namespace": "web"describes a website target, used for other purposes, not an Android app. - Misspelt keys:
packageNameorsha256_fingerprintsare ignored.
Why does this happen?
The structure is easy to get wrong when copying one statement from documentation and editing it by hand, or when merging files for several apps.
- Google says "a website can declare associations with multiple apps within the same assetlinks.json file", which means several objects in one array, not several arrays.
- Two fingerprints in one statement are equivalent to two statements, so either form works.
How to confirm it
- Fetch the file:
curl -i https://example.com/.well-known/assetlinks.json. - Check the body starts with
[and each object hasrelationandtarget. - Compare it with Google's example: a top-level array, at least one statement,
namespaceset toandroid_appand all three target fields. Then test it with Google's Statement List tester. - Call
https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://example.com&relation=delegate_permission/common.handle_all_urlsto see which statements Google can read.
How to fix it
- Wrap the statements in a top-level array.
- Give each statement a
relationarray containingdelegate_permission/common.handle_all_urls. - Set
target.namespacetoandroid_app. - Add
package_name(the application ID frombuild.gradle) andsha256_cert_fingerprints(an array). - For several apps, add one statement per app in the same array.
- Deploy, then re-verify with
adb shell pm verify-app-links --re-verify com.example.app.
[
{
"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"]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.lite",
"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"]
}
}
]
The Android App Links setup guide shows this structure. If the structure is right, check the relation and package name next.