html2apk Get the app

Dashboards and internal tools as HTML APKs

Field teams, warehouses and small offices need simple apps that work on cheap Android phones and patchy signal. HTML apps are the fastest way to give them one.

Updated 12 October 2026By HTML2APK Editorial Team8 min read
Short answer

To turn a dashboard or internal tool into an APK, bundle the chart library locally, cache the last API response in IndexedDB so the screen is never empty, queue form submissions while offline and send them when the connection returns, then build an APK and share it with staff directly or through a managed Google Play account.

Key takeaways

  • Show cached data first, then refresh — never a blank screen on bad signal.
  • Queue writes in IndexedDB and flush them on the online event.
  • Your API must allow CORS from https://appassets.androidplatform.net.
  • Internal apps can be shared as an APK file — no Play listing required.

Charts that work offline

Chart.js (about 70 KB gzipped), uPlot (very small, very fast) and ECharts all run in a WebView. Download the minified file into vendor/ rather than using a CDN. Keep animations short on low-end phones — animation: { duration: 250 } in Chart.js.

Cache first, then refresh

async function load(url, key) { const cached = localStorage.getItem(key); if (cached) render(JSON.parse(cached), { stale: true }); // instant try { const r = await fetch(url, { headers: { Authorization: 'Bearer ' + token() } }); if (!r.ok) throw new Error(r.status); const data = await r.json(); localStorage.setItem(key, JSON.stringify(data)); render(data, { stale: false }); } catch (e) { if (!cached) showOffline(); } }

Show the time of the last successful update — staff trust a screen that says "Updated 08:14" more than one that might be old.

Offline data entry with a send queue

function submit(record) { const q = JSON.parse(localStorage.getItem('queue') || '[]'); q.push({ ...record, id: crypto.randomUUID(), at: Date.now() }); localStorage.setItem('queue', JSON.stringify(q)); flush(); } async function flush() { let q = JSON.parse(localStorage.getItem('queue') || '[]'); while (q.length && navigator.onLine) { const r = await fetch('/api/records', { method: 'POST', body: JSON.stringify(q[0]), headers: { 'Content-Type': 'application/json' } }).catch(() => null); if (!r || !r.ok) break; q.shift(); localStorage.setItem('queue', JSON.stringify(q)); } updateBadge(q.length); } addEventListener('online', flush);

Sending a client-generated id lets the server ignore duplicates if a request succeeded but the response was lost. (Replace /api/records with your full https API address — inside the app a root path points at the app's own origin.)

CORS and authentication

Your files run on the origin https://appassets.androidplatform.net, so your API must return Access-Control-Allow-Origin for that origin (and handle preflight requests). Use token authentication in a header; cookies set by your API domain are third-party cookies from the app's point of view and are unreliable.

Getting it to staff

  • Direct APK — share the file or a QR link (how to share an APK). Each phone must allow installs from the app used to open it.
  • Managed Google Play — companies using Android Enterprise can publish private apps to their own staff only.
  • Updates — keep the package name and signing key, raise the version code; Android upgrades in place and keeps the queue and cache.

Frequently asked questions

Can an HTML app talk to our company API?

Yes, over https, provided the API allows cross-origin requests from the app's origin and you use token authentication. Keep secrets on the server, not in the HTML.

Can an internal app be kept off the public Play Store?

Yes. Share the APK directly, or use managed Google Play to publish a private app only your organisation can see.

H2

HTML2APK Editorial Team
Written and checked against the app our builder actually produces. Found an error? Tell us.

Turn your HTML into an APK today

Install the free builder on your Android phone, add your HTML file, ZIP or website, and install a signed APK a few minutes later. No watermark, no card.