feat: expo-audioによる音声再生機能を追加

- expo-audio依存を追加、app.jsonにプラグイン設定
- 設定画面ヘッダー画像タップで音声再生
- expo-assetでOTA対応のアセット解決 + file:// prefix除去(SDK52バグ回避)
- 音声ファイルはmp3のみ保持(wav/m4a/ogg削除)
- SDK53以降でinterruptionMode: duckOthers対応予定
This commit is contained in:
harukin-expo-dev-env
2026-03-17 09:43:54 +00:00
parent f387479ff7
commit adfe69b72f
4 changed files with 107 additions and 12 deletions
+31 -2
View File
@@ -23,7 +23,7 @@
"**/*"
],
"ios": {
"buildNumber": "52",
"buildNumber": "53",
"supportsTablet": false,
"bundleIdentifier": "jrshikokuinfo.xprocess.hrkn",
"config": {
@@ -46,6 +46,34 @@
"android": {
"package": "jrshikokuinfo.xprocess.hrkn",
"versionCode": 29,
"intentFilters": [
{
"action": "VIEW",
"data": [
{
"scheme": "jrshikoku"
}
],
"category": [
"BROWSABLE",
"DEFAULT"
]
},
{
"action": "VIEW",
"data": [
{
"scheme": "jrshikoku",
"host": "open",
"pathPrefix": "/felica"
}
],
"category": [
"BROWSABLE",
"DEFAULT"
]
}
],
"permissions": [
"ACCESS_FINE_LOCATION",
"NFC",
@@ -461,7 +489,8 @@
"kotlinVersion": "1.9.25"
}
}
]
],
"expo-audio"
]
}
}
Binary file not shown.
+75 -10
View File
@@ -1,4 +1,4 @@
import React from "react";
import React, { useCallback, useEffect, useState } from "react";
import {
View,
Text,
@@ -17,8 +17,15 @@ import { SwitchArea } from "../atom/SwitchArea";
import { useNotification } from "../../stateBox/useNotifications";
import { SheetHeaderItem } from "@/components/atom/SheetHeaderItem";
import { useTrainMenu } from "../../stateBox/useTrainMenu";
import { Asset } from "expo-asset";
import {
useAudioPlayer,
setAudioModeAsync,
} from "expo-audio";
import type { AudioSource } from "expo-audio";
const versionCode = "6.2.1.1"; // Update this version code as needed
const settingsPreviewSound = require("../../assets/sound/rikka-test.mp3");
export const SettingTopPage = ({
testNFC,
@@ -30,6 +37,62 @@ export const SettingTopPage = ({
const { expoPushToken } = useNotification();
const { updatePermission, dataSourcePermission } = useTrainMenu();
const navigation = useNavigation();
// expo-asset でローカルパスを取得し、expo-audio に渡す
// (SDK 52 の expo-audio は file:// URI を正しく処理できないため prefix を除去)
const [resolvedSource, setResolvedSource] = useState<AudioSource>(null);
useEffect(() => {
let mounted = true;
const resolve = async () => {
try {
const asset = Asset.fromModule(settingsPreviewSound);
await asset.downloadAsync();
const localUri = asset.localUri;
if (!mounted) return;
// file:// を剥がしてパスだけにする
// (expo-audio ネイティブ AudioModule.kt の File(uri) バグ回避)
const strippedPath = localUri
? localUri.replace(/^file:\/\//, "")
: null;
if (strippedPath) {
setResolvedSource({ uri: strippedPath });
}
} catch (error) {
if (!mounted) return;
console.warn("Failed to resolve audio asset", error);
}
};
resolve();
return () => {
mounted = false;
};
}, []);
const previewPlayer = useAudioPlayer(resolvedSource);
const onPressHeaderImage = useCallback(async () => {
try {
if (Platform.OS === "ios") {
await setAudioModeAsync({
playsInSilentMode: false,
shouldPlayInBackground: false,
interruptionMode: "mixWithOthers",
});
}
if (previewPlayer.playing) previewPlayer.pause();
previewPlayer.volume = 1;
await previewPlayer.seekTo(0);
previewPlayer.play();
} catch (error) {
console.warn("Failed to play preview sound", error);
}
}, [previewPlayer]);
// admin またはいずれかのソース権限を持つ場合のみ表示
const canAccessDataSourceSettings =
updatePermission || Object.values(dataSourcePermission).some(Boolean);
@@ -42,15 +105,17 @@ export const SettingTopPage = ({
<ScrollView style={{ flex: 1, backgroundColor: "#f8f8fc" }}>
<View style={{ height: 300, padding: 10 }}>
<View style={{ flex: 1 }} />
<Image
source={require("../../assets/Header.png")}
style={{
aspectRatio: 8.08,
height: undefined,
width: width - 20,
borderRadius: 5,
}}
/>
<TouchableOpacity activeOpacity={0.9} onPress={onPressHeaderImage}>
<Image
source={require("../../assets/Header.png")}
style={{
aspectRatio: 8.08,
height: undefined,
width: width - 20,
borderRadius: 5,
}}
/>
</TouchableOpacity>
<View style={{ flexDirection: "row", paddingTop: 10 }}>
<View style={{ flex: 1 }} />
<Text>内部バージョン: {versionCode}</Text>
+1
View File
@@ -24,6 +24,7 @@
"dayjs": "^1.11.9",
"expo": "^52.0.0",
"expo-alternate-app-icons": "^1.3.0",
"expo-audio": "~0.3.5",
"expo-build-properties": "~0.13.1",
"expo-clipboard": "~7.0.1",
"expo-constants": "~17.0.4",