nosnia-audio-recorder 0.8.3 → 0.8.5

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.
@@ -3,24 +3,23 @@ package com.nosniaaudiorecorder
3
3
  import android.media.MediaPlayer
4
4
  import android.os.Handler
5
5
  import android.os.Looper
6
- import com.facebook.react.bridge.Promise
7
- import com.facebook.react.bridge.ReactApplicationContext
8
- import com.facebook.react.bridge.ReadableMap
9
- import com.facebook.react.bridge.WritableMap
10
- import com.facebook.react.bridge.WritableNativeMap
11
- import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.*
12
7
  import com.facebook.react.modules.core.DeviceEventManagerModule
13
8
  import com.facebook.react.module.annotations.ReactModule
14
9
  import java.io.File
15
10
 
16
- @ReactModule(name = NosniaAudioPlayerModule.NAME)
17
- class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
18
- NativeNosniaAudioPlayerSpec(reactContext) {
11
+ @ReactModule(name = "NosniaAudioPlayer")
12
+ class NosniaAudioPlayerModule(private val reactContext: ReactApplicationContext) :
13
+ ReactContextBaseJavaModule(reactContext) {
14
+
15
+ companion object {
16
+ const val NAME = "NosniaAudioPlayer"
17
+ }
19
18
 
20
19
  private var mediaPlayer: MediaPlayer? = null
21
20
  private var currentFilePath: String? = null
22
21
  private var isPlaying = false
23
-
22
+
24
23
  private val progressHandler = Handler(Looper.getMainLooper())
25
24
  private val progressRunnable = object : Runnable {
26
25
  override fun run() {
@@ -28,38 +27,37 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
28
27
  if (isPlaying && player.isPlaying) {
29
28
  val currentTime = player.currentPosition.toLong()
30
29
  val duration = player.duration.toLong()
31
-
30
+
32
31
  sendEvent("onPlaybackProgress", Arguments.createMap().apply {
33
32
  putDouble("currentTime", currentTime.toDouble())
34
33
  putDouble("duration", duration.toDouble())
35
34
  putBoolean("isPlaying", true)
36
35
  })
37
-
36
+
38
37
  progressHandler.postDelayed(this, 100)
39
38
  }
40
39
  }
41
40
  }
42
41
  }
43
-
42
+
44
43
  private fun sendEvent(eventName: String, params: WritableMap?) {
45
- reactApplicationContext
44
+ reactContext
46
45
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
47
46
  .emit(eventName, params)
48
47
  }
49
-
48
+
50
49
  private fun startProgressUpdates() {
51
50
  progressHandler.post(progressRunnable)
52
51
  }
53
-
52
+
54
53
  private fun stopProgressUpdates() {
55
54
  progressHandler.removeCallbacks(progressRunnable)
56
55
  }
57
56
 
58
- override fun getName(): String {
59
- return NAME
60
- }
57
+ override fun getName(): String = NAME
61
58
 
62
- override fun startPlaying(options: ReadableMap, promise: Promise) {
59
+ @ReactMethod
60
+ fun startPlaying(options: ReadableMap, promise: Promise) {
63
61
  try {
64
62
  val filePath = options.getString("filePath")
65
63
  if (filePath == null) {
@@ -79,33 +77,31 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
79
77
  false
80
78
  }
81
79
 
82
- // Check if file exists
83
80
  val file = File(filePath)
84
81
  if (!file.exists()) {
85
82
  promise.reject("FILE_NOT_FOUND", "Audio file not found: $filePath")
86
83
  return
87
84
  }
88
85
 
89
- // Release existing player if any
90
86
  mediaPlayer?.release()
91
87
 
92
88
  mediaPlayer = MediaPlayer().apply {
93
89
  setDataSource(filePath)
94
90
  setVolume(volume, volume)
95
91
  isLooping = loop
96
-
92
+
97
93
  setOnCompletionListener {
98
94
  isPlaying = false
99
95
  stopProgressUpdates()
100
96
  sendEvent("onPlaybackComplete", Arguments.createMap())
101
97
  }
102
-
103
- setOnErrorListener { _, what, extra ->
98
+
99
+ setOnErrorListener { _, _, _ ->
104
100
  isPlaying = false
105
101
  stopProgressUpdates()
106
102
  true
107
103
  }
108
-
104
+
109
105
  prepare()
110
106
  start()
111
107
  }
@@ -122,10 +118,11 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
122
118
  }
123
119
  }
124
120
 
125
- override fun stopPlaying(promise: Promise) {
121
+ @ReactMethod
122
+ fun stopPlaying(promise: Promise) {
126
123
  try {
127
124
  stopProgressUpdates()
128
-
125
+
129
126
  mediaPlayer?.apply {
130
127
  if (isPlaying) {
131
128
  stop()
@@ -135,14 +132,15 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
135
132
  mediaPlayer = null
136
133
  isPlaying = false
137
134
  currentFilePath = null
138
-
135
+
139
136
  promise.resolve(null)
140
137
  } catch (e: Exception) {
141
138
  promise.reject("STOP_PLAYING_ERROR", e.message, e)
142
139
  }
143
140
  }
144
141
 
145
- override fun pausePlaying(promise: Promise) {
142
+ @ReactMethod
143
+ fun pausePlaying(promise: Promise) {
146
144
  try {
147
145
  if (!isPlaying || mediaPlayer == null) {
148
146
  promise.reject("NOT_PLAYING", "No playback in progress")
@@ -157,7 +155,8 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
157
155
  }
158
156
  }
159
157
 
160
- override fun resumePlaying(promise: Promise) {
158
+ @ReactMethod
159
+ fun resumePlaying(promise: Promise) {
161
160
  try {
162
161
  if (isPlaying || mediaPlayer == null) {
163
162
  promise.reject("NOT_PAUSED", "Playback is not paused")
@@ -172,7 +171,8 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
172
171
  }
173
172
  }
174
173
 
175
- override fun seekToTime(time: Double, promise: Promise) {
174
+ @ReactMethod
175
+ fun seekToTime(time: Double, promise: Promise) {
176
176
  try {
177
177
  if (mediaPlayer == null) {
178
178
  promise.reject("NO_PLAYER", "No audio player initialized")
@@ -187,7 +187,8 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
187
187
  }
188
188
  }
189
189
 
190
- override fun setVolume(volume: Double, promise: Promise) {
190
+ @ReactMethod
191
+ fun setVolume(volume: Double, promise: Promise) {
191
192
  try {
192
193
  if (mediaPlayer == null) {
193
194
  promise.reject("NO_PLAYER", "No audio player initialized")
@@ -202,11 +203,12 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
202
203
  }
203
204
  }
204
205
 
205
- override fun getPlayerStatus(promise: Promise) {
206
+ @ReactMethod
207
+ fun getPlayerStatus(promise: Promise) {
206
208
  try {
207
209
  val status = WritableNativeMap().apply {
208
210
  putBoolean("isPlaying", isPlaying)
209
-
211
+
210
212
  if (mediaPlayer != null) {
211
213
  putDouble("duration", mediaPlayer!!.duration.toDouble())
212
214
  putDouble("currentTime", mediaPlayer!!.currentPosition.toDouble())
@@ -214,7 +216,7 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
214
216
  putDouble("duration", 0.0)
215
217
  putDouble("currentTime", 0.0)
216
218
  }
217
-
219
+
218
220
  if (currentFilePath != null) {
219
221
  putString("currentFilePath", currentFilePath)
220
222
  }
@@ -231,8 +233,4 @@ class NosniaAudioPlayerModule(reactContext: ReactApplicationContext) :
231
233
  mediaPlayer?.release()
232
234
  mediaPlayer = null
233
235
  }
234
-
235
- companion object {
236
- const val NAME = "NosniaAudioPlayer"
237
- }
238
236
  }
@@ -8,12 +8,7 @@ import android.os.Environment
8
8
  import android.os.Handler
9
9
  import android.os.Looper
10
10
  import androidx.core.content.ContextCompat
11
- import com.facebook.react.bridge.Promise
12
- import com.facebook.react.bridge.ReactApplicationContext
13
- import com.facebook.react.bridge.ReadableMap
14
- import com.facebook.react.bridge.WritableMap
15
- import com.facebook.react.bridge.WritableNativeMap
16
- import com.facebook.react.bridge.Arguments
11
+ import com.facebook.react.bridge.*
17
12
  import com.facebook.react.modules.core.DeviceEventManagerModule
18
13
  import com.facebook.react.module.annotations.ReactModule
19
14
  import java.io.File
@@ -21,9 +16,13 @@ import java.text.SimpleDateFormat
21
16
  import java.util.Date
22
17
  import java.util.Locale
23
18
 
24
- @ReactModule(name = NosniaAudioRecorderModule.NAME)
25
- class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
26
- NativeNosniaAudioRecorderSpec(reactContext) {
19
+ @ReactModule(name = "NosniaAudioRecorder")
20
+ class NosniaAudioRecorderModule(private val reactContext: ReactApplicationContext) :
21
+ ReactContextBaseJavaModule(reactContext) {
22
+
23
+ companion object {
24
+ const val NAME = "NosniaAudioRecorder"
25
+ }
27
26
 
28
27
  private var mediaRecorder: MediaRecorder? = null
29
28
  private var currentFilePath: String? = null
@@ -66,11 +65,10 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
66
65
  progressHandler.removeCallbacks(progressRunnable)
67
66
  }
68
67
 
69
- override fun getName(): String {
70
- return NAME
71
- }
68
+ override fun getName(): String = NAME
72
69
 
73
- override fun startRecording(options: ReadableMap, promise: Promise) {
70
+ @ReactMethod
71
+ fun startRecording(options: ReadableMap, promise: Promise) {
74
72
  try {
75
73
  // Prevent concurrent recordings
76
74
  if (isRecording) {
@@ -189,7 +187,8 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
189
187
  }
190
188
  }
191
189
 
192
- override fun stopRecording(promise: Promise) {
190
+ @ReactMethod
191
+ fun stopRecording(promise: Promise) {
193
192
  try {
194
193
  if (!isRecording || mediaRecorder == null) {
195
194
  promise.reject("NOT_RECORDING", "No recording in progress")
@@ -246,7 +245,8 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
246
245
  }
247
246
  }
248
247
 
249
- override fun pauseRecording(promise: Promise) {
248
+ @ReactMethod
249
+ fun pauseRecording(promise: Promise) {
250
250
  try {
251
251
  if (!isRecording || mediaRecorder == null) {
252
252
  promise.reject("NOT_RECORDING", "No recording in progress")
@@ -275,7 +275,8 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
275
275
  }
276
276
  }
277
277
 
278
- override fun resumeRecording(promise: Promise) {
278
+ @ReactMethod
279
+ fun resumeRecording(promise: Promise) {
279
280
  try {
280
281
  if (!isRecording || mediaRecorder == null) {
281
282
  promise.reject("NOT_RECORDING", "No recording in progress")
@@ -304,7 +305,8 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
304
305
  }
305
306
  }
306
307
 
307
- override fun cancelRecording(promise: Promise) {
308
+ @ReactMethod
309
+ fun cancelRecording(promise: Promise) {
308
310
  try {
309
311
  stopProgressUpdates()
310
312
 
@@ -353,7 +355,8 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
353
355
  }
354
356
  }
355
357
 
356
- override fun getRecorderStatus(promise: Promise) {
358
+ @ReactMethod
359
+ fun getRecorderStatus(promise: Promise) {
357
360
  try {
358
361
  val currentTime = System.currentTimeMillis()
359
362
 
@@ -385,20 +388,13 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
385
388
  promise.reject("STATUS_ERROR", e.message ?: "Failed to get recorder status", e)
386
389
  }
387
390
  }
388
- putString("currentFilePath", currentFilePath)
389
- }
390
- }
391
- promise.resolve(status)
392
- } catch (e: Exception) {
393
- promise.reject("STATUS_ERROR", e.message, e)
394
- }
395
- }
396
391
 
397
- override fun requestAudioPermission(promise: Promise) {
392
+ @ReactMethod
393
+ fun requestAudioPermission(promise: Promise) {
398
394
  try {
399
395
  val permission = Manifest.permission.RECORD_AUDIO
400
396
  val hasPermission = ContextCompat.checkSelfPermission(
401
- reactApplicationContext,
397
+ reactContext,
402
398
  permission
403
399
  ) == android.content.pm.PackageManager.PERMISSION_GRANTED
404
400
 
@@ -408,11 +404,12 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
408
404
  }
409
405
  }
410
406
 
411
- override fun checkAudioPermission(promise: Promise) {
407
+ @ReactMethod
408
+ fun checkAudioPermission(promise: Promise) {
412
409
  try {
413
410
  val permission = Manifest.permission.RECORD_AUDIO
414
411
  val hasPermission = ContextCompat.checkSelfPermission(
415
- reactApplicationContext,
412
+ reactContext,
416
413
  permission
417
414
  ) == android.content.pm.PackageManager.PERMISSION_GRANTED
418
415
 
@@ -424,7 +421,7 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
424
421
 
425
422
  private fun getRecordingDirectory(): File {
426
423
  return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
427
- File(reactApplicationContext.getExternalFilesDir(null), "recordings")
424
+ File(reactContext.getExternalFilesDir(null), "recordings")
428
425
  } else {
429
426
  @Suppress("DEPRECATION")
430
427
  File(
@@ -436,10 +433,6 @@ class NosniaAudioRecorderModule(reactContext: ReactApplicationContext) :
436
433
 
437
434
  private fun generateFilename(): String {
438
435
  val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
439
- return "recording_$timestamp.mp3"
440
- }
441
-
442
- companion object {
443
- const val NAME = "NosniaAudioRecorder"
436
+ return "recording_$timestamp.m4a"
444
437
  }
445
438
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nosnia-audio-recorder",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "This is a modern audio recorder which actually works cross platform",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",