@capgo/native-audio 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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>