始め方
-
パッケージのインストール
Terminal window npm i @capgo/capacitor-ibeaconTerminal window pnpm add @capgo/capacitor-ibeaconTerminal window yarn add @capgo/capacitor-ibeaconTerminal window bun add @capgo/capacitor-ibeacon -
ネイティブプロジェクトと同期
Terminal window npx cap syncTerminal window pnpm cap syncTerminal window yarn cap syncTerminal window bunx cap sync
Info.plistに以下を追加します:
<key>NSLocationWhenInUseUsageDescription</key><string>このアプリは近くのビーコンを検出するために位置情報アクセスが必要です</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key><string>このアプリはバックグラウンドでビーコンを監視するために位置情報アクセスが必要です</string>
<key>NSBluetoothAlwaysUsageDescription</key><string>このアプリは近くのビーコンを検出するためにBluetoothを使用します</string>
<key>UIBackgroundModes</key><array> <string>location</string></array>Android設定
Section titled “Android設定”AndroidManifest.xmlに以下を追加します:
<manifest> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /></manifest>重要: Androidの場合、ビーコン検出が動作するためには、AltBeaconライブラリをプロジェクトに統合する必要があります。
アプリのbuild.gradleに追加します:
dependencies { implementation 'org.altbeacon:android-beacon-library:2.20+'}基本的なセットアップ
Section titled “基本的なセットアップ”import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';
// ビーコンリージョンを定義const beaconRegion = { identifier: 'MyStore', uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D', major: 1, // 任意 minor: 2 // 任意};許可のリクエスト
Section titled “許可のリクエスト”// "使用中のみ"許可をリクエストconst requestPermission = async () => { const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization(); console.log('Permission status:', status); // status: 'not_determined' | 'restricted' | 'denied' | 'authorized_always' | 'authorized_when_in_use'};
// "常に許可"をリクエスト (バックグラウンド監視用)const requestAlwaysPermission = async () => { const { status } = await CapacitorIbeacon.requestAlwaysAuthorization(); console.log('Always permission status:', status);};
// 現在の認証状態を確認const checkPermission = async () => { const { status } = await CapacitorIbeacon.getAuthorizationStatus(); console.log('Current status:', status);};デバイスの機能を確認
Section titled “デバイスの機能を確認”// Bluetoothが有効かどうかを確認const checkBluetooth = async () => { const { enabled } = await CapacitorIbeacon.isBluetoothEnabled(); if (!enabled) { console.log('Please enable Bluetooth'); }};
// レンジングが利用可能かどうかを確認const checkRanging = async () => { const { available } = await CapacitorIbeacon.isRangingAvailable(); console.log('Ranging available:', available);};ビーコンリージョンの監視
Section titled “ビーコンリージョンの監視”監視は、ビーコンリージョンに入ったとき、または出たときを検出します。これはバックグラウンドで動作します。
// 監視を開始const startMonitoring = async () => { await CapacitorIbeacon.startMonitoringForRegion({ identifier: 'MyStore', uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D', major: 1, minor: 2 }); console.log('Started monitoring for beacons');};
// 監視を停止const stopMonitoring = async () => { await CapacitorIbeacon.stopMonitoringForRegion({ identifier: 'MyStore', uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D' });};ビーコンのレンジング
Section titled “ビーコンのレンジング”レンジングは、近くのビーコンとその距離について継続的な更新を提供します。これにはアプリがフォアグラウンドにある必要があります。
// レンジングを開始const startRanging = async () => { await CapacitorIbeacon.startRangingBeaconsInRegion({ identifier: 'MyStore', uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D' }); console.log('Started ranging beacons');};
// レンジングを停止const stopRanging = async () => { await CapacitorIbeacon.stopRangingBeaconsInRegion({ identifier: 'MyStore', uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D' });};イベントをリスンする
Section titled “イベントをリスンする”import { PluginListenerHandle } from '@capacitor/core';
// レンジングイベントをリスン (継続的な距離更新)const rangingListener: PluginListenerHandle = await CapacitorIbeacon.addListener( 'didRangeBeacons', (data) => { console.log('Beacons detected:', data.beacons); data.beacons.forEach(beacon => { console.log(`UUID: ${beacon.uuid}`); console.log(`Major: ${beacon.major}, Minor: ${beacon.minor}`); console.log(`Distance: ${beacon.accuracy}m`); console.log(`Proximity: ${beacon.proximity}`); // immediate, near, far, unknown console.log(`RSSI: ${beacon.rssi}`); }); });
// リージョン入域イベントをリスンconst enterListener: PluginListenerHandle = await CapacitorIbeacon.addListener( 'didEnterRegion', (data) => { console.log('Entered region:', data.region.identifier); // ウェルカム通知を表示するか、アクションをトリガー });
// リージョン退域イベントをリスンconst exitListener: PluginListenerHandle = await CapacitorIbeacon.addListener( 'didExitRegion', (data) => { console.log('Exited region:', data.region.identifier); // さよならアクションをトリガー });
// リージョン状態変更をリスンconst stateListener: PluginListenerHandle = await CapacitorIbeacon.addListener( 'didDetermineStateForRegion', (data) => { console.log(`Region ${data.region.identifier}: ${data.state}`); // state: 'inside' | 'outside' | 'unknown' });
// 完了時にリスナーをクリーンアップconst cleanup = () => { rangingListener.remove(); enterListener.remove(); exitListener.remove(); stateListener.remove();};iBeaconとして広告 (iOSのみ)
Section titled “iBeaconとして広告 (iOSのみ)”デバイスをiBeacon送信機に変換します。
// 広告を開始const startAdvertising = async () => { await CapacitorIbeacon.startAdvertising({ uuid: 'B9407F30-F5F8-466E-AFF9-25556B57FE6D', major: 1, minor: 2, identifier: 'MyBeacon', measuredPower: -59 // 任意: 1メートルでの較正パワー }); console.log('Started advertising as iBeacon');};
// 広告を停止const stopAdvertising = async () => { await CapacitorIbeacon.stopAdvertising();};import { CapacitorIbeacon } from '@capgo/capacitor-ibeacon';import { PluginListenerHandle } from '@capacitor/core';
export class BeaconService { private listeners: PluginListenerHandle[] = [];
async init() { // 許可をリクエスト const { status } = await CapacitorIbeacon.requestWhenInUseAuthorization();
if (status !== 'authorized_when_in_use' && status !== 'authorized_always') { throw new Error('Location permission denied'); }
// Bluetoothを確認 const { enabled } = await CapacitorIbeacon.isBluetoothEnabled(); if (!enabled) { throw new Error('Bluetooth is not enabled'); }
// イベントリスナーを設定 this.setupListeners(); }
private setupListeners() { this.listeners.push( await CapacitorIbeacon.addListener('didEnterRegion', (data) => { console.log('Welcome! Entered:', data.region.identifier); this.onEnterRegion(data.region); }) );
this.listeners.push( await CapacitorIbeacon.addListener('didExitRegion', (data) => { console.log('Goodbye! Left:', data.region.identifier); this.onExitRegion(data.region); }) );
this.listeners.push( await CapacitorIbeacon.addListener('didRangeBeacons', (data) => { this.onRangeBeacons(data.beacons); }) ); }
async startMonitoring(uuid: string, identifier: string, major?: number, minor?: number) { await CapacitorIbeacon.startMonitoringForRegion({ identifier, uuid, major, minor }); }
async startRanging(uuid: string, identifier: string) { await CapacitorIbeacon.startRangingBeaconsInRegion({ identifier, uuid }); }
private onEnterRegion(region: any) { // リージョン入域を処理 (例: 通知を表示、コンテンツをトリガー) console.log('Entered beacon region:', region); }
private onExitRegion(region: any) { // リージョン退域を処理 console.log('Left beacon region:', region); }
private onRangeBeacons(beacons: any[]) { // ビーコンの距離を処理 const nearestBeacon = beacons.reduce((nearest, beacon) => { return beacon.accuracy < nearest.accuracy ? beacon : nearest; }, beacons[0]);
if (nearestBeacon) { console.log('Nearest beacon:', nearestBeacon); this.handleProximity(nearestBeacon); } }
private handleProximity(beacon: any) { switch (beacon.proximity) { case 'immediate': // < 0.5m console.log('Very close to beacon'); break; case 'near': // 0.5m - 3m console.log('Near beacon'); break; case 'far': // > 3m console.log('Far from beacon'); break; case 'unknown': console.log('Distance unknown'); break; } }
cleanup() { this.listeners.forEach(listener => listener.remove()); this.listeners = []; }}APIリファレンス
Section titled “APIリファレンス”startMonitoringForRegion(options)
Section titled “startMonitoringForRegion(options)”ビーコンリージョンの監視を開始します。入域/退域時にイベントをトリガーします。
interface BeaconRegion { identifier: string; uuid: string; major?: number; minor?: number; notifyEntryStateOnDisplay?: boolean;}
await CapacitorIbeacon.startMonitoringForRegion(options);stopMonitoringForRegion(options)
Section titled “stopMonitoringForRegion(options)”ビーコンリージョンの監視を停止します。
await CapacitorIbeacon.stopMonitoringForRegion(options);startRangingBeaconsInRegion(options)
Section titled “startRangingBeaconsInRegion(options)”継続的な距離更新のためにリージョン内のビーコンのレンジングを開始します。
await CapacitorIbeacon.startRangingBeaconsInRegion(options);stopRangingBeaconsInRegion(options)
Section titled “stopRangingBeaconsInRegion(options)”リージョン内のビーコンのレンジングを停止します。
await CapacitorIbeacon.stopRangingBeaconsInRegion(options);startAdvertising(options)
Section titled “startAdvertising(options)”デバイスをiBeaconとして広告開始します (iOSのみ)。
interface BeaconAdvertisingOptions { uuid: string; major: number; minor: number; identifier: string; measuredPower?: number; // 1メートルでの較正パワー}
await CapacitorIbeacon.startAdvertising(options);stopAdvertising()
Section titled “stopAdvertising()”デバイスのiBeaconとしての広告を停止します。
await CapacitorIbeacon.stopAdvertising();requestWhenInUseAuthorization()
Section titled “requestWhenInUseAuthorization()”“使用中のみ”の位置情報認証をリクエストします。
const result = await CapacitorIbeacon.requestWhenInUseAuthorization();// 戻り値: { status: string }requestAlwaysAuthorization()
Section titled “requestAlwaysAuthorization()”“常に許可”の位置情報認証をリクエストします (バックグラウンド監視に必要)。
const result = await CapacitorIbeacon.requestAlwaysAuthorization();// 戻り値: { status: string }getAuthorizationStatus()
Section titled “getAuthorizationStatus()”現在の位置情報認証状態を取得します。
const result = await CapacitorIbeacon.getAuthorizationStatus();// 戻り値: { status: 'not_determined' | 'restricted' | 'denied' | 'authorized_always' | 'authorized_when_in_use' }isBluetoothEnabled()
Section titled “isBluetoothEnabled()”Bluetoothが有効かどうかを確認します。
const result = await CapacitorIbeacon.isBluetoothEnabled();// 戻り値: { enabled: boolean }isRangingAvailable()
Section titled “isRangingAvailable()”デバイスでレンジングが利用可能かどうかを確認します。
const result = await CapacitorIbeacon.isRangingAvailable();// 戻り値: { available: boolean }enableARMAFilter(options)
Section titled “enableARMAFilter(options)”距離計算のためのARMAフィルタリングを有効にします (Androidのみ)。
await CapacitorIbeacon.enableARMAFilter({ enabled: true });didRangeBeacons
Section titled “didRangeBeacons”レンジング中にビーコンが検出されたときに発火します。
interface RangingEvent { region: BeaconRegion; beacons: Beacon[];}
interface Beacon { uuid: string; major: number; minor: number; rssi: number; // 信号強度 proximity: 'immediate' | 'near' | 'far' | 'unknown'; accuracy: number; // メートル単位の距離}didEnterRegion
Section titled “didEnterRegion”監視対象のビーコンリージョンに入ったときに発火します。
interface RegionEvent { region: BeaconRegion;}didExitRegion
Section titled “didExitRegion”監視対象のビーコンリージョンを出たときに発火します。
interface RegionEvent { region: BeaconRegion;}didDetermineStateForRegion
Section titled “didDetermineStateForRegion”リージョンの状態が判定されたときに発火します。
interface StateEvent { region: BeaconRegion; state: 'inside' | 'outside' | 'unknown';}- immediate: 非常に近い (< 0.5メートル)
- near: 比較的近い (0.5 - 3メートル)
- far: より遠く (> 3メートル)
- unknown: 距離を判定できません
ベストプラクティス
Section titled “ベストプラクティス”-
適切な許可をリクエストする
- フォアグラウンド機能には”使用中のみ”を使用
- バックグラウンド監視が必要な場合のみ”常に許可”をリクエスト
- 位置情報アクセスが必要な理由を明確に説明
-
Bluetooth状態を処理する
const { enabled } = await CapacitorIbeacon.isBluetoothEnabled();if (!enabled) {// ユーザーにBluetoothを有効にするよう促す} -
バッテリーの最適化
- 可能な場合は、レンジングの代わりに監視を使用 (よりバッテリー効率的)
- 積極的に必要でないときはレンジングを停止
- 処理を減らすために、より大きなmajor/minor範囲の使用を検討
-
エラー処理
try {await CapacitorIbeacon.startMonitoringForRegion(region);} catch (error) {console.error('Failed to start monitoring:', error);} -
リスナーのクリーンアップ メモリリークを防ぐため、コンポーネントがアンマウントされるときは常にイベントリスナーを削除します。
プラットフォームに関する注意事項
Section titled “プラットフォームに関する注意事項”- iOS 10.0+が必要
- ネイティブのCoreLocationフレームワークを使用
- “常に許可”でバックグラウンド監視をサポート
- CoreBluetoothを使用してiBeaconとして広告可能
- レンジングにはアプリがフォアグラウンドにある必要があります
Android
Section titled “Android”- Android 6.0 (API 23)+が必要
- AltBeaconライブラリを使用
- ビーコンがBluetoothを使用しているにもかかわらず、位置情報許可が必要
- バックグラウンド監視にはACCESS_BACKGROUND_LOCATIONが必要 (Android 10+)
- ほとんどのデバイスでiBeaconとして広告できません (ハードウェアの制限)
- Webプラットフォームではサポートされていません
一般的なユースケース
Section titled “一般的なユースケース”- 近接マーケティング: ユーザーが店舗に近づいたときに通知やコンテンツをトリガー
- 屋内ナビゲーション: ビーコンウェイポイントを使用してユーザーを建物内で案内
- 出席追跡: ユーザーが場所に入ったときに自動チェックイン
- 資産追跡: 機器や在庫の移動を監視
- 博物館ツアー: 訪問者が展示物に近づくにつれてコンテキスト情報を提供
- スマートホーム: 部屋の存在に基づいて自動化をトリガー
トラブルシューティング
Section titled “トラブルシューティング”ビーコンが検出されない
Section titled “ビーコンが検出されない”- Bluetoothが有効になっていることを確認
- 位置情報許可が付与されていることを確認
- ビーコンのUUIDが正確に一致することを確認 (大文字小文字を区別)
- ビーコンが電源供給され、送信していることを確認
- まずmajor/minorフィルタなしで試す
バックグラウンド監視が動作しない
Section titled “バックグラウンド監視が動作しない”- “常に許可”の位置情報許可が付与されていることを確認
- UIBackgroundModesに
locationを追加 (iOS) - ACCESS_BACKGROUND_LOCATIONをリクエスト (Android 10+)
- 注意: iOSはバッテリーを節約するためにバックグラウンドコールバックを遅延させる場合があります
距離測定が不正確
Section titled “距離測定が不正確”- ビーコンのRSSIは環境によって変動します (壁、干渉)
- 三角測量のために複数のビーコンを使用
- ビーコンから1メートルの位置でmeasuredPowerを較正
- より滑らかな値のためにAndroidでARMAフィルタリングを有効化