@independo/capacitor-voice-recorder 6.0.14-dev.2 → 7.0.0-dev.1
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/IndependoCapacitorVoiceRecorder.podspec +1 -1
- package/README.md +1 -0
- package/android/build.gradle +9 -9
- package/ios/Plugin/CurrentRecordingStatus.swift +2 -2
- package/ios/Plugin/CustomMediaRecorder.swift +18 -18
- package/ios/Plugin/Messages.swift +2 -3
- package/ios/Plugin/RecordData.swift +7 -7
- package/ios/Plugin/ResponseGenerator.swift +12 -12
- package/ios/Plugin/VoiceRecorder.swift +29 -30
- package/package.json +10 -14
|
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
13
|
s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
-
s.ios.deployment_target = '
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
15
|
s.dependency 'Capacitor'
|
|
16
16
|
s.swift_version = '5.1'
|
|
17
17
|
end
|
package/README.md
CHANGED
package/android/build.gradle
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
ext {
|
|
2
2
|
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
-
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.
|
|
4
|
-
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1
|
|
5
|
-
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
@@ -11,7 +11,7 @@ buildscript {
|
|
|
11
11
|
mavenCentral()
|
|
12
12
|
}
|
|
13
13
|
dependencies {
|
|
14
|
-
classpath 'com.android.tools.build:gradle:8.2
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -19,10 +19,10 @@ apply plugin: 'com.android.library'
|
|
|
19
19
|
|
|
20
20
|
android {
|
|
21
21
|
namespace "com.tchvu3.capacitorvoicerecorder"
|
|
22
|
-
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion :
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
23
|
defaultConfig {
|
|
24
|
-
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion :
|
|
25
|
-
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion :
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
26
26
|
versionCode 1
|
|
27
27
|
versionName "1.0"
|
|
28
28
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
@@ -37,8 +37,8 @@ android {
|
|
|
37
37
|
abortOnError false
|
|
38
38
|
}
|
|
39
39
|
compileOptions {
|
|
40
|
-
sourceCompatibility JavaVersion.
|
|
41
|
-
targetCompatibility JavaVersion.
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -2,25 +2,25 @@ import Foundation
|
|
|
2
2
|
import AVFoundation
|
|
3
3
|
|
|
4
4
|
class CustomMediaRecorder {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
private var recordingSession: AVAudioSession!
|
|
7
7
|
private var audioRecorder: AVAudioRecorder!
|
|
8
8
|
private var audioFilePath: URL!
|
|
9
9
|
private var originalRecordingSessionCategory: AVAudioSession.Category!
|
|
10
10
|
private var status = CurrentRecordingStatus.NONE
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
private let settings = [
|
|
13
13
|
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
|
|
14
14
|
AVSampleRateKey: 44100,
|
|
15
15
|
AVNumberOfChannelsKey: 1,
|
|
16
16
|
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
|
|
17
17
|
]
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
private func getDirectoryToSaveAudioFile() -> URL {
|
|
20
20
|
return URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
func startRecording() -> Bool {
|
|
24
24
|
do {
|
|
25
25
|
recordingSession = AVAudioSession.sharedInstance()
|
|
26
26
|
originalRecordingSessionCategory = recordingSession.category
|
|
@@ -35,8 +35,8 @@ class CustomMediaRecorder {
|
|
|
35
35
|
return false
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
func stopRecording() {
|
|
40
40
|
do {
|
|
41
41
|
audioRecorder.stop()
|
|
42
42
|
try recordingSession.setActive(false)
|
|
@@ -47,13 +47,13 @@ class CustomMediaRecorder {
|
|
|
47
47
|
status = CurrentRecordingStatus.NONE
|
|
48
48
|
} catch {}
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
|
|
51
|
+
func getOutputFile() -> URL {
|
|
52
52
|
return audioFilePath
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if
|
|
54
|
+
|
|
55
|
+
func pauseRecording() -> Bool {
|
|
56
|
+
if status == CurrentRecordingStatus.RECORDING {
|
|
57
57
|
audioRecorder.pause()
|
|
58
58
|
status = CurrentRecordingStatus.PAUSED
|
|
59
59
|
return true
|
|
@@ -61,9 +61,9 @@ class CustomMediaRecorder {
|
|
|
61
61
|
return false
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if
|
|
64
|
+
|
|
65
|
+
func resumeRecording() -> Bool {
|
|
66
|
+
if status == CurrentRecordingStatus.PAUSED {
|
|
67
67
|
audioRecorder.record()
|
|
68
68
|
status = CurrentRecordingStatus.RECORDING
|
|
69
69
|
return true
|
|
@@ -71,9 +71,9 @@ class CustomMediaRecorder {
|
|
|
71
71
|
return false
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
|
|
75
|
+
func getCurrentStatus() -> CurrentRecordingStatus {
|
|
76
76
|
return status
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
struct Messages {
|
|
5
|
-
|
|
4
|
+
|
|
6
5
|
static let MISSING_PERMISSION = "MISSING_PERMISSION"
|
|
7
6
|
static let CANNOT_RECORD_ON_THIS_PHONE = "CANNOT_RECORD_ON_THIS_PHONE"
|
|
8
7
|
static let FAILED_TO_RECORD = "FAILED_TO_RECORD"
|
|
@@ -11,5 +10,5 @@ struct Messages {
|
|
|
11
10
|
static let EMPTY_RECORDING = "EMPTY_RECORDING"
|
|
12
11
|
static let ALREADY_RECORDING = "ALREADY_RECORDING"
|
|
13
12
|
static let MICROPHONE_BEING_USED = "MICROPHONE_BEING_USED"
|
|
14
|
-
|
|
13
|
+
|
|
15
14
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
struct RecordData {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
|
|
5
|
+
let recordDataBase64: String?
|
|
6
|
+
let mimeType: String
|
|
7
|
+
let msDuration: Int
|
|
8
|
+
|
|
9
|
+
func toDictionary() -> [String: Any] {
|
|
10
10
|
return [
|
|
11
11
|
"recordDataBase64": recordDataBase64 ?? "",
|
|
12
12
|
"msDuration": msDuration,
|
|
13
13
|
"mimeType": mimeType
|
|
14
14
|
]
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
|
|
3
3
|
struct ResponseGenerator {
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
private static let VALUE_RESPONSE_KEY = "value"
|
|
6
6
|
private static let STATUS_RESPONSE_KEY = "status"
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
|
|
8
|
+
static func fromBoolean(_ value: Bool) -> [String: Bool] {
|
|
9
9
|
return value ? successResponse() : failResponse()
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
static func successResponse() -> [String: Bool] {
|
|
13
13
|
return [VALUE_RESPONSE_KEY: true]
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
|
|
16
|
+
static func failResponse() -> [String: Bool] {
|
|
17
17
|
return [VALUE_RESPONSE_KEY: false]
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
|
|
20
|
+
static func dataResponse(_ data: Any) -> [String: Any] {
|
|
21
21
|
return [VALUE_RESPONSE_KEY: data]
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
static func statusResponse(_ data: CurrentRecordingStatus) -> [String: String] {
|
|
25
25
|
return [STATUS_RESPONSE_KEY: data.rawValue]
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
}
|
|
@@ -5,12 +5,12 @@ import Capacitor
|
|
|
5
5
|
@objc(VoiceRecorder)
|
|
6
6
|
public class VoiceRecorder: CAPPlugin {
|
|
7
7
|
|
|
8
|
-
private var customMediaRecorder: CustomMediaRecorder?
|
|
9
|
-
|
|
8
|
+
private var customMediaRecorder: CustomMediaRecorder?
|
|
9
|
+
|
|
10
10
|
@objc func canDeviceVoiceRecord(_ call: CAPPluginCall) {
|
|
11
11
|
call.resolve(ResponseGenerator.successResponse())
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
@objc func requestAudioRecordingPermission(_ call: CAPPluginCall) {
|
|
15
15
|
AVAudioSession.sharedInstance().requestRecordPermission { granted in
|
|
16
16
|
if granted {
|
|
@@ -20,29 +20,28 @@ public class VoiceRecorder: CAPPlugin {
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
@objc func hasAudioRecordingPermission(_ call: CAPPluginCall) {
|
|
25
25
|
call.resolve(ResponseGenerator.fromBoolean(doesUserGaveAudioRecordingPermission()))
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
|
|
29
28
|
@objc func startRecording(_ call: CAPPluginCall) {
|
|
30
|
-
if
|
|
29
|
+
if !doesUserGaveAudioRecordingPermission() {
|
|
31
30
|
call.reject(Messages.MISSING_PERMISSION)
|
|
32
31
|
return
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
if
|
|
33
|
+
|
|
34
|
+
if customMediaRecorder != nil {
|
|
36
35
|
call.reject(Messages.ALREADY_RECORDING)
|
|
37
36
|
return
|
|
38
37
|
}
|
|
39
|
-
|
|
38
|
+
|
|
40
39
|
customMediaRecorder = CustomMediaRecorder()
|
|
41
|
-
if
|
|
40
|
+
if customMediaRecorder == nil {
|
|
42
41
|
call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
|
|
43
42
|
return
|
|
44
43
|
}
|
|
45
|
-
|
|
44
|
+
|
|
46
45
|
let successfullyStartedRecording = customMediaRecorder!.startRecording()
|
|
47
46
|
if successfullyStartedRecording == false {
|
|
48
47
|
call.reject(Messages.CANNOT_RECORD_ON_THIS_PHONE)
|
|
@@ -50,17 +49,17 @@ public class VoiceRecorder: CAPPlugin {
|
|
|
50
49
|
call.resolve(ResponseGenerator.successResponse())
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
@objc func stopRecording(_ call: CAPPluginCall) {
|
|
55
|
-
if
|
|
54
|
+
if customMediaRecorder == nil {
|
|
56
55
|
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
57
56
|
return
|
|
58
57
|
}
|
|
59
|
-
|
|
58
|
+
|
|
60
59
|
customMediaRecorder?.stopRecording()
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
let audioFileUrl = customMediaRecorder?.getOutputFile()
|
|
63
|
-
if
|
|
62
|
+
if audioFileUrl == nil {
|
|
64
63
|
customMediaRecorder = nil
|
|
65
64
|
call.reject(Messages.FAILED_TO_FETCH_RECORDING)
|
|
66
65
|
return
|
|
@@ -77,54 +76,54 @@ public class VoiceRecorder: CAPPlugin {
|
|
|
77
76
|
call.resolve(ResponseGenerator.dataResponse(recordData.toDictionary()))
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
|
-
|
|
79
|
+
|
|
81
80
|
@objc func pauseRecording(_ call: CAPPluginCall) {
|
|
82
|
-
if
|
|
81
|
+
if customMediaRecorder == nil {
|
|
83
82
|
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
84
83
|
} else {
|
|
85
84
|
call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.pauseRecording() ?? false))
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
|
-
|
|
87
|
+
|
|
89
88
|
@objc func resumeRecording(_ call: CAPPluginCall) {
|
|
90
|
-
if
|
|
89
|
+
if customMediaRecorder == nil {
|
|
91
90
|
call.reject(Messages.RECORDING_HAS_NOT_STARTED)
|
|
92
91
|
} else {
|
|
93
92
|
call.resolve(ResponseGenerator.fromBoolean(customMediaRecorder?.resumeRecording() ?? false))
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
|
-
|
|
95
|
+
|
|
97
96
|
@objc func getCurrentStatus(_ call: CAPPluginCall) {
|
|
98
|
-
if
|
|
97
|
+
if customMediaRecorder == nil {
|
|
99
98
|
call.resolve(ResponseGenerator.statusResponse(CurrentRecordingStatus.NONE))
|
|
100
99
|
} else {
|
|
101
100
|
call.resolve(ResponseGenerator.statusResponse(customMediaRecorder?.getCurrentStatus() ?? CurrentRecordingStatus.NONE))
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
|
-
|
|
103
|
+
|
|
105
104
|
func doesUserGaveAudioRecordingPermission() -> Bool {
|
|
106
105
|
return AVAudioSession.sharedInstance().recordPermission == AVAudioSession.RecordPermission.granted
|
|
107
106
|
}
|
|
108
|
-
|
|
107
|
+
|
|
109
108
|
func readFileAsBase64(_ filePath: URL?) -> String? {
|
|
110
|
-
if
|
|
109
|
+
if filePath == nil {
|
|
111
110
|
return nil
|
|
112
111
|
}
|
|
113
|
-
|
|
112
|
+
|
|
114
113
|
do {
|
|
115
114
|
let fileData = try Data.init(contentsOf: filePath!)
|
|
116
115
|
let fileStream = fileData.base64EncodedString(options: NSData.Base64EncodingOptions.init(rawValue: 0))
|
|
117
116
|
return fileStream
|
|
118
117
|
} catch {}
|
|
119
|
-
|
|
118
|
+
|
|
120
119
|
return nil
|
|
121
120
|
}
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
func getMsDurationOfAudioFile(_ filePath: URL?) -> Int {
|
|
124
123
|
if filePath == nil {
|
|
125
124
|
return -1
|
|
126
125
|
}
|
|
127
126
|
return Int(CMTimeGetSeconds(AVURLAsset(url: filePath!).duration) * 1000)
|
|
128
127
|
}
|
|
129
|
-
|
|
128
|
+
|
|
130
129
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@independo/capacitor-voice-recorder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-dev.1",
|
|
4
4
|
"description": "Capacitor plugin for voice recording",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -52,14 +52,13 @@
|
|
|
52
52
|
"verify:ios": "cd ios && pod install && xcodebuild -workspace Plugin.xcworkspace -scheme Plugin -destination generic/platform=iOS && cd ..",
|
|
53
53
|
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
54
54
|
"verify:web": "npm run build",
|
|
55
|
-
"lint": "npm run eslint
|
|
56
|
-
"fmt": "npm run eslint -- --fix
|
|
55
|
+
"lint": "npm run eslint",
|
|
56
|
+
"fmt": "npm run eslint -- --fix",
|
|
57
57
|
"eslint": "eslint . --ext ts",
|
|
58
|
-
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
|
59
58
|
"swiftlint": "node-swiftlint",
|
|
60
59
|
"docgen": "docgen --api VoiceRecorderPlugin --output-readme README.md --output-json dist/docs.json",
|
|
61
60
|
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
62
|
-
"clean": "
|
|
61
|
+
"clean": "rm -rf dist",
|
|
63
62
|
"watch": "tsc --watch",
|
|
64
63
|
"prepublishOnly": "npm run build"
|
|
65
64
|
},
|
|
@@ -67,10 +66,10 @@
|
|
|
67
66
|
"get-blob-duration": "^1.2.0"
|
|
68
67
|
},
|
|
69
68
|
"devDependencies": {
|
|
70
|
-
"@capacitor/android": "^
|
|
71
|
-
"@capacitor/core": "^
|
|
69
|
+
"@capacitor/android": "^7.0.1",
|
|
70
|
+
"@capacitor/core": "^7.0.1",
|
|
72
71
|
"@capacitor/docgen": "^0.3.0",
|
|
73
|
-
"@capacitor/ios": "^
|
|
72
|
+
"@capacitor/ios": "^7.0.1",
|
|
74
73
|
"@ionic/eslint-config": "^0.4.0",
|
|
75
74
|
"@ionic/prettier-config": "^4.0.0",
|
|
76
75
|
"@ionic/swiftlint-config": "^2.0.0",
|
|
@@ -79,17 +78,14 @@
|
|
|
79
78
|
"@semantic-release/git": "^10.0.1",
|
|
80
79
|
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
|
81
80
|
"conventional-changelog-conventionalcommits": "^8.0.0",
|
|
82
|
-
"eslint": "^8.
|
|
83
|
-
"
|
|
84
|
-
"prettier-plugin-java": "~2.1.0",
|
|
85
|
-
"rimraf": "^6.0.1",
|
|
86
|
-
"rollup": "^4.19.2",
|
|
81
|
+
"eslint": "^8.57.0",
|
|
82
|
+
"rollup": "^4.34.3",
|
|
87
83
|
"semantic-release": "^24.0.0",
|
|
88
84
|
"swiftlint": "^2.0.0",
|
|
89
85
|
"typescript": "<4.5.0"
|
|
90
86
|
},
|
|
91
87
|
"peerDependencies": {
|
|
92
|
-
"@capacitor/core": "
|
|
88
|
+
"@capacitor/core": ">=7.0.0"
|
|
93
89
|
},
|
|
94
90
|
"prettier": "@ionic/prettier-config",
|
|
95
91
|
"swiftlint": "@ionic/swiftlint-config",
|