# Real-World Usage Example: Ionic1/AngularJS Audio Recording

This document provides a complete, real-world example of how to integrate the `cordova-plugin-audio-recorder` plugin into an Ionic1/AngularJS application, based on actual implementation patterns.

## 📱 Controller Structure

### AngularJS Controller Setup

```javascript
angular.module('eyes-and-ear.controller', [])
    .controller('RecordInsightsCtrl', function ($scope, $sce, $timeout, eandeHttpService, $ionicModal, $ionicHistory, commonService, $state, $ionicLoading, $interval, $ionicPopup) {
        
        // Initialize data object
        $scope.data = {};
        $scope.data.pageLoader = false;
        $scope.data.recording = false;
        $scope.data.mediaRecorder = null;
        $scope.data.audioChunks = [];
        $scope.data.audioFile = null;
        $scope.data.recordingTime = Number($state.params.audioDuration); // Dynamic duration from state
        $scope.data.recordingTimer = null;
        $scope.data.isPaused = false;
        $scope.data.isCanceling = false; // Flag to track if recording is being canceled
        $scope.data.isIOSRecording = false; // Flag to track if using iOS recording

        // Audio playback variables
        $scope.data.time = 0;
        $scope.data.isAudio = false;
        $scope.data.audio = null;
        $scope.data.isRunning = false;
        $scope.data.interval = null;
        $scope.data.audioDuration = 0;

        // Get state parameters
        $scope.data.path = $state.params.path;
        $scope.data.language = $state.params.language;
        $scope.data.category = $state.params.category;
        $scope.data.categoryvalue = $state.params.categoryvalue;
    });
```

## 🎯 Platform Detection and Recording Strategy

### Main Recording Entry Point

```javascript
$scope.checkAudioPemision = function () {
    $scope.data.recordingTime = Number($state.params.audioDuration);

    // Check if we're on iOS
    if (device.platform === 'iOS' || device.platform === 'ios') {
        console.log('iOS platform detected, using audio recorder plugin');
        $scope.checkIOSAudioPermission();
    } else {
        console.log('Android platform detected, using MediaRecorder API');
        $scope.checkAndroidAudioPermission();
    }
};
```

## 🍎 iOS-Specific Implementation

### iOS Permission Handling

```javascript
$scope.checkIOSAudioPermission = function () {
    console.log('Checking iOS audio permission...');

    if (!navigator.audioRecorder) {
        console.error('Audio recorder plugin not available');
        alert('Audio recording plugin not available on this device.');
        return;
    }

    // Check permission using the plugin
    navigator.audioRecorder.checkPermission(
        function (permission) {
            console.log('iOS permission status:', permission);
            if (permission === 'granted') {
                $scope.proceedWithIOSRecording();
            } else {
                // Request permission
                navigator.audioRecorder.requestPermission(
                    function (result) {
                        console.log('iOS permission granted:', result);
                        $scope.proceedWithIOSRecording();
                    },
                    function (error) {
                        console.error('iOS permission denied:', error);
                        alert('Audio permission is required to record. Please allow access in your app settings.');
                    }
                );
            }
        },
        function (error) {
            console.error('iOS permission check failed:', error);
            // Fallback to direct recording attempt
            $scope.proceedWithIOSRecording();
        }
    );
};
```

### iOS Recording Start

```javascript
$scope.startRecordingIOS = function () {
    console.log('Starting iOS recording...');

    // Check if the audio recorder plugin is available
    if (!navigator.audioRecorder) {
        console.error('Audio recorder plugin not available');
        alert('Audio recording plugin not available on this device.');
        return;
    }

    // Configure recording options for continuous recording
    // Use M4A format for better iOS compatibility
    var recordingOptions = {
        quality: navigator.audioRecorder.Quality.HIGH,
        format: navigator.audioRecorder.Format.M4A, // Use M4A instead of WAV
        sampleRate: 44100,
        channels: 1,
        fileName: 'Audio_' + Date.now() // Remove the .m4a extension, let plugin handle it
    };

    console.log('iOS recording options:', recordingOptions);

    // Start continuous recording using the installed plugin
    navigator.audioRecorder.startRecording(
        function (result) {
            console.log('iOS recording started successfully:', result);

            // Set recording state
            $scope.data.isIOSRecording = true;
            $scope.data.recording = true;
            $scope.data.recordingStartTime = Date.now();

            // Start the timer
            $scope.startTimer();
            $scope.$apply();
        },
        function (error) {
            console.error('Failed to start iOS recording:', error);
            alert('Failed to start recording: ' + error);
        },
        recordingOptions
    );
};
```

### iOS Recording Stop

```javascript
$scope.stopRecordingIOS = function () {
    console.log("Stopping iOS recording...");

    if (!navigator.audioRecorder || !$scope.data.isIOSRecording) {
        console.log("No active recording to stop");
        return;
    }

    // Stop the recording
    navigator.audioRecorder.stopRecording(
        function (result) {
            console.log("iOS recording stopped successfully:", result);

            // Process the recorded audio
            if (result && result.audioData) {
                $scope.data.audioFileName = result.fileName || "Audio_" + Date.now() + ".m4a";
                $scope.data.audioFileSize = result.fileSize || 0;
                $scope.data.audioDuration = result.duration || 0;

                // Convert base64 to blob for API transmission
                var byteCharacters = atob(result.audioData);
                var byteNumbers = new Array(byteCharacters.length);
                for (var i = 0; i < byteCharacters.length; i++) {
                    byteNumbers[i] = byteCharacters.charCodeAt(i);
                }
                var byteArray = new Uint8Array(byteNumbers);
                $scope.data.wavBlob = new Blob([byteArray], {
                    type: result.mimeType || "audio/mp4",
                });

                // Create audio URL for playback
                $scope.data.audioFile = $sce.trustAsResourceUrl(result.audioBlob);
                $scope.data.audio = new Audio($scope.data.audioFile);

                // Set up audio playback events
                $scope.data.audio.onloadedmetadata = function () {
                    $scope.data.audioDuration = $scope.data.audio.duration;
                    $scope.$apply();
                };

                $scope.data.audio.ontimeupdate = function () {
                    $scope.data.time = Math.floor($scope.data.audio.currentTime);
                    $scope.$apply();
                };

                $scope.data.audio.onended = function () {
                    $scope.data.isAudio = false;
                    $scope.$apply();
                };

                $scope.data.isIOSRecording = false;
                $scope.data.recording = false;
                $scope.stopTimer();
                $scope.$apply();

                // Show save confirmation popup
                $ionicPopup.show({
                    title: "Save Recording",
                    template: "Are you sure, you want to save the recording?",
                    buttons: [
                        {
                            text: "No",
                            type: "button-dark",
                            onTap: function (e) {
                                $state.go("eyes-and-ear");
                            },
                        },
                        {
                            text: "Yes",
                            type: "button-positive",
                            onTap: function () {
                                $scope.saveRecording();
                            },
                        },
                    ],
                });
            } else {
                console.error("No audio data received from recording");
                alert("Failed to process recording: No audio data received");
            }
        },
        function (error) {
            console.error("Failed to stop iOS recording:", error);
            alert("Failed to stop recording: " + error);
        }
    );
};
```

## ⏱️ Timer Management

### Timer Implementation

```javascript
$scope.startTimer = function () {
    if ($scope.data.recordingTimer) clearInterval($scope.data.recordingTimer);
    $scope.data.recordingTimer = setInterval(function () {
        $scope.data.recordingTime -= 0.1;
        if ($scope.data.recordingTime <= 0) {
            $scope.data.recordingTime = 0;
            $scope.stopTimer(); // Stop the timer immediately
            if ($scope.data.recording) { // Only call if still recording
                if ($scope.data.isIOSRecording) {
                    $scope.stopRecordingIOS();
                } else {
                    $scope.stopRecording();
                }
            }
            return;
        }
        $scope.$apply();
    }, 100);
};

$scope.stopTimer = function () {
    if ($scope.data.recordingTimer) {
        clearInterval($scope.data.recordingTimer);
        $scope.data.recordingTimer = null;
    }
};
```

## 🧹 Cleanup and Resource Management

### Controller Destroy Cleanup

```javascript
// Clean up when controller is destroyed
$scope.$on('$destroy', function () {
    $scope.stopTimer();

    // Stop iOS recording if active
    if ($scope.data.isIOSRecording && navigator.audioRecorder) {
        try {
            // For recordWithInterval, we can only cancel by setting the flag
            // The recording will automatically stop after the duration
            $scope.data.isCanceling = true;
            console.log('iOS recording will be canceled on destroy');
        } catch (error) {
            console.error('Error canceling iOS recording on destroy:', error);
        }
    }

    // Stop Android recording if active
    if ($scope.data.mediaRecorder && $scope.data.recording) {
        try {
            $scope.data.mediaRecorder.stop();
        } catch (error) {
            console.error('Error stopping recording on destroy:', error);
        }
    }

    // Stop all media streams
    if ($scope.data.mediaStream) {
        $scope.data.mediaStream.getTracks().forEach(function (track) {
            track.stop();
        });
        $scope.data.mediaStream = null;
    }
});
```

## 🎮 User Interface Integration

### Recording Controls

```javascript
// Platform-specific recording function selection
$scope.startRecordingPlatform = function () {
    console.log('Platform detection for recording...');
    console.log('Device platform:', device.platform);

    // Check if we're on iOS
    if (device.platform === 'iOS' || device.platform === 'ios') {
        console.log('Using iOS audio recorder plugin');
        $scope.startRecordingIOS();
    } else {
        console.log('Using MediaRecorder API');
        $scope.startRecording();
    }
};

$scope.stopRecordingPlatform = function () {
    console.log('Stopping recording based on platform...');

    if ($scope.data.isIOSRecording) {
        $scope.stopRecordingIOS();
    } else {
        $scope.stopRecording();
    }
};

$scope.cancelRecordingPlatform = function () {
    console.log('Canceling recording based on platform...');

    if ($scope.data.isIOSRecording) {
        $scope.cancelRecordingIOS();
    } else {
        $scope.cancelRecording();
    }
};
```

### Navigation and State Management

```javascript
$scope.goBack = function () {
    $scope.data.isCanceling = true;

    if ($scope.data.isIOSRecording) {
        // For iOS, we need to stop the recording first
        $scope.stopRecordingIOS();
    } else if ($scope.data.mediaRecorder && $scope.data.recording) {
        $scope.data.mediaRecorder.stop();
        $scope.data.recording = false;
        $scope.stopTimer();

        // Stop all tracks in the stream
        if ($scope.data.stream) {
            $scope.data.stream.getTracks().forEach(function (track) {
                track.stop();
            });
        }
    }
    $ionicHistory.goBack();
};

$scope.cancelRecording = function () {
    console.log('Canceling recording...');
    $scope.data.isCanceling = true;

    if ($scope.data.isIOSRecording) {
        // For iOS, we need to stop the recording first
        $scope.data.recording = false;
        $scope.stopTimer();
    } else if ($scope.data.mediaRecorder && $scope.data.recording) {
        $scope.data.mediaRecorder.stop();
        $scope.data.recording = false;
        $scope.stopTimer();

        // Stop all tracks in the stream
        if ($scope.data.stream) {
            $scope.data.stream.getTracks().forEach(function (track) {
                track.stop();
            });
        }
    }

    $state.go('eyes-and-ear');
};
```

## 📤 Data Processing and API Integration

### Audio Data Processing

```javascript
$scope.saveRecording = function () {
    console.log("saveRecording");
    if ($scope.data.audioFile) {
        $scope.data.pageLoader = true;
        $scope.data.textGenarateMessage = "Uploading audio..."

        console.log("$scope.data.wavBlob : ", $scope.data.wavBlob);

        const data = {
            InsightId: '',
            Language: $scope.data.language,
            InsightCategory: $scope.data.category,
            FileName: $scope.data.audioFileName,
            FileData: $scope.data.wavBlob,
            IsUpdate: false
        }

        console.log("data", data)
        eandeHttpService.UploadAudio(data).then(function (data) {
            // Handle API response
            if (typeof data == 'object' && data != null) {
                if (data.UserValid.ValidUserYN == 'Y') {
                    if (data.noOfRecord != undefined && data.noOfRecord != '0') {
                        $scope.data.pageLoader = false;
                        // Process successful upload
                        $scope.GetAudioTranscript(data.objData.insight_id, data.objData.request_id, data.objData.transcript_id)
                    } else {
                        $scope.data.errorMessage = data.msg
                        $scope.errorRecordPopup.show()
                    }
                }
            } else {
                $scope.errorRecordPopup.show()
            }
            $scope.data.pageLoader = false;
        }, function (err) {
            $scope.data.errorMessage = err
            $scope.errorRecordPopup.show()
            $scope.data.pageLoader = false;
        });
    } else {
        $ionicLoading.show({
            template: 'No recording to save.',
            duration: 2000
        });
    }
}
```

## 🔧 Key Implementation Patterns

### 1. **Platform Detection**
- Always check `device.platform` to determine iOS vs Android
- Use different recording strategies for each platform

### 2. **Plugin Availability Check**
- Always verify `navigator.audioRecorder` exists before using
- Provide fallback behavior when plugin is not available

### 3. **State Management**
- Use flags like `isIOSRecording` to track recording state
- Maintain separate state for iOS vs Android recording

### 4. **Timer Integration**
- Use timers to control recording duration
- Automatically stop recording when timer expires

### 5. **Resource Cleanup**
- Always clean up resources in `$destroy` event
- Stop timers, recordings, and media streams

### 6. **Error Handling**
- Provide user-friendly error messages
- Handle permission denials gracefully

### 7. **Data Processing**
- Convert base64 audio data to Blob for API transmission
- Set up audio playback for recorded content

## 📋 Best Practices

1. **Always check plugin availability** before using
2. **Use platform detection** to choose appropriate recording method
3. **Implement proper cleanup** in controller destroy
4. **Handle permissions** gracefully with user feedback
5. **Use timers** to control recording duration
6. **Process audio data** properly for API transmission
7. **Provide fallback behavior** when plugin is not available
8. **Maintain separate state** for different recording methods

This implementation provides a robust, production-ready audio recording solution that works seamlessly across iOS and Android platforms while maintaining compatibility with Ionic1/AngularJS applications.
