@siteed/expo-audio-stream 1.9.2 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -1
- package/README.md +4 -0
- package/android/src/main/java/net/siteed/audiostream/AudioNotificationsManager.kt +89 -33
- package/android/src/main/java/net/siteed/audiostream/AudioRecorderManager.kt +213 -1
- package/android/src/main/java/net/siteed/audiostream/Constants.kt +1 -0
- package/android/src/main/java/net/siteed/audiostream/ExpoAudioStreamModule.kt +5 -1
- package/android/src/main/java/net/siteed/audiostream/PermissionUtils.kt +8 -0
- package/android/src/main/java/net/siteed/audiostream/RecordingConfig.kt +3 -1
- package/build/AudioAnalysis/extractAudioAnalysis.d.ts.map +1 -1
- package/build/AudioAnalysis/extractWaveform.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.d.ts +8 -0
- package/build/ExpoAudioStream.types.d.ts.map +1 -1
- package/build/ExpoAudioStream.types.js.map +1 -1
- package/build/utils/BlobFix.d.ts.map +1 -1
- package/build/utils/convertPCMToFloat32.d.ts +2 -2
- package/build/utils/convertPCMToFloat32.d.ts.map +1 -1
- package/build/utils/encodingToBitDepth.d.ts.map +1 -1
- package/build/utils/getWavFileInfo.d.ts.map +1 -1
- package/ios/AudioStreamManager.swift +55 -14
- package/ios/AudioStreamManagerDelegate.swift +1 -0
- package/ios/ExpoAudioStreamModule.swift +16 -4
- package/ios/RecordingSettings.swift +4 -1
- package/package.json +2 -1
- package/plugin/build/index.d.ts +6 -1
- package/plugin/build/index.js +43 -38
- package/plugin/src/index.ts +75 -50
- package/src/ExpoAudioStream.types.ts +20 -0
|
@@ -19,6 +19,7 @@ data class RecordingConfig(
|
|
|
19
19
|
val enableCompressedOutput: Boolean = false,
|
|
20
20
|
val compressedFormat: String = "opus",
|
|
21
21
|
val compressedBitRate: Int = 24000,
|
|
22
|
+
val autoResumeAfterInterruption: Boolean = false,
|
|
22
23
|
) {
|
|
23
24
|
companion object {
|
|
24
25
|
fun fromMap(options: Map<String, Any?>?): Result<Pair<RecordingConfig, AudioFormatInfo>> {
|
|
@@ -73,7 +74,8 @@ data class RecordingConfig(
|
|
|
73
74
|
features = features,
|
|
74
75
|
enableCompressedOutput = enableCompressedOutput,
|
|
75
76
|
compressedFormat = compressedFormat,
|
|
76
|
-
compressedBitRate = compressedBitRate
|
|
77
|
+
compressedBitRate = compressedBitRate,
|
|
78
|
+
autoResumeAfterInterruption = options.getBooleanOrDefault("autoResumeAfterInterruption", false)
|
|
77
79
|
)
|
|
78
80
|
|
|
79
81
|
// Validate sample rate and channels
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractAudioAnalysis.d.ts","sourceRoot":"","sources":["../../src/AudioAnalysis/extractAudioAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAGtD,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAkB,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrE,MAAM,WAAW,yBAAyB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,kBAAkB,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB;AAED,eAAO,MAAM,oBAAoB,oKAa9B,yBAAyB,KAAG,
|
|
1
|
+
{"version":3,"file":"extractAudioAnalysis.d.ts","sourceRoot":"","sources":["../../src/AudioAnalysis/extractAudioAnalysis.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAGtD,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,oBAAoB,EACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAkB,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrE,MAAM,WAAW,yBAAyB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,EAAE,kBAAkB,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAC/B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB;AAED,eAAO,MAAM,oBAAoB,oKAa9B,yBAAyB,KAAG,OAAO,CAAC,aAAa,CAsGnD,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractWaveform.d.ts","sourceRoot":"","sources":["../../src/AudioAnalysis/extractWaveform.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AACD,eAAO,MAAM,eAAe,kDAKzB,oBAAoB,KAAG,
|
|
1
|
+
{"version":3,"file":"extractWaveform.d.ts","sourceRoot":"","sources":["../../src/AudioAnalysis/extractWaveform.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAClB;AACD,eAAO,MAAM,eAAe,kDAKzB,oBAAoB,KAAG,OAAO,CAAC,OAAO,CAQxC,CAAA"}
|
|
@@ -79,6 +79,11 @@ export interface AudioSessionConfig {
|
|
|
79
79
|
export interface IOSConfig {
|
|
80
80
|
audioSession?: AudioSessionConfig;
|
|
81
81
|
}
|
|
82
|
+
export type RecordingInterruptionReason = 'audioFocusLoss' | 'audioFocusGain' | 'phoneCall' | 'phoneCallEnded';
|
|
83
|
+
export interface RecordingInterruptionEvent {
|
|
84
|
+
reason: RecordingInterruptionReason;
|
|
85
|
+
isPaused: boolean;
|
|
86
|
+
}
|
|
82
87
|
export interface RecordingConfig {
|
|
83
88
|
sampleRate?: SampleRate;
|
|
84
89
|
channels?: 1 | 2;
|
|
@@ -100,6 +105,8 @@ export interface RecordingConfig {
|
|
|
100
105
|
format: 'aac' | 'opus' | 'mp3';
|
|
101
106
|
bitrate?: number;
|
|
102
107
|
};
|
|
108
|
+
autoResumeAfterInterruption?: boolean;
|
|
109
|
+
onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void;
|
|
103
110
|
}
|
|
104
111
|
export interface NotificationConfig {
|
|
105
112
|
title?: string;
|
|
@@ -144,5 +151,6 @@ export interface UseAudioRecorderState {
|
|
|
144
151
|
size: number;
|
|
145
152
|
compression?: CompressionInfo;
|
|
146
153
|
analysisData?: AudioAnalysis;
|
|
154
|
+
onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void;
|
|
147
155
|
}
|
|
148
156
|
//# sourceMappingURL=ExpoAudioStream.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.types.d.ts","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus' | 'mp3'\n bitrate?: number\n }\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoAudioStream.types.js","sourceRoot":"","sources":["../src/ExpoAudioStream.types.ts"],"names":[],"mappings":"","sourcesContent":["// packages/expo-audio-stream/src/ExpoAudioStream.types.ts\nimport {\n AmplitudeAlgorithm,\n AudioAnalysis,\n AudioFeaturesOptions,\n} from './AudioAnalysis/AudioAnalysis.types'\nimport { AudioAnalysisEvent } from './events'\n\nexport interface CompressionInfo {\n size: number\n mimeType: string\n bitrate: number\n format: string\n}\n\nexport interface AudioStreamStatus {\n isRecording: boolean\n isPaused: boolean\n durationMs: number\n size: number\n interval: number\n mimeType: string\n compression?: CompressionInfo\n}\n\nexport interface AudioDataEvent {\n data: string | Float32Array\n position: number\n fileUri: string\n eventDataSize: number\n totalSize: number\n compression?: CompressionInfo & {\n data?: string | Blob // Base64 (native) or Float32Array (web) encoded compressed data chunk\n }\n}\n\nexport type EncodingType = 'pcm_32bit' | 'pcm_16bit' | 'pcm_8bit'\nexport type SampleRate = 16000 | 44100 | 48000\nexport type BitDepth = 8 | 16 | 32\n\nexport type ConsoleLike = {\n log: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n}\n\nexport interface Chunk {\n text: string\n timestamp: [number, number | null]\n}\n\nexport interface TranscriberData {\n id: string\n isBusy: boolean\n text: string\n startTime: number\n endTime: number\n chunks: Chunk[]\n}\n\nexport interface AudioRecording {\n fileUri: string\n filename: string\n durationMs: number\n size: number\n mimeType: string\n channels: number\n bitDepth: BitDepth\n sampleRate: SampleRate\n transcripts?: TranscriberData[]\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface StartRecordingResult {\n fileUri: string\n mimeType: string\n channels?: number\n bitDepth?: BitDepth\n sampleRate?: SampleRate\n compression?: CompressionInfo & {\n compressedFileUri: string\n }\n}\n\nexport interface AudioSessionConfig {\n category?:\n | 'Ambient'\n | 'SoloAmbient'\n | 'Playback'\n | 'Record'\n | 'PlayAndRecord'\n | 'MultiRoute'\n mode?:\n | 'Default'\n | 'VoiceChat'\n | 'VideoChat'\n | 'GameChat'\n | 'VideoRecording'\n | 'Measurement'\n | 'MoviePlayback'\n | 'SpokenAudio'\n categoryOptions?: (\n | 'MixWithOthers'\n | 'DuckOthers'\n | 'InterruptSpokenAudioAndMixWithOthers'\n | 'AllowBluetooth'\n | 'AllowBluetoothA2DP'\n | 'AllowAirPlay'\n | 'DefaultToSpeaker'\n )[]\n}\n\nexport interface IOSConfig {\n audioSession?: AudioSessionConfig\n}\n\n// Add new type for interruption reasons\nexport type RecordingInterruptionReason =\n | 'audioFocusLoss'\n | 'audioFocusGain'\n | 'phoneCall'\n | 'phoneCallEnded'\n\n// Add new interface for interruption events\nexport interface RecordingInterruptionEvent {\n reason: RecordingInterruptionReason\n isPaused: boolean\n}\n\nexport interface RecordingConfig {\n // Sample rate for recording (16000, 44100, or 48000 Hz)\n sampleRate?: SampleRate\n\n // Number of audio channels (1 for mono, 2 for stereo)\n channels?: 1 | 2\n\n // Encoding type for the recording (pcm_32bit, pcm_16bit, pcm_8bit)\n encoding?: EncodingType\n\n // Interval in milliseconds at which to emit recording data\n interval?: number\n\n // Keep the device awake while recording (default is false)\n keepAwake?: boolean\n\n // Show a notification during recording (default is false)\n showNotification?: boolean\n\n // Show waveform in the notification (Android only, when showNotification is true)\n showWaveformInNotification?: boolean\n\n // Configuration for the notification\n notification?: NotificationConfig\n\n // Enable audio processing (default is false)\n enableProcessing?: boolean\n\n // iOS-specific configuration\n ios?: IOSConfig\n\n // Number of data points to extract per second of audio (default is 1000)\n pointsPerSecond?: number\n\n // Algorithm to use for amplitude computation (default is \"rms\")\n algorithm?: AmplitudeAlgorithm\n\n // Feature options to extract (default is empty)\n features?: AudioFeaturesOptions\n\n // Callback function to handle audio stream\n onAudioStream?: (_: AudioDataEvent) => Promise<void>\n\n // Callback function to handle audio features extraction results\n onAudioAnalysis?: (_: AudioAnalysisEvent) => Promise<void>\n\n compression?: {\n enabled: boolean\n format: 'aac' | 'opus' | 'mp3'\n bitrate?: number\n }\n\n // Whether to automatically resume recording after an interruption (default is false)\n autoResumeAfterInterruption?: boolean\n\n // Optional callback to handle recording interruptions\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n\nexport interface NotificationConfig {\n // Title of the notification\n title?: string\n\n // Main text content of the notification\n text?: string\n\n // Icon to be displayed in the notification (resource name or URI)\n icon?: string\n\n // Android-specific notification configuration\n android?: {\n // Unique identifier for the notification channel\n channelId?: string\n\n // User-visible name of the notification channel\n channelName?: string\n\n // User-visible description of the notification channel\n channelDescription?: string\n\n // Unique identifier for this notification\n notificationId?: number\n\n // List of actions that can be performed from the notification\n actions?: NotificationAction[]\n\n // Configuration for the waveform visualization in the notification\n waveform?: WaveformConfig\n\n // Color of the notification LED (if device supports it)\n lightColor?: string\n\n // Priority of the notification (affects how it's displayed)\n priority?: 'min' | 'low' | 'default' | 'high' | 'max'\n\n // Accent color for the notification (used for the app icon and buttons)\n accentColor?: string\n }\n\n // iOS-specific notification configuration\n ios?: {\n // Identifier for the notification category (used for grouping similar notifications)\n categoryIdentifier?: string\n }\n}\n\nexport interface NotificationAction {\n // Display title for the action\n title: string\n\n // Unique identifier for the action\n identifier: string\n\n // Icon to be displayed for the action (Android only)\n icon?: string\n}\n\nexport interface WaveformConfig {\n color?: string // The color of the waveform (e.g., \"#FFFFFF\" for white)\n opacity?: number // Opacity of the waveform (0.0 - 1.0)\n strokeWidth?: number // Width of the waveform line (default: 1.5)\n style?: 'stroke' | 'fill' // Drawing style: \"stroke\" for outline, \"fill\" for solid\n mirror?: boolean // Whether to mirror the waveform (symmetrical display)\n height?: number // Height of the waveform view in dp (default: 64)\n}\n\nexport interface UseAudioRecorderState {\n startRecording: (_: RecordingConfig) => Promise<StartRecordingResult>\n stopRecording: () => Promise<AudioRecording | null>\n pauseRecording: () => Promise<void>\n resumeRecording: () => Promise<void>\n isRecording: boolean\n isPaused: boolean\n durationMs: number // Duration of the recording\n size: number // Size in bytes of the recorded audio\n compression?: CompressionInfo\n analysisData?: AudioAnalysis // Analysis data for the recording depending on enableProcessing flag\n onRecordingInterrupted?: (_: RecordingInterruptionEvent) => void\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlobFix.d.ts","sourceRoot":"","sources":["../../src/utils/BlobFix.ts"],"names":[],"mappings":"AAugBA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,SAClB,IAAI,YACA,MAAM,oBAEjB,
|
|
1
|
+
{"version":3,"file":"BlobFix.d.ts","sourceRoot":"","sources":["../../src/utils/BlobFix.ts"],"names":[],"mappings":"AAugBA;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,SAClB,IAAI,YACA,MAAM,oBAEjB,OAAO,CAAC,IAAI,CA4Bd,CAAA"}
|
|
@@ -3,8 +3,8 @@ export declare const WAV_HEADER_SIZE = 44;
|
|
|
3
3
|
export declare const convertPCMToFloat32: ({ bitDepth, buffer, skipWavHeader, logger, }: {
|
|
4
4
|
buffer: ArrayBuffer;
|
|
5
5
|
bitDepth: number;
|
|
6
|
-
skipWavHeader?: boolean
|
|
7
|
-
logger?: ConsoleLike
|
|
6
|
+
skipWavHeader?: boolean;
|
|
7
|
+
logger?: ConsoleLike;
|
|
8
8
|
}) => Promise<{
|
|
9
9
|
pcmValues: Float32Array;
|
|
10
10
|
min: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertPCMToFloat32.d.ts","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAGtD,eAAO,MAAM,eAAe,KAAK,CAAA;AA+DjC,eAAO,MAAM,mBAAmB;
|
|
1
|
+
{"version":3,"file":"convertPCMToFloat32.d.ts","sourceRoot":"","sources":["../../src/utils/convertPCMToFloat32.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAGtD,eAAO,MAAM,eAAe,KAAK,CAAA;AA+DjC,eAAO,MAAM,mBAAmB,iDAK7B;IACC,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB,KAAG,OAAO,CAAC;IAAE,SAAS,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA2FhE,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encodingToBitDepth.d.ts","sourceRoot":"","sources":["../../src/utils/encodingToBitDepth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,eAAO,MAAM,kBAAkB;
|
|
1
|
+
{"version":3,"file":"encodingToBitDepth.d.ts","sourceRoot":"","sources":["../../src/utils/encodingToBitDepth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,eAAO,MAAM,kBAAkB,kBAE5B;IACC,QAAQ,EAAE,YAAY,CAAA;CACzB,KAAG,QAWH,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getWavFileInfo.d.ts","sourceRoot":"","sources":["../../src/utils/getWavFileInfo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAoB/D;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,gBACV,WAAW,KACzB,
|
|
1
|
+
{"version":3,"file":"getWavFileInfo.d.ts","sourceRoot":"","sources":["../../src/utils/getWavFileInfo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAoB/D;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;CAC1B;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,gBACV,WAAW,KACzB,OAAO,CAAC,WAAW,CAmFrB,CAAA"}
|
|
@@ -11,6 +11,7 @@ import Accelerate
|
|
|
11
11
|
import UIKit
|
|
12
12
|
import MediaPlayer
|
|
13
13
|
import UserNotifications
|
|
14
|
+
import CallKit
|
|
14
15
|
|
|
15
16
|
// Helper to convert to little-endian byte array
|
|
16
17
|
extension UInt32 {
|
|
@@ -74,6 +75,9 @@ class AudioStreamManager: NSObject {
|
|
|
74
75
|
private var compressedFormat: String = "aac"
|
|
75
76
|
private var compressedBitRate: Int = 128000
|
|
76
77
|
|
|
78
|
+
// Add property to track auto-resume preference
|
|
79
|
+
private var autoResumeAfterInterruption: Bool = false
|
|
80
|
+
|
|
77
81
|
/// Initializes the AudioStreamManager
|
|
78
82
|
override init() {
|
|
79
83
|
super.init()
|
|
@@ -107,28 +111,62 @@ class AudioStreamManager: NSObject {
|
|
|
107
111
|
}
|
|
108
112
|
}
|
|
109
113
|
|
|
110
|
-
/// Handles audio session
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
let typeValue = info[AVAudioSessionInterruptionTypeKey] as? UInt,
|
|
114
|
+
/// Handles an audio session interruption.
|
|
115
|
+
@objc private func handleAudioSessionInterruption(_ notification: Notification) {
|
|
116
|
+
guard let userInfo = notification.userInfo,
|
|
117
|
+
let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
|
|
115
118
|
let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
|
|
116
119
|
return
|
|
117
120
|
}
|
|
118
121
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
let wasSuspended = isPaused
|
|
123
|
+
|
|
124
|
+
switch type {
|
|
125
|
+
case .began:
|
|
126
|
+
Logger.debug("Audio session interruption began")
|
|
127
|
+
pauseRecording()
|
|
128
|
+
|
|
129
|
+
// Notify about the interruption
|
|
130
|
+
delegate?.audioStreamManager(
|
|
131
|
+
self,
|
|
132
|
+
didReceiveInterruption: [
|
|
133
|
+
"type": "began",
|
|
134
|
+
"wasSuspended": wasSuspended
|
|
135
|
+
]
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
case .ended:
|
|
139
|
+
Logger.debug("Audio session interruption ended")
|
|
140
|
+
if let optionsValue = userInfo[AVAudioSessionInterruptionOptionKey] as? UInt {
|
|
124
141
|
let options = AVAudioSession.InterruptionOptions(rawValue: optionsValue)
|
|
125
142
|
if options.contains(.shouldResume) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
if autoResumeAfterInterruption && !wasSuspended {
|
|
144
|
+
resumeRecording()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Notify about the interruption
|
|
148
|
+
delegate?.audioStreamManager(
|
|
149
|
+
self,
|
|
150
|
+
didReceiveInterruption: [
|
|
151
|
+
"type": "ended",
|
|
152
|
+
"wasSuspended": wasSuspended,
|
|
153
|
+
"shouldResume": true
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
} else {
|
|
157
|
+
// Notify about the interruption without resume option
|
|
158
|
+
delegate?.audioStreamManager(
|
|
159
|
+
self,
|
|
160
|
+
didReceiveInterruption: [
|
|
161
|
+
"type": "ended",
|
|
162
|
+
"wasSuspended": wasSuspended,
|
|
163
|
+
"shouldResume": false
|
|
164
|
+
]
|
|
165
|
+
)
|
|
130
166
|
}
|
|
131
167
|
}
|
|
168
|
+
@unknown default:
|
|
169
|
+
break
|
|
132
170
|
}
|
|
133
171
|
}
|
|
134
172
|
|
|
@@ -441,6 +479,9 @@ class AudioStreamManager: NSObject {
|
|
|
441
479
|
/// - intervalMilliseconds: The interval in milliseconds for emitting audio data.
|
|
442
480
|
/// - Returns: A StartRecordingResult object if recording starts successfully, or nil otherwise.
|
|
443
481
|
func startRecording(settings: RecordingSettings, intervalMilliseconds: Int) -> StartRecordingResult? {
|
|
482
|
+
// Update auto-resume preference from settings
|
|
483
|
+
autoResumeAfterInterruption = settings.autoResumeAfterInterruption
|
|
484
|
+
|
|
444
485
|
guard !isRecording else {
|
|
445
486
|
Logger.debug("Debug: Recording is already in progress.")
|
|
446
487
|
return nil
|
|
@@ -11,4 +11,5 @@ protocol AudioStreamManagerDelegate: AnyObject {
|
|
|
11
11
|
func audioStreamManager(_ manager: AudioStreamManager, didPauseRecording pauseTime: Date)
|
|
12
12
|
func audioStreamManager(_ manager: AudioStreamManager, didResumeRecording resumeTime: Date)
|
|
13
13
|
func audioStreamManager(_ manager: AudioStreamManager, didUpdateNotificationState isPaused: Bool)
|
|
14
|
+
func audioStreamManager(_ manager: AudioStreamManager, didReceiveInterruption info: [String: Any])
|
|
14
15
|
}
|
|
@@ -3,6 +3,9 @@ import AVFoundation
|
|
|
3
3
|
|
|
4
4
|
let audioDataEvent: String = "AudioData"
|
|
5
5
|
let audioAnalysisEvent: String = "AudioAnalysis"
|
|
6
|
+
let recordingStateChangedEvent: String = "recordingStateChanged"
|
|
7
|
+
let notificationStateChangedEvent: String = "notificationStateChanged"
|
|
8
|
+
let recordingInterruptedEvent: String = "onRecordingInterrupted"
|
|
6
9
|
|
|
7
10
|
public class ExpoAudioStreamModule: Module, AudioStreamManagerDelegate {
|
|
8
11
|
private var streamManager = AudioStreamManager()
|
|
@@ -13,7 +16,13 @@ public class ExpoAudioStreamModule: Module, AudioStreamManagerDelegate {
|
|
|
13
16
|
Name("ExpoAudioStream")
|
|
14
17
|
|
|
15
18
|
// Defines event names that the module can send to JavaScript.
|
|
16
|
-
Events([
|
|
19
|
+
Events([
|
|
20
|
+
audioDataEvent,
|
|
21
|
+
audioAnalysisEvent,
|
|
22
|
+
recordingStateChangedEvent,
|
|
23
|
+
notificationStateChangedEvent,
|
|
24
|
+
recordingInterruptedEvent
|
|
25
|
+
])
|
|
17
26
|
|
|
18
27
|
OnCreate {
|
|
19
28
|
print("Setting streamManager delegate")
|
|
@@ -299,21 +308,21 @@ public class ExpoAudioStreamModule: Module, AudioStreamManagerDelegate {
|
|
|
299
308
|
}
|
|
300
309
|
|
|
301
310
|
func audioStreamManager(_ manager: AudioStreamManager, didPauseRecording pauseTime: Date) {
|
|
302
|
-
sendEvent(
|
|
311
|
+
sendEvent(recordingStateChangedEvent, [
|
|
303
312
|
"state": "paused",
|
|
304
313
|
"timestamp": pauseTime.timeIntervalSince1970 * 1000
|
|
305
314
|
])
|
|
306
315
|
}
|
|
307
316
|
|
|
308
317
|
func audioStreamManager(_ manager: AudioStreamManager, didResumeRecording resumeTime: Date) {
|
|
309
|
-
sendEvent(
|
|
318
|
+
sendEvent(recordingStateChangedEvent, [
|
|
310
319
|
"state": "recording",
|
|
311
320
|
"timestamp": resumeTime.timeIntervalSince1970 * 1000
|
|
312
321
|
])
|
|
313
322
|
}
|
|
314
323
|
|
|
315
324
|
func audioStreamManager(_ manager: AudioStreamManager, didUpdateNotificationState isPaused: Bool) {
|
|
316
|
-
sendEvent(
|
|
325
|
+
sendEvent(notificationStateChangedEvent, [
|
|
317
326
|
"isPaused": isPaused
|
|
318
327
|
])
|
|
319
328
|
}
|
|
@@ -447,4 +456,7 @@ public class ExpoAudioStreamModule: Module, AudioStreamManagerDelegate {
|
|
|
447
456
|
}
|
|
448
457
|
}
|
|
449
458
|
|
|
459
|
+
func audioStreamManager(_ manager: AudioStreamManager, didReceiveInterruption info: [String: Any]) {
|
|
460
|
+
sendEvent(recordingInterruptedEvent, info)
|
|
461
|
+
}
|
|
450
462
|
}
|
|
@@ -98,6 +98,8 @@ struct RecordingSettings {
|
|
|
98
98
|
let compressedFormat: String // "aac" or "opus"
|
|
99
99
|
let compressedBitRate: Int
|
|
100
100
|
|
|
101
|
+
let autoResumeAfterInterruption: Bool
|
|
102
|
+
|
|
101
103
|
static func fromDictionary(_ dict: [String: Any]) -> Result<RecordingSettings, Error> {
|
|
102
104
|
// Extract compression settings
|
|
103
105
|
let compression = dict["compression"] as? [String: Any]
|
|
@@ -122,7 +124,8 @@ struct RecordingSettings {
|
|
|
122
124
|
desiredSampleRate: dict["desiredSampleRate"] as? Double ?? 44100.0,
|
|
123
125
|
enableCompressedOutput: enableCompressedOutput,
|
|
124
126
|
compressedFormat: compressedFormat,
|
|
125
|
-
compressedBitRate: compressedBitRate
|
|
127
|
+
compressedBitRate: compressedBitRate,
|
|
128
|
+
autoResumeAfterInterruption: dict["autoResumeAfterInterruption"] as? Bool ?? false
|
|
126
129
|
)
|
|
127
130
|
|
|
128
131
|
// Parse core settings
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@siteed/expo-audio-stream",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"description": "stream audio crossplatform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "build/index.js",
|
|
@@ -104,6 +104,7 @@
|
|
|
104
104
|
"registry": "https://registry.npmjs.org"
|
|
105
105
|
},
|
|
106
106
|
"dependencies": {
|
|
107
|
+
"@siteed/design-system": "^0.35.1",
|
|
107
108
|
"expo-modules-core": "^2.1.1"
|
|
108
109
|
}
|
|
109
110
|
}
|
package/plugin/build/index.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
-
|
|
2
|
+
interface AudioStreamPluginOptions {
|
|
3
|
+
enablePhoneStateHandling?: boolean;
|
|
4
|
+
enableNotifications?: boolean;
|
|
5
|
+
enableBackgroundAudio?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare const withRecordingPermission: ConfigPlugin<AudioStreamPluginOptions>;
|
|
3
8
|
export default withRecordingPermission;
|
package/plugin/build/index.js
CHANGED
|
@@ -9,68 +9,73 @@ function debugLog(message, ...args) {
|
|
|
9
9
|
console.log(`${LOG_PREFIX} ${message}`, ...args);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
const withRecordingPermission = (config) => {
|
|
13
|
-
|
|
12
|
+
const withRecordingPermission = (config, props) => {
|
|
13
|
+
// Default options if pluginOptions is undefined (void)
|
|
14
|
+
const options = {
|
|
15
|
+
enablePhoneStateHandling: true,
|
|
16
|
+
enableNotifications: true,
|
|
17
|
+
enableBackgroundAudio: true,
|
|
18
|
+
...(props || {}),
|
|
19
|
+
};
|
|
20
|
+
const { enablePhoneStateHandling, enableNotifications, enableBackgroundAudio, } = options;
|
|
21
|
+
debugLog('📱 Configuring Recording Permissions Plugin...', options);
|
|
14
22
|
// iOS Configuration
|
|
15
23
|
config = (0, config_plugins_1.withInfoPlist)(config, (config) => {
|
|
16
|
-
|
|
17
|
-
// Existing microphone permission
|
|
24
|
+
// Base microphone permission (always required)
|
|
18
25
|
config.modResults['NSMicrophoneUsageDescription'] =
|
|
19
26
|
config.modResults['NSMicrophoneUsageDescription'] ||
|
|
20
27
|
MICROPHONE_USAGE;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
// Background modes
|
|
28
|
+
if (enableNotifications) {
|
|
29
|
+
config.modResults['NSUserNotificationsUsageDescription'] =
|
|
30
|
+
NOTIFICATION_USAGE;
|
|
31
|
+
config.modResults['NSUserNotificationAlertStyle'] = 'alert';
|
|
32
|
+
}
|
|
27
33
|
const existingBackgroundModes = config.modResults.UIBackgroundModes || [];
|
|
28
|
-
if (
|
|
34
|
+
if (enableBackgroundAudio &&
|
|
35
|
+
!existingBackgroundModes.includes('audio')) {
|
|
29
36
|
existingBackgroundModes.push('audio');
|
|
30
37
|
}
|
|
31
|
-
if (
|
|
32
|
-
existingBackgroundModes.
|
|
38
|
+
if (enablePhoneStateHandling) {
|
|
39
|
+
if (!existingBackgroundModes.includes('voip')) {
|
|
40
|
+
existingBackgroundModes.push('voip');
|
|
41
|
+
}
|
|
42
|
+
const existingCapabilities = (config.modResults
|
|
43
|
+
.UIRequiredDeviceCapabilities || []);
|
|
44
|
+
if (!existingCapabilities.includes('telephony')) {
|
|
45
|
+
existingCapabilities.push('telephony');
|
|
46
|
+
}
|
|
47
|
+
config.modResults.UIRequiredDeviceCapabilities =
|
|
48
|
+
existingCapabilities;
|
|
33
49
|
}
|
|
34
50
|
config.modResults.UIBackgroundModes = existingBackgroundModes;
|
|
35
|
-
debugLog('iOS Background Modes:', config.modResults.UIBackgroundModes);
|
|
36
51
|
return config;
|
|
37
52
|
});
|
|
38
53
|
// Android Configuration
|
|
39
54
|
config = (0, config_plugins_1.withAndroidManifest)(config, (config) => {
|
|
40
|
-
|
|
41
|
-
const androidManifest = config.modResults;
|
|
42
|
-
if (!androidManifest.manifest) {
|
|
43
|
-
console.error(`${LOG_PREFIX} ❌ Android Manifest is null - plugin cannot continue`);
|
|
44
|
-
return config;
|
|
45
|
-
}
|
|
46
|
-
// Add xmlns:android attribute to manifest
|
|
47
|
-
androidManifest.manifest.$ = {
|
|
48
|
-
...androidManifest.manifest.$,
|
|
49
|
-
'xmlns:android': 'http://schemas.android.com/apk/res/android',
|
|
50
|
-
};
|
|
51
|
-
// Ensure permissions array exists
|
|
52
|
-
if (!androidManifest.manifest['uses-permission']) {
|
|
53
|
-
androidManifest.manifest['uses-permission'] = [];
|
|
54
|
-
}
|
|
55
|
-
const { addPermission } = config_plugins_1.AndroidConfig.Permissions;
|
|
56
|
-
debugLog('📋 Existing Android permissions:', androidManifest.manifest['uses-permission']?.map(p => p.$?.['android:name']) || []);
|
|
57
|
-
const permissionsToAdd = [
|
|
55
|
+
const basePermissions = [
|
|
58
56
|
'android.permission.RECORD_AUDIO',
|
|
59
|
-
'android.permission.FOREGROUND_SERVICE',
|
|
60
|
-
'android.permission.FOREGROUND_SERVICE_MICROPHONE',
|
|
61
57
|
'android.permission.WAKE_LOCK',
|
|
62
|
-
'android.permission.POST_NOTIFICATIONS',
|
|
63
58
|
];
|
|
59
|
+
const optionalPermissions = [
|
|
60
|
+
enableNotifications && 'android.permission.POST_NOTIFICATIONS',
|
|
61
|
+
enablePhoneStateHandling && 'android.permission.READ_PHONE_STATE',
|
|
62
|
+
enableBackgroundAudio && 'android.permission.FOREGROUND_SERVICE',
|
|
63
|
+
enableBackgroundAudio &&
|
|
64
|
+
'android.permission.FOREGROUND_SERVICE_MICROPHONE',
|
|
65
|
+
].filter(Boolean);
|
|
66
|
+
const permissionsToAdd = [...basePermissions, ...optionalPermissions];
|
|
67
|
+
debugLog('📋 Existing Android permissions:', config.modResults.manifest['uses-permission']?.map((p) => p.$?.['android:name']) || []);
|
|
64
68
|
debugLog('➕ Adding Android permissions:', permissionsToAdd);
|
|
69
|
+
const { addPermission } = config_plugins_1.AndroidConfig.Permissions;
|
|
65
70
|
// Add each permission only if it doesn't exist
|
|
66
71
|
permissionsToAdd.forEach((permission) => {
|
|
67
|
-
const existingPermission =
|
|
72
|
+
const existingPermission = config.modResults.manifest['uses-permission']?.find((p) => p.$?.['android:name'] === permission);
|
|
68
73
|
if (!existingPermission) {
|
|
69
|
-
addPermission(
|
|
74
|
+
addPermission(config.modResults, permission);
|
|
70
75
|
}
|
|
71
76
|
});
|
|
72
77
|
// Get the main application node
|
|
73
|
-
const mainApplication =
|
|
78
|
+
const mainApplication = config.modResults.manifest.application?.[0];
|
|
74
79
|
if (mainApplication) {
|
|
75
80
|
debugLog('📱 Configuring Android application components...');
|
|
76
81
|
// Add RecordingActionReceiver
|