@capgo/native-audio 4.0.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.
Files changed (37) hide show
  1. package/CapgoNativeAudio.podspec +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +394 -0
  4. package/android/build.gradle +55 -0
  5. package/android/src/main/AndroidManifest.xml +5 -0
  6. package/android/src/main/java/ee/forgr/audio/AudioAsset.java +140 -0
  7. package/android/src/main/java/ee/forgr/audio/AudioDispatcher.java +178 -0
  8. package/android/src/main/java/ee/forgr/audio/Constant.java +18 -0
  9. package/android/src/main/java/ee/forgr/audio/NativeAudio.java +471 -0
  10. package/android/src/main/res/layout/bridge_layout_main.xml +15 -0
  11. package/android/src/main/res/values/colors.xml +3 -0
  12. package/android/src/main/res/values/strings.xml +3 -0
  13. package/android/src/main/res/values/styles.xml +3 -0
  14. package/dist/docs.json +279 -0
  15. package/dist/esm/audio-asset.d.ts +4 -0
  16. package/dist/esm/audio-asset.js +6 -0
  17. package/dist/esm/audio-asset.js.map +1 -0
  18. package/dist/esm/definitions.d.ts +53 -0
  19. package/dist/esm/definitions.js +2 -0
  20. package/dist/esm/definitions.js.map +1 -0
  21. package/dist/esm/index.d.ts +4 -0
  22. package/dist/esm/index.js +7 -0
  23. package/dist/esm/index.js.map +1 -0
  24. package/dist/esm/web.d.ts +52 -0
  25. package/dist/esm/web.js +113 -0
  26. package/dist/esm/web.js.map +1 -0
  27. package/dist/plugin.cjs.js +134 -0
  28. package/dist/plugin.cjs.js.map +1 -0
  29. package/dist/plugin.js +137 -0
  30. package/dist/plugin.js.map +1 -0
  31. package/ios/Plugin/AudioAsset.swift +184 -0
  32. package/ios/Plugin/Constant.swift +20 -0
  33. package/ios/Plugin/Info.plist +24 -0
  34. package/ios/Plugin/Plugin.h +10 -0
  35. package/ios/Plugin/Plugin.m +19 -0
  36. package/ios/Plugin/Plugin.swift +276 -0
  37. package/package.json +91 -0
@@ -0,0 +1,178 @@
1
+ package ee.forgr.audio;
2
+
3
+ import android.content.res.AssetFileDescriptor;
4
+ import android.media.AudioAttributes;
5
+ import android.media.MediaPlayer;
6
+ import android.os.Build;
7
+ import android.os.SystemClock;
8
+ import android.util.Log;
9
+ import java.util.concurrent.Callable;
10
+
11
+ public class AudioDispatcher
12
+ implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnSeekCompleteListener {
13
+
14
+ private final String TAG = "AudioDispatcher";
15
+
16
+ private final int INVALID = 0;
17
+ private final int PREPARED = 1;
18
+ private final int PENDING_PLAY = 2;
19
+ private final int PLAYING = 3;
20
+ private final int PENDING_LOOP = 4;
21
+ private final int LOOPING = 5;
22
+ private final int PAUSE = 6;
23
+
24
+ private MediaPlayer mediaPlayer;
25
+ private int mediaState;
26
+ private AudioAsset owner;
27
+
28
+ public AudioDispatcher(AssetFileDescriptor assetFileDescriptor, float volume) throws Exception {
29
+ mediaState = INVALID;
30
+
31
+ mediaPlayer = new MediaPlayer();
32
+ mediaPlayer.setOnCompletionListener(this);
33
+ mediaPlayer.setOnPreparedListener(this);
34
+ mediaPlayer.setDataSource(
35
+ assetFileDescriptor.getFileDescriptor(),
36
+ assetFileDescriptor.getStartOffset(),
37
+ assetFileDescriptor.getLength()
38
+ );
39
+ mediaPlayer.setOnSeekCompleteListener(this);
40
+ mediaPlayer.setAudioAttributes(
41
+ new AudioAttributes.Builder()
42
+ .setUsage(AudioAttributes.USAGE_MEDIA)
43
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
44
+ .build()
45
+ );
46
+ mediaPlayer.setVolume(volume, volume);
47
+ mediaPlayer.prepare();
48
+ }
49
+
50
+ public void setOwner(AudioAsset asset) {
51
+ owner = asset;
52
+ }
53
+
54
+ public double getDuration() {
55
+ return mediaPlayer.getDuration() / 1000.0;
56
+ }
57
+
58
+ public double getCurrentPosition() {
59
+ return mediaPlayer.getCurrentPosition() / 1000.0;
60
+ }
61
+
62
+ public void play(Double time, Callable<Void> callable) throws Exception {
63
+ invokePlay(time, false);
64
+ }
65
+
66
+ public boolean pause() throws Exception {
67
+ if (mediaPlayer.isPlaying()) {
68
+ mediaPlayer.pause();
69
+ mediaState = PAUSE;
70
+ return true;
71
+ }
72
+
73
+ return false;
74
+ }
75
+
76
+ public void resume() throws Exception {
77
+ mediaPlayer.start();
78
+ }
79
+
80
+ public void stop() throws Exception {
81
+ if (mediaPlayer.isPlaying()) {
82
+ mediaState = INVALID;
83
+ mediaPlayer.pause();
84
+ mediaPlayer.seekTo(0);
85
+ }
86
+ }
87
+
88
+ public void setVolume(float volume) throws Exception {
89
+ mediaPlayer.setVolume(volume, volume);
90
+ }
91
+
92
+ public void loop() throws Exception {
93
+ mediaPlayer.setLooping(true);
94
+ }
95
+
96
+ public void unload() throws Exception {
97
+ this.stop();
98
+ mediaPlayer.release();
99
+ }
100
+
101
+ @Override
102
+ public void onCompletion(MediaPlayer mp) {
103
+ try {
104
+ if (mediaState != LOOPING) {
105
+ this.mediaState = INVALID;
106
+
107
+ this.stop();
108
+
109
+ if (this.owner != null) {
110
+ this.owner.dispatchComplete();
111
+ }
112
+ }
113
+ } catch (Exception ex) {
114
+ Log.d(TAG, "Caught exception while listening for onCompletion: " + ex.getLocalizedMessage());
115
+ }
116
+ }
117
+
118
+ @Override
119
+ public void onPrepared(MediaPlayer mp) {
120
+ try {
121
+ if (mediaState == PENDING_PLAY) {
122
+ mediaPlayer.setLooping(false);
123
+ } else if (mediaState == PENDING_LOOP) {
124
+ mediaPlayer.setLooping(true);
125
+ } else {
126
+ mediaState = PREPARED;
127
+ }
128
+ } catch (Exception ex) {
129
+ Log.d(TAG, "Caught exception while listening for onPrepared: " + ex.getLocalizedMessage());
130
+ }
131
+ }
132
+
133
+ private void seek(Double time) {
134
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
135
+ mediaPlayer.seekTo((int) (time * 1000), MediaPlayer.SEEK_NEXT_SYNC);
136
+ } else {
137
+ mediaPlayer.seekTo((int) (time * 1000));
138
+ }
139
+ }
140
+
141
+ private void invokePlay(Double time, Boolean loop) {
142
+ try {
143
+ boolean playing = mediaPlayer.isPlaying();
144
+
145
+ if (playing) {
146
+ mediaPlayer.pause();
147
+ mediaPlayer.setLooping(loop);
148
+ mediaState = PENDING_PLAY;
149
+ seek(time);
150
+ } else {
151
+ if (mediaState == PREPARED) {
152
+ mediaState = (loop ? PENDING_LOOP : PENDING_PLAY);
153
+ onPrepared(mediaPlayer);
154
+ seek(time);
155
+ } else {
156
+ mediaState = (loop ? PENDING_LOOP : PENDING_PLAY);
157
+ mediaPlayer.setLooping(loop);
158
+ seek(time);
159
+ }
160
+ }
161
+ } catch (Exception ex) {
162
+ Log.d(TAG, "Caught exception while invoking audio: " + ex.getLocalizedMessage());
163
+ }
164
+ }
165
+
166
+ @Override
167
+ public void onSeekComplete(MediaPlayer mp) {
168
+ if (mediaState == PENDING_PLAY || mediaState == PENDING_LOOP) {
169
+ Log.w("AudioDispatcher", "play " + mediaState);
170
+ mediaPlayer.start();
171
+ mediaState = PLAYING;
172
+ }
173
+ }
174
+
175
+ public boolean isPlaying() throws Exception {
176
+ return mediaPlayer.isPlaying();
177
+ }
178
+ }
@@ -0,0 +1,18 @@
1
+ package ee.forgr.audio;
2
+
3
+ public class Constant {
4
+
5
+ public static final String ERROR_AUDIO_ID_MISSING = "Audio Id is missing";
6
+ public static final String ERROR_AUDIO_ASSET_MISSING = "Audio Asset is missing";
7
+ public static final String ERROR_AUDIO_EXISTS = "Audio Asset already exists";
8
+ public static final String ERROR_ASSET_PATH_MISSING = "Asset Path is missing";
9
+ public static final String ERROR_ASSET_NOT_LOADED = "Asset is not loaded";
10
+
11
+ public static final String ASSET_ID = "assetId";
12
+ public static final String ASSET_PATH = "assetPath";
13
+ public static final String OPT_FADE_MUSIC = "fade";
14
+ public static final String OPT_FOCUS_AUDIO = "focus";
15
+ public static final String VOLUME = "volume";
16
+ public static final String AUDIO_CHANNEL_NUM = "audioChannelNum";
17
+ public static final String LOOP = "loop";
18
+ }
@@ -0,0 +1,471 @@
1
+ package ee.forgr.audio;
2
+
3
+ import static ee.forgr.audio.Constant.ASSET_ID;
4
+ import static ee.forgr.audio.Constant.ASSET_PATH;
5
+ import static ee.forgr.audio.Constant.AUDIO_CHANNEL_NUM;
6
+ import static ee.forgr.audio.Constant.ERROR_ASSET_NOT_LOADED;
7
+ import static ee.forgr.audio.Constant.ERROR_ASSET_PATH_MISSING;
8
+ import static ee.forgr.audio.Constant.ERROR_AUDIO_ASSET_MISSING;
9
+ import static ee.forgr.audio.Constant.ERROR_AUDIO_EXISTS;
10
+ import static ee.forgr.audio.Constant.ERROR_AUDIO_ID_MISSING;
11
+ import static ee.forgr.audio.Constant.LOOP;
12
+ import static ee.forgr.audio.Constant.OPT_FADE_MUSIC;
13
+ import static ee.forgr.audio.Constant.OPT_FOCUS_AUDIO;
14
+ import static ee.forgr.audio.Constant.VOLUME;
15
+
16
+ import android.Manifest;
17
+ import android.content.Context;
18
+ import android.content.res.AssetFileDescriptor;
19
+ import android.content.res.AssetManager;
20
+ import android.media.AudioManager;
21
+ import android.os.ParcelFileDescriptor;
22
+ import android.util.Log;
23
+ import com.getcapacitor.JSObject;
24
+ import com.getcapacitor.Plugin;
25
+ import com.getcapacitor.PluginCall;
26
+ import com.getcapacitor.PluginMethod;
27
+ import com.getcapacitor.annotation.CapacitorPlugin;
28
+ import com.getcapacitor.annotation.Permission;
29
+ import java.io.File;
30
+ import java.net.URI;
31
+ import java.util.ArrayList;
32
+ import java.util.HashMap;
33
+ import java.util.concurrent.Callable;
34
+
35
+ @CapacitorPlugin(
36
+ permissions = {
37
+ @Permission(strings = { Manifest.permission.MODIFY_AUDIO_SETTINGS }),
38
+ @Permission(strings = { Manifest.permission.WRITE_EXTERNAL_STORAGE }),
39
+ @Permission(strings = { Manifest.permission.READ_PHONE_STATE })
40
+ }
41
+ )
42
+ public class NativeAudio extends Plugin implements AudioManager.OnAudioFocusChangeListener {
43
+
44
+ public static final String TAG = "NativeAudio";
45
+
46
+ private static HashMap<String, AudioAsset> audioAssetList;
47
+ private static ArrayList<AudioAsset> resumeList;
48
+ private boolean fadeMusic = false;
49
+ private AudioManager audioManager;
50
+
51
+ @Override
52
+ public void load() {
53
+ super.load();
54
+
55
+ this.audioManager = (AudioManager) getBridge().getActivity().getSystemService(Context.AUDIO_SERVICE);
56
+ }
57
+
58
+ @Override
59
+ public void onAudioFocusChange(int focusChange) {
60
+ if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {} else if (
61
+ focusChange == AudioManager.AUDIOFOCUS_LOSS
62
+ ) {}
63
+ }
64
+
65
+ @Override
66
+ protected void handleOnPause() {
67
+ super.handleOnPause();
68
+
69
+ try {
70
+ if (audioAssetList != null) {
71
+ for (HashMap.Entry<String, AudioAsset> entry : audioAssetList.entrySet()) {
72
+ AudioAsset audio = entry.getValue();
73
+
74
+ if (audio != null) {
75
+ boolean wasPlaying = audio.pause();
76
+
77
+ if (wasPlaying) {
78
+ resumeList.add(audio);
79
+ }
80
+ }
81
+ }
82
+ }
83
+ } catch (Exception ex) {
84
+ Log.d(TAG, "Exception caught while listening for handleOnPause: " + ex.getLocalizedMessage());
85
+ }
86
+ }
87
+
88
+ @Override
89
+ protected void handleOnResume() {
90
+ super.handleOnResume();
91
+
92
+ try {
93
+ if (resumeList != null) {
94
+ while (!resumeList.isEmpty()) {
95
+ AudioAsset audio = resumeList.remove(0);
96
+
97
+ if (audio != null) {
98
+ audio.resume();
99
+ }
100
+ }
101
+ }
102
+ } catch (Exception ex) {
103
+ Log.d(TAG, "Exception caught while listening for handleOnResume: " + ex.getLocalizedMessage());
104
+ }
105
+ }
106
+
107
+ @PluginMethod
108
+ public void configure(PluginCall call) {
109
+ initSoundPool();
110
+
111
+ if (call.hasOption(OPT_FADE_MUSIC)) this.fadeMusic = call.getBoolean(OPT_FADE_MUSIC);
112
+
113
+ if (call.hasOption(OPT_FOCUS_AUDIO) && this.audioManager != null) {
114
+ if (call.getBoolean(OPT_FOCUS_AUDIO)) {
115
+ this.audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
116
+ } else {
117
+ this.audioManager.abandonAudioFocus(this);
118
+ }
119
+ }
120
+ }
121
+
122
+ @PluginMethod
123
+ public void preload(final PluginCall call) {
124
+ new Thread(
125
+ new Runnable() {
126
+ @Override
127
+ public void run() {
128
+ preloadAsset(call);
129
+ }
130
+ }
131
+ )
132
+ .start();
133
+ }
134
+
135
+ @PluginMethod
136
+ public void play(final PluginCall call) {
137
+ getBridge()
138
+ .getActivity()
139
+ .runOnUiThread(
140
+ new Runnable() {
141
+ @Override
142
+ public void run() {
143
+ playOrLoop("play", call);
144
+ }
145
+ }
146
+ );
147
+ }
148
+
149
+ @PluginMethod
150
+ public void getCurrentTime(final PluginCall call) {
151
+ try {
152
+ initSoundPool();
153
+
154
+ String audioId = call.getString(ASSET_ID);
155
+
156
+ if (!isStringValid(audioId)) {
157
+ call.reject(ERROR_AUDIO_ID_MISSING + " - " + audioId);
158
+ return;
159
+ }
160
+
161
+ if (audioAssetList.containsKey(audioId)) {
162
+ AudioAsset asset = audioAssetList.get(audioId);
163
+ if (asset != null) {
164
+ call.resolve(new JSObject().put("currentTime", asset.getCurrentPosition()));
165
+ }
166
+ } else {
167
+ call.reject(ERROR_AUDIO_ASSET_MISSING + " - " + audioId);
168
+ }
169
+ } catch (Exception ex) {
170
+ call.reject(ex.getMessage());
171
+ }
172
+ }
173
+
174
+ @PluginMethod
175
+ public void getDuration(final PluginCall call) {
176
+ try {
177
+ initSoundPool();
178
+
179
+ String audioId = call.getString(ASSET_ID);
180
+
181
+ if (!isStringValid(audioId)) {
182
+ call.reject(ERROR_AUDIO_ID_MISSING + " - " + audioId);
183
+ return;
184
+ }
185
+
186
+ if (audioAssetList.containsKey(audioId)) {
187
+ AudioAsset asset = audioAssetList.get(audioId);
188
+ if (asset != null) {
189
+ call.resolve(new JSObject().put("duration", asset.getDuration()));
190
+ }
191
+ } else {
192
+ call.reject(ERROR_AUDIO_ASSET_MISSING + " - " + audioId);
193
+ }
194
+ } catch (Exception ex) {
195
+ call.reject(ex.getMessage());
196
+ }
197
+ }
198
+
199
+ @PluginMethod
200
+ public void loop(final PluginCall call) {
201
+ getBridge()
202
+ .getActivity()
203
+ .runOnUiThread(
204
+ new Runnable() {
205
+ @Override
206
+ public void run() {
207
+ playOrLoop("loop", call);
208
+ }
209
+ }
210
+ );
211
+ }
212
+
213
+ @PluginMethod
214
+ public void pause(PluginCall call) {
215
+ try {
216
+ initSoundPool();
217
+ String audioId = call.getString(ASSET_ID);
218
+
219
+ if (audioAssetList.containsKey(audioId)) {
220
+ AudioAsset asset = audioAssetList.get(audioId);
221
+ if (asset != null) {
222
+ boolean wasPlaying = asset.pause();
223
+
224
+ if (wasPlaying) {
225
+ resumeList.add(asset);
226
+ }
227
+ }
228
+ } else {
229
+ call.reject(ERROR_ASSET_NOT_LOADED + " - " + audioId);
230
+ }
231
+ } catch (Exception ex) {
232
+ call.reject(ex.getMessage());
233
+ }
234
+ }
235
+
236
+ @PluginMethod
237
+ public void resume(PluginCall call) {
238
+ try {
239
+ initSoundPool();
240
+ String audioId = call.getString(ASSET_ID);
241
+
242
+ if (audioAssetList.containsKey(audioId)) {
243
+ AudioAsset asset = audioAssetList.get(audioId);
244
+ if (asset != null) {
245
+ asset.resume();
246
+ resumeList.add(asset);
247
+ }
248
+ } else {
249
+ call.reject(ERROR_ASSET_NOT_LOADED + " - " + audioId);
250
+ }
251
+ } catch (Exception ex) {
252
+ call.reject(ex.getMessage());
253
+ }
254
+ }
255
+
256
+ @PluginMethod
257
+ public void stop(PluginCall call) {
258
+ try {
259
+ initSoundPool();
260
+ String audioId = call.getString(ASSET_ID);
261
+
262
+ if (audioAssetList.containsKey(audioId)) {
263
+ AudioAsset asset = audioAssetList.get(audioId);
264
+ if (asset != null) {
265
+ asset.stop();
266
+ }
267
+ } else {
268
+ call.reject(ERROR_ASSET_NOT_LOADED + " - " + audioId);
269
+ }
270
+ } catch (Exception ex) {
271
+ call.reject(ex.getMessage());
272
+ }
273
+ }
274
+
275
+ @PluginMethod
276
+ public void unload(PluginCall call) {
277
+ try {
278
+ initSoundPool();
279
+ new JSObject();
280
+ JSObject status;
281
+
282
+ if (isStringValid(call.getString(ASSET_ID))) {
283
+ String audioId = call.getString(ASSET_ID);
284
+
285
+ if (audioAssetList.containsKey(audioId)) {
286
+ AudioAsset asset = audioAssetList.get(audioId);
287
+ if (asset != null) {
288
+ asset.unload();
289
+ audioAssetList.remove(audioId);
290
+
291
+ status = new JSObject();
292
+ status.put("status", "OK");
293
+ call.resolve(status);
294
+ } else {
295
+ status = new JSObject();
296
+ status.put("status", false);
297
+ call.resolve(status);
298
+ }
299
+ } else {
300
+ status = new JSObject();
301
+ status.put("status", ERROR_AUDIO_ASSET_MISSING + " - " + audioId);
302
+ call.resolve(status);
303
+ }
304
+ } else {
305
+ status = new JSObject();
306
+ status.put("status", ERROR_AUDIO_ID_MISSING);
307
+ call.resolve(status);
308
+ }
309
+ } catch (Exception ex) {
310
+ call.reject(ex.getMessage());
311
+ }
312
+ }
313
+
314
+ @PluginMethod
315
+ public void setVolume(PluginCall call) {
316
+ try {
317
+ initSoundPool();
318
+
319
+ String audioId = call.getString(ASSET_ID);
320
+ float volume = call.getFloat(VOLUME);
321
+
322
+ if (audioAssetList.containsKey(audioId)) {
323
+ AudioAsset asset = audioAssetList.get(audioId);
324
+ if (asset != null) {
325
+ asset.setVolume(volume);
326
+ }
327
+ } else {
328
+ call.reject(ERROR_AUDIO_ASSET_MISSING);
329
+ }
330
+ } catch (Exception ex) {
331
+ call.reject(ex.getMessage());
332
+ }
333
+ }
334
+
335
+ @PluginMethod
336
+ public void isPlaying(final PluginCall call) {
337
+ try {
338
+ initSoundPool();
339
+
340
+ String audioId = call.getString(ASSET_ID);
341
+
342
+ if (!isStringValid(audioId)) {
343
+ call.reject(ERROR_AUDIO_ID_MISSING + " - " + audioId);
344
+ return;
345
+ }
346
+
347
+ if (audioAssetList.containsKey(audioId)) {
348
+ AudioAsset asset = audioAssetList.get(audioId);
349
+ if (asset != null) {
350
+ call.resolve(new JSObject().put("isPlaying", asset.isPlaying()));
351
+ }
352
+ } else {
353
+ call.reject(ERROR_AUDIO_ASSET_MISSING + " - " + audioId);
354
+ }
355
+ } catch (Exception ex) {
356
+ call.reject(ex.getMessage());
357
+ }
358
+ }
359
+
360
+ public void dispatchComplete(String assetId) {
361
+ JSObject ret = new JSObject();
362
+ ret.put("assetId", assetId);
363
+ notifyListeners("complete", ret);
364
+ }
365
+
366
+ private void preloadAsset(PluginCall call) {
367
+ double volume = 1.0;
368
+ int audioChannelNum = 1;
369
+
370
+ try {
371
+ initSoundPool();
372
+
373
+ String audioId = call.getString(ASSET_ID);
374
+
375
+ boolean isUrl = call.getBoolean("isUrl", false);
376
+
377
+ if (!isStringValid(audioId)) {
378
+ call.reject(ERROR_AUDIO_ID_MISSING + " - " + audioId);
379
+ return;
380
+ }
381
+
382
+ if (!audioAssetList.containsKey(audioId)) {
383
+ String assetPath = call.getString(ASSET_PATH);
384
+
385
+ if (!isStringValid(assetPath)) {
386
+ call.reject(ERROR_ASSET_PATH_MISSING + " - " + audioId + " - " + assetPath);
387
+ return;
388
+ }
389
+
390
+ String fullPath = assetPath; //"raw/".concat(assetPath);
391
+
392
+ if (call.getDouble(VOLUME) == null) {
393
+ volume = 1.0;
394
+ } else {
395
+ volume = call.getDouble(VOLUME, 0.5);
396
+ }
397
+
398
+ if (call.getInt(AUDIO_CHANNEL_NUM) == null) {
399
+ audioChannelNum = 1;
400
+ } else {
401
+ audioChannelNum = call.getInt(AUDIO_CHANNEL_NUM);
402
+ }
403
+
404
+ AssetFileDescriptor assetFileDescriptor;
405
+ if (isUrl) {
406
+ File f = new File(new URI(fullPath));
407
+ ParcelFileDescriptor p = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
408
+ assetFileDescriptor = new AssetFileDescriptor(p, 0, -1);
409
+ } else {
410
+ Context ctx = getBridge().getActivity().getApplicationContext();
411
+ AssetManager am = ctx.getResources().getAssets();
412
+ assetFileDescriptor = am.openFd(fullPath);
413
+ }
414
+
415
+ AudioAsset asset = new AudioAsset(this, audioId, assetFileDescriptor, audioChannelNum, (float) volume);
416
+ audioAssetList.put(audioId, asset);
417
+
418
+ JSObject status = new JSObject();
419
+ status.put("STATUS", "OK");
420
+ call.resolve(status);
421
+ } else {
422
+ call.reject(ERROR_AUDIO_EXISTS);
423
+ }
424
+ } catch (Exception ex) {
425
+ call.reject(ex.getMessage());
426
+ }
427
+ }
428
+
429
+ private void playOrLoop(String action, final PluginCall call) {
430
+ try {
431
+ initSoundPool();
432
+
433
+ final String audioId = call.getString(ASSET_ID);
434
+ final Double time = call.getDouble("time", 0.0);
435
+ if (audioAssetList.containsKey(audioId)) {
436
+ AudioAsset asset = audioAssetList.get(audioId);
437
+ if (LOOP.equals(action) && asset != null) {
438
+ asset.loop();
439
+ } else if (asset != null) {
440
+ asset.play(
441
+ time,
442
+ new Callable<Void>() {
443
+ @Override
444
+ public Void call() throws Exception {
445
+ call.resolve(new JSObject().put(ASSET_ID, audioId));
446
+
447
+ return null;
448
+ }
449
+ }
450
+ );
451
+ }
452
+ }
453
+ } catch (Exception ex) {
454
+ call.reject(ex.getMessage());
455
+ }
456
+ }
457
+
458
+ private void initSoundPool() {
459
+ if (audioAssetList == null) {
460
+ audioAssetList = new HashMap<>();
461
+ }
462
+
463
+ if (resumeList == null) {
464
+ resumeList = new ArrayList<>();
465
+ }
466
+ }
467
+
468
+ private boolean isStringValid(String value) {
469
+ return (value != null && !value.isEmpty() && !value.equals("null"));
470
+ }
471
+ }
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+ xmlns:app="http://schemas.android.com/apk/res-auto"
4
+ xmlns:tools="http://schemas.android.com/tools"
5
+ android:layout_width="match_parent"
6
+ android:layout_height="match_parent"
7
+ tools:context="com.getcapacitor.BridgeActivity"
8
+ >
9
+
10
+ <WebView
11
+ android:id="@+id/webview"
12
+ android:layout_width="fill_parent"
13
+ android:layout_height="fill_parent" />
14
+
15
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -0,0 +1,3 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ </resources>
@@ -0,0 +1,3 @@
1
+ <resources>
2
+ <string name="my_string">Just a simple string</string>
3
+ </resources>
@@ -0,0 +1,3 @@
1
+ <resources>
2
+
3
+ </resources>