Apple HealthKit & Google FitをReact Native Expoで統合する方法
Apple HealthKitとGoogle Fitの fitness データをReact Native Expoアプリに安全に統合する包括的ガイド。権限設定、カスタムフック、統合データモデルの構築を解説します。
このページの内容
デジタルヘルス市場は急速に成長しており、ユーザーに対してフィットネスやウェルネスのデータを包括的に把握させることは、もはや追加機能ではなく当たり前の期待となっています。React Native開発者にとって、これはユニークな課題をもたらします。AppleのHealthKit(iOS)とGoogleのHealth Connect(Google Fitの後継、Android)という2つの異なるプラットフォーム固有のエコシステムからデータを安全にアクセスし、統合する方法です。
このチュートリアルでは、React NativeとExpoを使用してクロスプラットフォームの健康・フィットネスアプリケーションを構築する方法を説明します。ネイティブモジュールの力を借りて主要なヘルス指標を読み取り、各プラットフォームの複雑さを処理しながら、クリーンで統一されたコードベースを維持する方法を実演します。このチュートリアルを終えると、歩数、心拍数、睡眠データを取得できる動作するアプリと、より多くの指標を追加するための堅牢なフレームワークが得られます。
これは開発者にとって重要なテーマです。この統合をマスターすることで、ワークアウトトラッカーから包括的なウェルネスプラットフォームまで、すべて単一の管理しやすいReact Nativeプロジェクトから 健康技術アプリケーションを作成する道が開けます。
前提条件:
- Node.js(LTSバージョン)およびnpm/yarnがインストールされていること。
- Expo CLIがグローバルにインストールされていること。
- Apple HealthKitをテストするための物理的なiOSデバイスと、Google Fit/Health Connect用の物理的なAndroidデバイスまたはエミュレーター。
- React Native、TypeScript、Reactフックに関する基本的な理解。
問題の理解:2つのエコシステム
React Nativeアプリに健康データを統合するとは、2つの本質的に異なるネイティブAPIを扱うことを意味します:
- Apple HealthKit(iOS): iOS上で成熟し深く統合されたフレームワークです。すべての健康・フィットネスデータの中央暗号化リポジトリとして機能します。アクセスはデータタイプごとに許可され、ユーザーのプライバシーが最も重要です。
- Health Connect(Android): Googleの新しい統合プラットフォームで、ユーザーがお気に入りの健康・フィットネスアプリ間でデータを共有できます。以前は個々のアプリにサイロ化されていたり、古いGoogle Fit APIを通じてアクセス可能だったデータを統合します。
主な課題は、これら2つのプラットフォームが異なるデータ構造を公开し、異なるデータタイプ識別子を使用し、ユニークなセットアップと許可フローを持っていることです。私たちの目標は、この複雑さを隠蔽する抽象化レイヤーを作成し、Reactコンポーネントが実行中のOSを知る必要なく健康データをリクエストできるようにすることです。
前提条件:Expoプロジェクトの設定
HealthKitとHealth Connectの両方にネイティブコードを使用する必要があるため、標準のExpo Goアプリを使用できません。カスタム開発クライアントを作成する必要があります。このクライアントには、必要なネイティブモジュールを含めたアプリのバージョンになります。
ステップ1:プロジェクトの初期化
TypeScriptテンプレートを使用して新鮮なExpoプロジェクトから始めましょう:
npx create-expo-app MyHealthApp --template blank-typescript
cd MyHealthApp
ステップ2:依存関係のインストール
いくつかのライブラリが必要です:
expo-dev-client:カスタムクライアントのビルドと使用用。react-native-health:Apple HealthKitへのブリッジ。react-native-health-connect:AndroidのHealth Connectへのブリッジ。expo-build-properties:Androidの最小SDKバージョンを設定用。
1つのコマンドですべてインストールします:
npx expo install expo-dev-client react-native-health react-native-health-connect expo-build-properties
ステップ3:プロジェクトの設定
app.jsonファイルにいくつかの変更を加える必要があります。ここでは、ネイティブプロジェクトの設定とライブラリのための許可を構成します。
app.jsonを開いて、次のように変更します:
{
"expo": {
"name": "MyHealthApp",
"slug": "MyHealthApp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.yourcompany.myhealthapp",
"infoPlist": {
"NSHealthShareUsageDescription": "アクティビティを表示するために健康データへのアクセスが必要です。",
"NSHealthUpdateUsageDescription": "ワークアウトデータをApple Healthに書き込む必要があります。"
}
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#ffffff"
},
"package": "com.yourcompany.myhealthapp",
"permissions": [
"android.permission.health.READ_STEPS",
"android.permission.health.READ_HEART_RATE",
"android.permission.health.READ_SLEEP"
]
},
"web": {
"favicon": "./assets/favicon.png"
},
"plugins": [
"react-native-health",
"expo-health-connect",
[
"expo-build-properties",
{
"android": {
"compileSdkVersion": 34,
"targetSdkVersion": 34,
"minSdkVersion": 26
}
}
]
]
}
}
主な変更点:
- iOSの
infoPlist:HealthKitアクセスが必要な理由の説明を追加しました。これは必須であり、許可ダイアログでユーザーに表示されます。 - Androidの
permissions:アプリがリクエストするHealth Connectの許可を指定しました。 plugins:各ライブラリのプラグインを追加しました。expo-health-connectプラグインは、Androidネイティブプロジェクトに必要な変更を自動的に処理します。expo-build-propertiesプラグインは、AndroidアプリがHealth Connectに必要な十分な最新のSDKバージョンをターゲットにしていることを確認するために使用されます。
ステップ4:プレビルドと開発クライアントの実行
次に、ネイティブのiosとandroidディレクトリを生成します:
npx expo prebuild
最後に、カスタムクライアントをデバイスでビルドして実行します:
iOSの場合(物理デバイス上):
npx expo run:ios
Androidの場合(物理デバイスまたはエミュレーター上):
npx expo run:android
このプロセスは、初めては時間がかかる場合があります。実行されると、ネイティブ健康統合をテストする準備ができた開発環境が完成します。
コアロジック:統一されたuseHealthDataフック
プラットフォームの違いを管理するために、カスタムフックuseHealthDataを作成します。このフックは、requestPermissions()やfetchTodayStats()など、コンポーネントへのシンプルなAPIを公開し、すべてのプラットフォーム固有のロジックを内部的に処理します。
新しいディレクトリsrc/hooksを作成し、その中にuseHealthData.tsというファイルを作成します。
ステップ1:共通データ構造の定義
まず、統一されたHealthData型を定義します。これにより、ソースに関係なく、一貫したデータ形状でアプリケーションが動作することが保証されます。
// src/hooks/useHealthData.ts
export interface HealthData {
steps: number;
heartRate: number;
sleepHours: number;
}
ステップ2:フックとプラットフォーム固有モジュールの設定
次に、フックの基本構造を作成し、必要なライブラリをインポートします。
// src/hooks/useHealthData.ts
import { useState, useEffect } from 'react';
import { Platform } from 'react-native';
import AppleHealthKit, { HealthKitPermissions } from 'react-native-health';
import { initialize, requestPermission, readRecords } from 'react-native-health-connect';
export interface HealthData {
steps: number;
heartRate: number;
sleepHours: number;
}
// Apple HealthKitの許可を定義
const healthKitPermissions: HealthKitPermissions = {
permissions: {
read: [
AppleHealthKit.Constants.Permissions.Steps,
AppleHealthKit.Constants.Permissions.HeartRate,
AppleHealthKit.Constants.Permissions.SleepAnalysis,
],
write: [],
},
};
// Google Health Connectの許可を定義
const healthConnectPermissions = [
{ accessType: 'read', recordType: 'Steps' },
{ accessType: 'read', recordType: 'HeartRate' },
{ accessType: 'read', recordType: 'SleepSession' },
];
export const useHealthData = () => {
const [healthData, setHealthData] = useState<HealthData | null>(null);
const [isInitialized, setIsInitialized] = useState(false);
// ... 関数はここに追加
};
ステップ3:許可の実装
requestPermissions関数を実装しましょう。これは、ユーザーの同意を得るために最初に呼び出すものです。
// useHealthDataフック内
const requestPermissions = async (): Promise<boolean> => {
if (Platform.OS === 'ios') {
return new Promise((resolve) => {
AppleHealthKit.initHealthKit(healthKitPermissions, (error, results) => {
if (error) {
console.error("HealthKitの初期化中にエラー:", error);
return resolve(false);
}
setIsInitialized(true);
resolve(true);
});
});
} else if (Platform.OS === 'android') {
try {
const isInitialized = await initialize();
if (!isInitialized) {
console.error('Health Connectの初期化に失敗しました');
return false;
}
const grantedPermissions = await requestPermission(healthConnectPermissions);
console.log('許可された権限:', grantedPermissions);
setIsInitialized(true);
return true;
} catch (error) {
console.error("Health Connectの初期化中にエラー:", error);
return false;
}
}
return false;
};
動作の仕組み:
- iOS:
AppleHealthKit.initHealthKitを呼び出します。この関数は接続を初期化すると同時に、標準のiOS許可モーダルをユーザーに表示します。ユーザーは各許可を個別に許可または拒否できます。 - Android:プロセスは2段階です。まず、
initialize()がHealth Connectが利用可能で準備できているかを確認します。次に、requestPermission()がHealth Connectアプリの許可画面を開きます。
ステップ4:データの取得と正規化
ここでデータを統一します。適切なネイティブメソッドを呼び出し、結果をHealthDataインターフェースに変換するfetchTodayStats関数を作成します。
// useHealthDataフック内
const fetchTodayStats = async () => {
if (!isInitialized) {
console.warn("健康データが初期化されていません。最初に許可をリクエストしてください。");
return;
}
const today = new Date();
const startDate = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0).toISOString();
const endDate = today.toISOString();
let steps = 0;
let heartRate = 0;
let sleepHours = 0;
if (Platform.OS === 'ios') {
// --- iOSデータ取得 ---
const options = { date: endDate };
const stepResult = await new Promise<number>((resolve) => {
AppleHealthKit.getStepCount(options, (err, result) => {
resolve(result?.value || 0);
});
});
steps = stepResult;
// ... iOS心拍数と睡眠取得はここに追加
} else if (Platform.OS === 'android') {
// --- Androidデータ取得 ---
const stepRecords = await readRecords('Steps', {
timeRangeFilter: {
operator: 'between',
startTime: startDate,
endTime: endDate,
},
});
steps = stepRecords.reduce((total, record) => total + (record as any).count, 0);
// ... Android心拍数と睡眠取得はここに追加
}
setHealthData({ steps, heartRate, sleepHours });
};
このスニペットは主要な概念を説明するために歩数の取得のみを示しています。完全な実装には、HeartRateとSleepAnalysis/SleepSessionレコードの取得と正規化(例:心拍数、平均化、睡眠時間の合計)が含まれます。
すべてをまとめる:UI
これで、useHealthDataフックをReactコンポーネントで使用してデータを表示できます。
ファイルApp.tsxを作成し、以下のコードを追加します:
// App.tsx
import React, { useEffect } from 'react';
import { View, Text, Button, StyleSheet, SafeAreaView } from 'react-native';
import { useHealthData, HealthData } from './src/hooks/useHealthData'; // フックが完成したと仮定
export default function App() {
const { healthData, requestPermissions, fetchTodayStats } = useHealthData();
useEffect(() => {
// アプリの起動時に自動的に許可をリクエスト
requestPermissions().then(success => {
if (success) {
fetchTodayStats();
}
});
}, []);
return (
<SafeAreaView style={styles.container}>
<Text style={styles.title}>マイ健康統計</Text>
<View style={styles.card}>
<Stat label="歩数" value={healthData?.steps ?? 'N/A'} />
<Stat label="心拍数 (bpm)" value={healthData?.heartRate ?? 'N/A'} />
<Stat label="睡眠 (時間)" value={healthData?.sleepHours ?? 'N/A'} />
</View>
<Button title="データを更新" onPress={fetchTodayStats} />
</SafeAreaView>
);
}
const Stat = ({ label, value }: { label: string; value: string | number }) => (
<View style={styles.stat}>
<Text style={styles.label}>{label}</Text>
<Text style={styles.value}>{value}</Text>
</View>
);
const styles = StyleSheet.create({
// ... container、title、cardなどのスタイルを追加
});
このコンポーネントは許可をリクエストし、取得データを表示するためのシンプルなUIを提供し、抽象化の力を実証します。
セキュリティのベストプラクティス
機微な健康データを扱う場合、セキュリティとユーザーのプライバシーは交渉の余地がありません。
- 必要なものだけをリクエスト:アプリの機能に必要な特定のデータタイプの読み取り/書き込み許可のみを依頼してください。
- 透明性を保つ:健康データへのアクセスが必要な理由を、UIとプライバシーポリシーで明確に説明してください。
app.jsonのNSHealthShareUsageDescriptionは、信頼を構築する最初の機会です。 - データを責任を持って扱う:HIPAAやGDPRなどの規制に準拠し、絶対に必要な場合、また合规している場合にのみ、健康データをサーバーに保存しないでください。可能な場合はデバイス上でデータを処理してください。
- 穏やかな機能低下:ユーザーが許可を拒否した場合でも、アプリは穏やかに機能するべきです。クラッシュしたり、不必要に機能をロックしないでください。代わりに、何が利用できないかの明確な説明と、システム設定から後で許可を付与する方法を предоставьтеしてください。
結論
React Native ExpoアプリでApple HealthKitとGoogle Fitを統合することは、魅力的な健康・ウェルネスアプリケーションを構築する強力な方法です。カスタム開発クライアントを使用し、統一されたデータフックを作成することで、アプリケーションロジックをクリーンで保守しやすい状態に保ちながら、プラットフォーム固有のAPIを効果的に管理できます。このアプローチは、nutritionからワークアウトトラッキングまで、幅広い健康指標をサポートするために拡張できる堅実な基盤を提供します。
次のステップ
- 心拍数と睡眠データの正規化を含む
fetchTodayStats関数を完成させます。 - ワークアウト或其他の健康データをHealthKitとHealth Connectに書き込む機能を実装します。
- アプリのデータを最新の状態に保つためのバックグラウンドデータ取得を探索します。
- チャートやグラフで健康データを視覚化するためのより高度なUIコンポーネントを構築します。
リソース
- react-native-health(HealthKit用)ドキュメント
- react-native-health-connect(Health Connect用)ドキュメント
- Apple HealthKit開発者ドキュメント
- Android Health Connect開発者ドキュメント
クイックリファレンス
| 側面 | 重要な情報 |
|---|---|
| トピック | 開発 |
| 関連性 | 患者の知識と意識 |
| アクション | 医療提供者にご相談ください |
| 頻度 | ケアチームのおすすめに応じて |
| 証拠 | 現在の臨床ガイドラインに基づく |
よくある質問
Q: これが自分に該当する怎么看わかりますか? A: 個人の病歴と家族歴について医療提供者と相談し、個別のリスク因子を評価し、適切な次のステップを決定してください。
Q: 医師に何 вопросовすべきですか? A: 良い質問には次のようなものがあります:「私の結果はどういう意味ですか?」「私のオプションは何ですか?」「どのようなライフスタイルの変更が有帮助ですか?」「いつフォローアップすべきですか?」
Q: 帮助になるライフスタイルの変更はありますか? A: ほとんどの健康状態は、基本的な対策から benefits を受けます:バランスの取れた栄養、定期的な身体活動(週150分以上)、質の良い睡眠(7〜9時間)、ストレス管理、タバコの回避。
医学的免責事項
この記事は教育的目的のみを目的としており、医学的アドバイスを构成するものではありません。健康、治療、またはケアに関する決定する前に、常に資格のある医療提供者に相談してください。個人の状況是不同的ため、ある人に適切なことが別の人に適切なとは限りません。
医療上の緊急事態が発生した場合は、直ちに119番(またはお使いの地域の緊急電話番号)に連絡してください。