Capacitorのデバイスセンサーは、小さく目的を絞ったプラグインから利用できます: @capgo/capacitor-accelerometer モーション用 @capgo/capacitor-barometer 気圧用 @capgo/capacitor-compass 方位用 @capgo/capacitor-pedometer 歩数用に加え、ライト、近接、シェイクのプラグインもあります。それぞれ同じ流れです:利用可否を確認し、必要なら権限をリクエストし、更新を開始してリスナーを登録し、終わったら停止します。本ガイドでは、Capacitor 8 codeでの全センサー、押さえるべきプラットフォームの違い、アプリが問題を起こさないためのバッテリーのルールを解説します。
センサーの概要
| センサー | プラグイン | iOSと | Androidでは | 権限 |
|---|---|---|---|---|
| 加速度センサー | @capgo/capacitor-accelerometer |
はい | はい | iOSと NSMotionUsageDescription |
| 気圧計 | @capgo/capacitor-barometer |
はい、相対高度で | はい、圧力のみ(センサー搭載デバイス) | iOS のモーション使用文字列 |
| コンパス | @capgo/capacitor-compass |
はい | はい、精度イベント付き | iOS の使用中の位置情報 |
| 歩数計 | @capgo/capacitor-pedometer |
歩数、距離、階数、ペース、歩幅 | ステップ | iOS のモーション、Android ACTIVITY_RECOGNITION |
| 環境光 | @capgo/capacitor-light-sensor |
公開されていない API | はい | なし |
| 近接 | @capgo/capacitor-proximity |
はい | はい | なし |
| シェイクジェスチャー | @capgo/capacitor-shake |
はい | はい | なし |
| ジャイロスコープ / 向き | Web DeviceMotionEvent / DeviceOrientationEvent |
はい | はい | iOSと requestPermission() WebView 内 |
必要なものだけをインストールしましょう。各プラグインは軽量で、権限の説明文が少なければ App Review での質問も減ります。
bun add @capgo/capacitor-accelerometer @capgo/capacitor-compass @capgo/capacitor-pedometer
bunx cap sync
iOSの設定
センサーに必要な使用目的の文字列を以下に追加してください: ios/App/App/Info.plist:
<!-- Accelerometer, pedometer, barometer altitude -->
<key>NSMotionUsageDescription</key>
<string>Counts your steps and detects movement during workouts.</string>
<!-- Compass heading -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Shows which direction you are facing on the map.</string>
ユーザーにとってのメリットを平易な言葉で説明しましょう。「このアプリにはモーションへのアクセスが必要です」のようなありきたりな文言は、App Review でリジェクトされるよくある原因です。
Androidの設定
ほとんどのセンサーは権限を必要としません。pedometerプラグインは ACTIVITY_RECOGNITION マージされたマニフェストに追加し、Android 10以降では実行時にリクエストします。
センサーが必須の場合は、Google Playで非対応デバイスにアプリが表示されないよう、ハードウェア機能を宣言してください。オプションの場合は、 required="false" と宣言した上で、実行時に利用可能か確認します:
<uses-feature android:name="android.hardware.sensor.barometer" android:required="false" />
<uses-feature android:name="android.hardware.sensor.stepcounter" android:required="false" />
<uses-feature android:name="android.hardware.sensor.compass" android:required="false" />
加速度センサー:動きと傾き
加速度計は、x、y、z軸の加速度をG単位で報告します。平らに置かれたスマホは、 z = -1 または 1 重力が含まれるため、プラットフォームの慣例によって異なります。
import { CapacitorAccelerometer } from '@capgo/capacitor-accelerometer';
const { isAvailable } = await CapacitorAccelerometer.isAvailable();
if (isAvailable) {
await CapacitorAccelerometer.requestPermissions();
const listener = await CapacitorAccelerometer.addListener('measurement', ({ x, y, z }) => {
const tiltX = Math.atan2(x, Math.sqrt(y * y + z * z)) * (180 / Math.PI);
ball.style.transform = `translateX(${tiltX * 3}px)`;
});
await CapacitorAccelerometer.startMeasurementUpdates();
// later
await CapacitorAccelerometer.stopMeasurementUpdates();
await listener.remove();
}
ユースケース:ゲームの傾き操作、「持ち上げてスリープ解除」UI、転倒・衝撃検知、活動強度。生データはノイズが多いため、使用前にローパスフィルタで平滑化してください:
const alpha = 0.2;
let smoothed = { x: 0, y: 0, z: 0 };
function lowPass(m: { x: number; y: number; z: number }) {
smoothed = {
x: smoothed.x + alpha * (m.x - smoothed.x),
y: smoothed.y + alpha * (m.y - smoothed.y),
z: smoothed.z + alpha * (m.z - smoothed.z),
};
return smoothed;
}
サンプルごとにDOMを更新しないでください。最新の値を保持し、 requestAnimationFrame ループ内で描画します。
シェイクジェスチャー
「シェイクでバグ報告」や「シェイクで元に戻す」では、しきい値を自分で調整する必要はありません:
import { CapacitorShake } from '@capgo/capacitor-shake';
const handle = await CapacitorShake.addListener('shake', () => openFeedbackForm());
ジャイロスコープとデバイスの向き
回転に専用のプラグインは不要です。WebViewがすでに提供しています:
async function enableMotion() {
// iOS 13+ requires a user gesture and explicit permission
const DME = DeviceMotionEvent as unknown as { requestPermission?: () => Promise<'granted' | 'denied'> };
if (typeof DME.requestPermission === 'function') {
const result = await DME.requestPermission();
if (result !== 'granted') return;
}
window.addEventListener('devicemotion', (e) => {
const r = e.rotationRate; // alpha, beta, gamma in degrees per second
if (r) updateRotation(r.alpha ?? 0, r.beta ?? 0, r.gamma ?? 0);
});
window.addEventListener('deviceorientation', (e) => {
// alpha: 0-360 around z, beta: -180..180 front/back, gamma: -90..90 left/right
updateOrientation(e.alpha, e.beta, e.gamma);
});
}
document.querySelector('#enable-motion')!.addEventListener('click', enableMotion);
呼び出す requestPermission ボタンのタップを起点にし、ページ読み込み時には実行しないでください。iOSがリクエストを拒否します。
コンパス:方位(heading)
import { CapgoCompass, CompassAccuracy } from '@capgo/capacitor-compass';
const status = await CapgoCompass.requestPermissions(); // iOS: location permission
if (status.compass === 'granted') {
await CapgoCompass.addListener('headingChange', ({ value }) => {
needle.style.transform = `rotate(${-value}deg)`;
});
await CapgoCompass.startListening({
minInterval: 100, // ms between events
minHeadingChange: 2, // degrees
});
// Android only: ask the user to calibrate when accuracy drops
await CapgoCompass.addListener('accuracyChange', ({ accuracy }) => {
calibrationHint.hidden = accuracy >= CompassAccuracy.MEDIUM;
});
await CapgoCompass.watchAccuracy();
}
// One-off reading
const { value } = await CapgoCompass.getCurrentHeading();
value 磁北からの角度(0〜360度)です。注意点は以下のとおりです:
- 磁力計は、スマホケース、ノートPC、車載ホルダーなどの磁石の影響を受けます。Androidで精度が低いと報告された場合は、キャリブレーションのヒント(スマホを8の字に動かすよう促す)を表示してください。
- 〜でスロットル制御を行い、
minIntervalとminHeadingChangeJavaScript内ではなくそこで処理することで、ブリッジのトラフィックを削減できます。 - ユーザーに合わせて回転する地図を作るには、方位とGeolocationを組み合わせます。アプリがバックグラウンドの状態でも位置情報が必要な場合は、以下を参照してください: background geolocation プラグイン.
Pedometer: 歩数、距離、階数
歩数カウンターは低消費電力チップで、アプリが起動していないときでも継続的にカウントします。
import { CapacitorPedometer } from '@capgo/capacitor-pedometer';
const features = await CapacitorPedometer.isAvailable();
// { stepCounting, distance, pace, cadence, floorCounting }
const perm = await CapacitorPedometer.requestPermissions();
if (perm.activityRecognition !== 'granted') {
// explain why and link to settings
}
// Steps today (start and end are required on iOS)
const startOfDay = new Date();
startOfDay.setHours(0, 0, 0, 0);
const today = await CapacitorPedometer.getMeasurement({
start: startOfDay.getTime(),
end: Date.now(),
});
console.log(today.numberOfSteps, today.distance, today.floorsAscended);
// Live updates during a walk
await CapacitorPedometer.addListener('measurement', (m) => {
stepsEl.textContent = String(m.numberOfSteps ?? 0);
});
await CapacitorPedometer.startMeasurementUpdates();
プラットフォームごとの違い:
- iOSと (Core Motion) は過去約7日間の履歴クエリに応答し、対応デバイスでは距離、階数、ペース、ケイデンスも提供します。
- Androidでは 歩数のみを報告します。ハードウェアカウンターは再起動時にリセットされるため、生涯累計として扱わないでください。独自のベースラインを保存してください。
長期的な履歴、デバイスをまたいだ日次合計、ウォッチからのデータが必要な場合は、ヘルスストアから以下を使って読み取ってください @capgo/capacitor-health 代わりに、こちらを使用してください。これは Apple Health と Health Connect のすべてのソースから歩数を集計します。当社の Health Connect 移行ガイド で設定方法を説明しています。
気圧計: 気圧と高度
import { CapacitorBarometer } from '@capgo/capacitor-barometer';
const { isAvailable } = await CapacitorBarometer.isAvailable();
if (isAvailable) {
await CapacitorBarometer.requestPermissions();
await CapacitorBarometer.addListener('measurement', ({ pressure, relativeAltitude }) => {
pressureEl.textContent = `${pressure.toFixed(1)} hPa`;
altitudeEl.textContent = `${relativeAltitude.toFixed(1)} m`;
});
await CapacitorBarometer.startMeasurementUpdates();
}
pressure 両プラットフォームともヘクトパスカル単位です。 relativeAltitude は、更新開始時からの変化量(メートル)で、iOSでのみ提供されます。Androidでは常に 0なので、気圧高度公式を使って自分で計算してください:
const P0 = 1013.25; // standard sea-level pressure in hPa
const altitudeMeters = (p: number) => 44330 * (1 - Math.pow(p / P0, 1 / 5.255));
let baseline: number | null = null;
function relativeAltitude(pressure: number) {
baseline ??= altitudeMeters(pressure);
return altitudeMeters(pressure) - baseline;
}
気圧から求めた絶対高度は、天候で海面気圧が変わるため数十メートルずれます。数分間の相対変化は約1メートル精度なので、階数や登った高さを数えるには十分です。低価格のAndroid端末の多くは気圧計を搭載していないため、必ず isAvailable.
環境光センサー (Android)
import { LightSensor } from '@capgo/capacitor-light-sensor';
const { available } = await LightSensor.isAvailable(); // always false on iOS
if (available) {
await LightSensor.addListener('lightSensorChange', ({ illuminance }) => {
document.body.classList.toggle('high-contrast', illuminance > 10_000); // bright sunlight
});
await LightSensor.start({ updateInterval: 500 });
}
一般的な値: 10 lux以下は暗い部屋、数百 lux はオフィス、数万 lux は直射日光です。部屋に合わせて調整する読書モードや、屋外でコントラストを上げる用途に活用しましょう。画面の輝度自体を変更するには、これと組み合わせて @capgo/capacitor-brightness.
近接センサー
近接センサーは、画面上部が何かに覆われたこと(通話中のユーザーの耳など)を検知します。
import { CapacitorProximity } from '@capgo/capacitor-proximity';
const status = await CapacitorProximity.getStatus();
if (status.available) {
await CapacitorProximity.enable(); // screen turns off when covered
}
// when the call or voice message ends
await CapacitorProximity.disable();
iOSでは、これで UIDevice.isProximityMonitoringEnabledが切り替わり、覆われている間はディスプレイがオフになります。Androidでは、プラグインが近接センサーを監視してアプリのウィンドウを暗くします。有効にするのは、音声通話、ボイスメッセージ、トランシーバーモードが動作している間だけにしてください。ユーザーの頬がボタンを押さないようにするためです。
センサーアプリの実践的なルール
- まずは利用可能か確認しましょう。 タブレットには歩数計や気圧計がないことが多く、エミュレータはほとんどのセンサーを擬似的に動作させます。サポートできない機能は非表示にしましょう。
- 非表示のときは更新を停止します。 使用する
@capacitor/appのappStateChangeアプリがバックグラウンドに回った時にリスナーを停止し、復帰時に再開するようにします。センサーを動かし続けるとバッテリーを消耗し、低評価レビューの原因になります。 - プラグインが許可している場合は、ネイティブの code でスロットリングを行います (コンパス
minInterval, 光センサーupdateInterval)、JavaScript ではなく。 - 適切なタイミングで権限を要求 モーションへのアクセス権限は、アプリの初回起動時ではなく、ユーザーがワークアウトを開始した時にリクエストしてください。
- 実機でテストする。 シミュレーターは一定値や合成値を返します。センサーが欠落しているかノイズの多い、安価なAndroid端末を少なくとも1台テストしてください。
- プライバシールールを遵守する。 モーションや位置情報データは、App StoreのプライバシーラベルやPlayのデータ安全性フォームで機密情報に該当します。収集する内容を宣言してください。
トラブルシューティング
iOSでイベントが発生しない:使用文字列が不足しています Info.plist、または権限が拒否されました。設定 > プライバシーとセキュリティ > モーションとフィットネスを確認してください。
AndroidでPedometerが0を返す: ACTIVITY_RECOGNITION が拒否されたか、デバイスに歩数カウンターがない可能性があります。確認してください isAvailable().stepCounting.
コンパスがブレる:磁気干渉またはキャリブレーション未実施。Androidでは精度を監視し、キャリブレーションのヒントを表示してください。
relativeAltitude 常に0になります:Androidで想定される値です。上記のように気圧から計算してください。
DeviceMotionEvent.requestPermission スローします:ユーザーのジェスチャーから呼び出されていません。
バッテリー消費レポート:リスナーがバックグラウンドで動作し続けています。次のタイミングで停止してください: appStateChange.
センサー機能を素早くリリース
Thresholds, smoothing factors and UI for sensor features usually need several rounds of tuning with real users. That logic lives in JavaScript, so you can adjust it with Capgo Live Updates ストア審査なしで反映できますが、新しいプラグインや権限文字列は通常のビルドが必要です。チェストストラップなどの外部センサーを接続する場合は、次のガイドに進んでください: Capacitor で心拍数モニターを構築する.