Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .DS_Store
Binary file not shown.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,8 @@
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
},
"editor.codeActionsOnSave": {

},
}
14 changes: 11 additions & 3 deletions app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
bundleIdentifier: Env.BUNDLE_ID,
requireFullScreen: true,
infoPlist: {
UIBackgroundModes: ['remote-notification'],
UIBackgroundModes: ['remote-notification', 'audio'],
ITSAppUsesNonExemptEncryption: false,
},
},
Expand All @@ -40,7 +40,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
softwareKeyboardLayoutMode: 'pan',
package: Env.PACKAGE,
googleServicesFile: 'google-services.json',
permissions: ['WAKE_LOCK', 'RECORD_AUDIO', 'FOREGROUND_SERVICE_MICROPHONE'],
permissions: ['WAKE_LOCK', 'RECORD_AUDIO', 'FOREGROUND_SERVICE_MICROPHONE', 'POST_NOTIFICATIONS', 'FOREGROUND_SERVICE', 'FOREGROUND_SERVICE_CONNECTED_DEVICE', 'FOREGROUND_SERVICE_MEDIA_PLAYBACK'],
},
web: {
favicon: './assets/favicon.png',
Expand Down Expand Up @@ -176,7 +176,14 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
[
'expo-asset',
{
assets: ['assets/mapping'],
assets: [
'assets/mapping',
'assets/audio/ui/space_notification1.mp3',
'assets/audio/ui/space_notification2.mp3',
'assets/audio/ui/positive_interface_beep.mp3',
'assets/audio/ui/software_interface_start.mp3',
'assets/audio/ui/software_interface_back.mp3',
],
},
],
[
Expand All @@ -201,6 +208,7 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
bluetoothAlwaysPermission: 'Allow Resgrid Unit to connect to bluetooth devices',
},
],
'expo-audio',
'@livekit/react-native-expo-plugin',
'@config-plugins/react-native-webrtc',
'./customGradle.plugin.js',
Expand Down
Binary file removed assets/audio/ui/Space_Notification1.mp3
Binary file not shown.
Binary file removed assets/audio/ui/Space_Notification1.ogg
Binary file not shown.
Binary file removed assets/audio/ui/Space_Notification2.mp3
Binary file not shown.
Binary file removed assets/audio/ui/Space_Notification2.ogg
Binary file not shown.
Binary file added assets/audio/ui/positive_interface_beep.mp3
Binary file not shown.
Binary file added assets/audio/ui/software_interface_back.mp3
Binary file not shown.
Binary file added assets/audio/ui/software_interface_start.mp3
Binary file not shown.
Binary file removed assets/audio/ui/space_notification1.ogg
Binary file not shown.
Binary file removed assets/audio/ui/space_notification2.ogg
Binary file not shown.
2 changes: 1 addition & 1 deletion customManifest.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const withForegroundService = (config) => {
mainApplication['service'].push({
$: {
'android:name': 'app.notifee.core.ForegroundService',
'android:foregroundServiceType': 'microphone',
'android:foregroundServiceType': 'microphone|mediaPlayback|connectedDevice',
'tools:replace': 'android:foregroundServiceType',
},
});
Expand Down
92 changes: 92 additions & 0 deletions docs/audio-service-direct-playback.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Audio Service Implementation

## Overview
The audio service has been updated to play connection and disconnection sounds directly in the application using `expo-audio` instead of the notification system.

## Changes Made

### 1. Dependencies
- **Added**: `expo-audio` for direct audio playback
- **Removed**: Dependency on `expo-notifications` for audio playback

### 2. Audio Files
The service now uses the existing audio files located in:
- **Connection Sound**: `assets/audio/ui/space_notification1.mp3`
- **Disconnection Sound**: `assets/audio/ui/space_notification2.mp3`

### 3. Implementation Details

#### Audio Initialization
```typescript
private async initializeAudio(): Promise<void> {
// Configure audio mode for playback
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
staysActiveInBackground: false,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
playThroughEarpieceAndroid: false,
});

// Pre-load audio files
await this.loadAudioFiles();
}
```

#### Sound Loading
- Audio files are preloaded during service initialization
- Both iOS and Android use the same `.mp3` files
- Sounds are stored as class properties for efficient reuse

#### Sound Playback
- Uses `sound.replayAsync()` for direct playback
- Includes proper error handling and logging
- Plays sounds immediately without notification system overhead

#### Resource Management
- Proper cleanup in the `cleanup()` method
- Unloads audio files to prevent memory leaks
- Null checks to prevent errors during cleanup

### 4. Benefits

1. **Direct Playback**: Sounds play immediately without notification system delays
2. **Better Control**: More control over audio playback behavior
3. **Reduced Dependencies**: No longer depends on notification permissions for audio
4. **Consistent Behavior**: Same audio behavior across iOS and Android
5. **Resource Efficient**: Preloaded sounds for faster playback

### 5. Usage

The API remains the same:

```typescript
// Play connection sound
await audioService.playConnectionSound();

// Play disconnection sound
await audioService.playDisconnectionSound();

// Cleanup when done
await audioService.cleanup();
```

### 6. Error Handling

The service includes comprehensive error handling:
- Initialization errors are logged but don't crash the app
- Sound loading errors are handled gracefully
- Playback errors are logged with context
- Cleanup errors are handled to prevent resource leaks

### 7. Testing

The service includes unit tests that verify:
- Proper initialization
- Sound playback functionality
- Error handling
- Resource cleanup

## Migration Notes

The change is backward compatible - existing code using `playConnectionSound()` and `playDisconnectionSound()` will continue to work without modification, but now with improved performance and reliability.
2 changes: 1 addition & 1 deletion expo-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/// <reference types="expo/types" />

// NOTE: This file should not be edited and should be in your git ignore
// NOTE: This file should not be edited and should be in your git ignore

Check warning on line 3 in expo-env.d.ts

View workflow job for this annotation

GitHub Actions / test

Insert `⏎`
28 changes: 28 additions & 0 deletions jest-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,31 @@ import '@testing-library/react-native/extend-expect';
global.window = {};
// @ts-ignore
global.window = global;

// Mock expo-audio globally
jest.mock('expo-audio', () => ({
createAudioPlayer: jest.fn(() => ({
play: jest.fn(),
pause: jest.fn(),
remove: jest.fn(),
replace: jest.fn(),
seekTo: jest.fn(),
playing: false,
paused: false,
isLoaded: true,
duration: 0,
currentTime: 0,
volume: 1,
muted: false,
loop: false,
playbackRate: 1,
id: 1,
isAudioSamplingSupported: false,
isBuffering: false,
shouldCorrectPitch: false,
})),
useAudioPlayer: jest.fn(),
useAudioPlayerStatus: jest.fn(),
setAudioModeAsync: jest.fn(),
setIsAudioActiveAsync: jest.fn(),
}));
5 changes: 3 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ module.exports = {
preset: 'jest-expo',
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
testPathIgnorePatterns: ['<rootDir>/node_modules/', '\\.\\._.*'],
collectCoverage: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/coverage/**', '!**/node_modules/**', '!**/babel.config.js', '!**/jest.setup.js', '!**/docs/**', '!**/cli/**', '!**/ios/**', '!**/android/**'],
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/coverage/**', '!**/node_modules/**', '!**/babel.config.js', '!**/jest.setup.js', '!**/docs/**', '!**/cli/**', '!**/ios/**', '!**/android/**', '!**/_*', '!**/._*'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleDirectories: ['node_modules', '<rootDir>/'],
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg|@legendapp/motion|@gluestack-ui/.*))',
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg|@legendapp/motion|@gluestack-ui|expo-audio/.*))',
],
coverageReporters: ['json-summary', ['text', { file: 'coverage.txt' }], 'cobertura'],
reporters: [
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
"dependencies": {
"@config-plugins/react-native-webrtc": "~12.0.0",
"@dev-plugins/react-query": "^0.3.1",
"@dev-plugins/react-query": "~0.2.0",
"@expo/config-plugins": "~9.0.0",
"@expo/html-elements": "~0.10.1",
"@expo/metro-runtime": "~4.0.0",
Expand Down Expand Up @@ -95,6 +95,7 @@
"expo": "~52.0.46",
"expo-application": "~6.0.2",
"expo-asset": "~11.0.5",
"expo-audio": "~0.3.5",
"expo-build-properties": "~0.13.3",
"expo-constants": "~17.0.8",
"expo-dev-client": "~5.0.20",
Expand Down
Binary file modified src/.DS_Store
Binary file not shown.
Loading
Loading