""" Real Android Developer documentation lookup. Fetches from developer.android.com search and reference pages. No authentication required. """ from __future__ import annotations import logging import re import time from typing import Any from urllib.parse import quote_plus import httpx logger = logging.getLogger("dolor3v.tools.android_docs") _BASE = "https://developer.android.com" _SEARCH_URL = f"{_BASE}/s/results" _HEADERS = { "User-Agent": ( "Mozilla/5.0 (Linux; Android 14; Pixel 8) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0.0.0 Mobile Safari/537.36" ), "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", } # Curated fast-path: well-known Android API references _KNOWN_REFS: dict[str, str] = { "activity": "/reference/android/app/Activity", "fragment": "/reference/androidx/fragment/app/Fragment", "viewmodel": "/reference/androidx/lifecycle/ViewModel", "livedata": "/reference/androidx/lifecycle/LiveData", "room": "/reference/androidx/room/package-summary", "compose": "/jetpack/compose", "navigation": "/guide/navigation", "workmanager": "/reference/androidx/work/WorkManager", "coroutines": "/kotlin/coroutines", "hilt": "/training/dependency-injection/hilt-android", "retrofit": "https://square.github.io/retrofit/", "jetpack": "/jetpack", "manifest": "/guide/topics/manifest/manifest-intro", "permissions": "/guide/topics/permissions/overview", "intent": "/reference/android/content/Intent", "service": "/reference/android/app/Service", "broadcastreceiver": "/reference/android/content/BroadcastReceiver", "contentprovider": "/reference/android/content/ContentProvider", "recyclerview": "/reference/androidx/recyclerview/widget/RecyclerView", "constraintlayout": "/reference/androidx/constraintlayout/widget/ConstraintLayout", "gradle": "/build/releases/gradle-plugin", "apk": "/studio/build/build-variants", "aab": "/guide/app-bundle", "proguard": "/studio/build/shrink-code", "keystore": "/training/articles/keystore", } def _fast_path(query: str) -> str | None: q = query.lower().strip() for key, path in _KNOWN_REFS.items(): if key in q: return path if path.startswith("http") else f"{_BASE}{path}" return None async def lookup_android_docs( query: str, max_results: int = 5, ) -> dict[str, Any]: """ Fetch real Android Developer documentation. Tries fast-path known references first, then falls back to search. """ t0 = time.monotonic() # Fast path for known APIs fast_url = _fast_path(query) results = [] async with httpx.AsyncClient( timeout=20.0, follow_redirects=True, headers=_HEADERS, ) as client: if fast_url: try: resp = await client.get(fast_url) if resp.status_code == 200: # Extract title and description from HTML html = resp.text title_match = re.search(r"