JavaScript bridge API
Health Connect
Reading and writing steps, distance, calories, heart rate, sleep, weight and exercise through Android’s Health Connect, for exactly the types the build ticked.
AppMint.health helper#
AppMint.health.isAvailable() / requestPermissions() / read() / write() / openHealthConnect()
Example
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.
healthIsAvailable bridge#
window.WebToApk.healthIsAvailable(callbackId: String)
Health Connect's state for this app; resolves [callbackId] with `{available, status, read, write}`.
Example
Documented together with AppMint.health - the example there shows this one too.
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.
healthOpen bridge#
window.WebToApk.healthOpen(callbackId: String)
Opens Health Connect, or its Play Store page when it is not installed.
Example
Documented together with AppMint.health - the example there shows this one too.
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.
healthRead bridge#
window.WebToApk.healthRead(type: String, optionsJson: String, callbackId: String)
Reads [type] records (or totals with `aggregate:true`) between [optionsJson] `start` and `end`.
Example
Documented together with AppMint.health - the example there shows this one too.
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.
healthRequestPermissions bridge#
window.WebToApk.healthRequestPermissions(requestJson: String, callbackId: String)
Opens Health Connect's permission screen for [requestJson] `{read:[…], write:[…]}`; resolves with `{granted, denied}`.
Example
Documented together with AppMint.health - the example there shows this one too.
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.
healthWrite bridge#
window.WebToApk.healthWrite(type: String, recordsJson: String, callbackId: String)
Writes the records in [recordsJson] (an array) as [type]; resolves with their ids.
Example
Documented together with AppMint.health - the example there shows this one too.
Reads and writes the user's health data through Health Connect: steps, distance, active calories, heart rate, sleep, weight and exercise sessions. Turn on Health data (Health Connect) in the wizard's Access step and tick the types and whether the app reads or writes each one - only those can be asked for.
Returns: every method returns a Promise. isAvailable() → {ok: true, available, status, read, write} (status: available, not_installed, update_required, unsupported = Android below 8.0, disabled = option off). The others → {ok: true, …} or {ok: false, code, message} with code disabled, unsupported, not_installed, update_required, not_declared (type not ticked in the wizard), permission (the user has not granted it), bad-input, blocked (a page from another site), failed. Needs: the wizard option, Android 8.0+, and Health Connect (built into Android 14+, an app from Play before that).
Types: steps, distance, calories, heartRate, sleep, weight, exercise. Times are milliseconds (Date.now()), Date objects or ISO strings; answers use ISO strings.
Check, then ask:
async function connectHealth() {
if (!(window.AppMint && AppMint.health)) return false; // browser or option off
var s = await AppMint.health.isAvailable();
if (s.status === 'not_installed') { await AppMint.health.openHealthConnect(); return false; }
if (!s.available) return false;
var r = await AppMint.health.requestPermissions({ read: ['steps', 'heartRate'], write: ['weight'] });
return r.ok && r.denied.read.length === 0;
}Today's steps (totals with aggregate: true, the records themselves without it):
async function stepsToday() {
var start = new Date(); start.setHours(0, 0, 0, 0);
var r = await AppMint.health.read('steps', { start: start, end: new Date(), aggregate: true });
if (!r.ok) { console.warn(r.code, r.message); return 0; }
return r.aggregate.count;
}
async function lastNightHeartRate() {
var end = Date.now(), start = end - 12 * 3600 * 1000;
var r = await AppMint.health.read('heartRate', { start: start, end: end });
// r.records = [{start, end, id, samples: [{time, bpm}]}]
return r.ok ? r.records.flatMap(function (x) { return x.samples; }) : [];
}Write - one record or an array:
await AppMint.health.write('weight', { time: Date.now(), kilograms: 72.4 });
await AppMint.health.write('exercise', [{
start: Date.now() - 45 * 60000, end: Date.now(), exerciseType: 'running', title: 'Evening run'
}]);
await AppMint.health.write('steps', { start: Date.now() - 3600000, end: Date.now(), count: 4200 });Record fields: steps {start, end, count} · distance {start, end, meters} · calories {start, end, kilocalories} · heartRate {start, end, samples: [{time, bpm}]} · sleep {start, end, title?, stages?: [{start, end, stage}]} (awake, sleeping, out_of_bed, light, deep, rem) · weight {time, kilograms} · exercise {start, end, exerciseType, title?} (Health Connect names such as running, walking, biking, swimming_pool, yoga, strength_training, other_workout). Aggregates: steps {count}, distance {meters}, calories {kilocalories}, heartRate {avg, min, max}, sleep / exercise {minutes}, weight {avg, min, max} (kg).
Notes: Health Connect shows your privacy policy from its permission screen - the address from the Finish step, or the generated policy. Before publishing on Google Play, fill in App content → Health apps in Play Console with the same data types and why the app needs each one; Play reviews health permissions. Health Connect gives an app the last 30 days of history from before its first grant. The raw bridge methods behind it (healthIsAvailable, healthRequestPermissions, healthRead, healthWrite, healthOpen) take JSON text and a callback id - use the helper.