I turned my website directory into an offline Android app. Here's the SQL trick that made it work
The constraint I gave myself: the app must work with the network off, and must show every user the same "today's picks" without asking a server.
重點摘要
Data ships in the APK and loads into Room on first run.
SQLite uses a date-seeded ORDER BY expression to shuffle today's picks.
Kotlin must mirror the SQL math in Long to keep navigation in sync.
The developer turned a small web directory into an offline Android app by bundling about 800 sites, categories, tags, pricing, and multilingual descriptions inside the APK, then loading them into Room on first launch. Search, filters, and browsing run entirely in local SQLite, while only thumbnails and ads touch the network. The key challenge was reproducing a stable, serverless “today’s picks” shuffle, solved with a date-based seed and a simple linear congruential ORDER BY expression that SQLite can evaluate. The same ordering logic had to be duplicated in Kotlin using Long arithmetic so detail-page next/previous navigation matched exactly. The post also notes trade-offs: faster startup and independence from server uptime, but updates are needed when the catalog changes.
我把网站目录做成了离线 Android App,靠的是这个 SQL 小技巧
我给自己的约束是:App 必须在断网时也能运行,并且不向服务器请求就让所有用户看到同一组“今日精选”。
重點摘要
数据打包进 APK,首次启动后导入 Room。
用日期作为种子,在 SQLite 内完成稳定洗牌。
Kotlin 端要用 Long 复现 SQL 计算,才能让上一页/下一页一致。
作者把一个网站目录改造成离线 Android App,将约 800 个站点、分类、标签、价格和五种语言的描述直接打包进 APK,首次运行时导入 Room,搜索、筛选与浏览都在本地 SQLite 中完成。核心难点是如何在没有服务器参与的情况下,让“今日精选”每天稳定且对所有用户一致;作者用日期作为种子,借助简单的线性同余公式在 SQL 里完成排序。为了让详情页的上一条/下一条导航和列表顺序完全一致,Kotlin 端也必须用 Long 复现同样的计算。文章同时指出,这种方案的代价是目录更新需要发布 App 更新。
我把網站目錄做成離線 Android App,靠的是這個 SQL 小技巧
我給自己的限制是:App 必須在斷網時也能運作,並且不向伺服器請求就讓所有使用者看到同一組「今日精選」。
重點摘要
資料打包進 APK,首次開啟後匯入 Room。
用日期作為種子,在 SQLite 內完成穩定洗牌。
Kotlin 端要用 Long 重現 SQL 計算,才能讓上一頁/下一頁一致。
作者把原本的網站目錄改成離線 Android App,將約 800 個站點、分類、標籤、價格與多語描述直接打包進 APK,首次執行後匯入 Room,搜尋與篩選都在本機 SQLite 完成。最大的難題是如何在沒有伺服器的情況下,讓「今日精選」每天固定且對所有人一致;做法是用日期當種子,搭配簡單的線性同餘公式在 SQL 中排序。為了讓詳情頁的上一筆/下一筆導航完全一致,Kotlin 端必須以 Long 重新實作同樣的運算。文章也提到這種做法的代價是內容更新必須透過 App 更新。