react-native-audio-api 0.6.0-rc.4 → 0.6.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.
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +35 -2
- package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +4 -0
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +31 -17
- package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +1 -3
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +56 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +0 -12
- package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +35 -12
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +30 -29
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +20 -22
- package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +19 -9
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +30 -11
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +53 -26
- package/android/src/main/java/com/swmansion/audioapi/system/VolumeChangeListener.kt +10 -5
- package/android/src/oldarch/NativeAudioAPIModuleSpec.java +39 -0
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +20 -14
- package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -3
- package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +24 -11
- package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +1 -0
- package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +10 -89
- package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +3 -24
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +2 -2
- package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +2 -3
- package/common/cpp/audioapi/core/AudioContext.cpp +4 -1
- package/common/cpp/audioapi/core/AudioContext.h +1 -1
- package/common/cpp/audioapi/core/AudioNode.cpp +31 -2
- package/common/cpp/audioapi/core/AudioNode.h +7 -1
- package/common/cpp/audioapi/core/AudioParam.cpp +84 -2
- package/common/cpp/audioapi/core/AudioParam.h +14 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +7 -1
- package/common/cpp/audioapi/core/BaseAudioContext.h +7 -1
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +3 -2
- package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
- package/common/cpp/audioapi/core/analysis/AnalyserNode.cpp +19 -56
- package/common/cpp/audioapi/core/analysis/AnalyserNode.h +3 -2
- package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +28 -26
- package/common/cpp/audioapi/core/effects/GainNode.cpp +9 -9
- package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +5 -2
- package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +56 -0
- package/common/cpp/audioapi/core/inputs/AudioRecorder.h +13 -13
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +14 -10
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +7 -6
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +5 -3
- package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +15 -10
- package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +35 -1
- package/common/cpp/audioapi/core/utils/AudioNodeManager.h +15 -1
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +108 -0
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +62 -0
- package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +48 -0
- package/common/cpp/audioapi/jsi/JsiPromise.cpp +3 -4
- package/common/cpp/audioapi/utils/AudioArray.h +1 -1
- package/common/cpp/audioapi/utils/CircularAudioArray.cpp +94 -0
- package/common/cpp/audioapi/utils/CircularAudioArray.h +26 -0
- package/ios/audioapi/ios/AudioAPIModule.h +13 -0
- package/ios/audioapi/ios/AudioAPIModule.mm +115 -6
- package/ios/audioapi/ios/core/IOSAudioRecorder.h +3 -10
- package/ios/audioapi/ios/core/IOSAudioRecorder.mm +15 -52
- package/ios/audioapi/ios/core/NativeAudioPlayer.m +2 -0
- package/ios/audioapi/ios/core/NativeAudioRecorder.m +7 -3
- package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +7 -0
- package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +12 -0
- package/ios/audioapi/ios/system/AudioEngine.h +5 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +7 -15
- package/ios/audioapi/ios/system/AudioSessionManager.h +3 -1
- package/ios/audioapi/ios/system/AudioSessionManager.mm +36 -17
- package/ios/audioapi/ios/system/LockScreenManager.h +3 -3
- package/ios/audioapi/ios/system/LockScreenManager.mm +36 -48
- package/ios/audioapi/ios/system/NotificationManager.h +3 -3
- package/ios/audioapi/ios/system/NotificationManager.mm +21 -29
- package/lib/commonjs/api.js +4 -4
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioBufferSourceNode.js +2 -2
- package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/core/AudioNode.js +8 -2
- package/lib/commonjs/core/AudioNode.js.map +1 -1
- package/lib/commonjs/core/AudioParam.js +2 -1
- package/lib/commonjs/core/AudioParam.js.map +1 -1
- package/lib/commonjs/core/AudioRecorder.js +11 -28
- package/lib/commonjs/core/AudioRecorder.js.map +1 -1
- package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -1
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/core/BiquadFilterNode.js +4 -4
- package/lib/commonjs/core/BiquadFilterNode.js.map +1 -1
- package/lib/commonjs/core/GainNode.js +1 -1
- package/lib/commonjs/core/GainNode.js.map +1 -1
- package/lib/commonjs/core/OscillatorNode.js +2 -2
- package/lib/commonjs/core/OscillatorNode.js.map +1 -1
- package/lib/commonjs/core/StereoPannerNode.js +1 -1
- package/lib/commonjs/core/StereoPannerNode.js.map +1 -1
- package/lib/commonjs/events/AudioEventEmitter.js +22 -0
- package/lib/commonjs/events/AudioEventEmitter.js.map +1 -0
- package/lib/commonjs/events/AudioEventSubscription.js +20 -0
- package/lib/commonjs/events/AudioEventSubscription.js.map +1 -0
- package/lib/commonjs/events/index.js +21 -0
- package/lib/commonjs/events/index.js.map +1 -0
- package/lib/commonjs/events/types.js +6 -0
- package/lib/commonjs/events/types.js.map +1 -0
- package/lib/commonjs/hooks/useSytemVolume.js +1 -1
- package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js +3 -3
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/commonjs/specs/index.js +2 -16
- package/lib/commonjs/specs/index.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +26 -26
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/module/api.js +2 -2
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioBufferSourceNode.js +2 -2
- package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/core/AudioNode.js +7 -2
- package/lib/module/core/AudioNode.js.map +1 -1
- package/lib/module/core/AudioParam.js +2 -1
- package/lib/module/core/AudioParam.js.map +1 -1
- package/lib/module/core/AudioRecorder.js +11 -28
- package/lib/module/core/AudioRecorder.js.map +1 -1
- package/lib/module/core/AudioScheduledSourceNode.js +4 -1
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BiquadFilterNode.js +4 -4
- package/lib/module/core/BiquadFilterNode.js.map +1 -1
- package/lib/module/core/GainNode.js +1 -1
- package/lib/module/core/GainNode.js.map +1 -1
- package/lib/module/core/OscillatorNode.js +2 -2
- package/lib/module/core/OscillatorNode.js.map +1 -1
- package/lib/module/core/StereoPannerNode.js +1 -1
- package/lib/module/core/StereoPannerNode.js.map +1 -1
- package/lib/module/events/AudioEventEmitter.js +16 -0
- package/lib/module/events/AudioEventEmitter.js.map +1 -0
- package/lib/module/events/AudioEventSubscription.js +15 -0
- package/lib/module/events/AudioEventSubscription.js.map +1 -0
- package/lib/module/events/index.js +6 -0
- package/lib/module/events/index.js.map +1 -0
- package/lib/module/events/types.js +4 -0
- package/lib/module/events/types.js.map +1 -0
- package/lib/module/hooks/useSytemVolume.js +1 -1
- package/lib/module/hooks/useSytemVolume.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js +3 -2
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/specs/index.js +2 -3
- package/lib/module/specs/index.js.map +1 -1
- package/lib/module/system/AudioManager.js +27 -27
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/typescript/api.d.ts +2 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +2 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioParam.d.ts +4 -2
- package/lib/typescript/core/AudioParam.d.ts.map +1 -1
- package/lib/typescript/core/AudioRecorder.d.ts +4 -14
- package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +3 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
- package/lib/typescript/events/AudioEventEmitter.d.ts +10 -0
- package/lib/typescript/events/AudioEventEmitter.d.ts.map +1 -0
- package/lib/typescript/events/AudioEventSubscription.d.ts +11 -0
- package/lib/typescript/events/AudioEventSubscription.d.ts.map +1 -0
- package/lib/typescript/events/index.d.ts +4 -0
- package/lib/typescript/events/index.d.ts.map +1 -0
- package/lib/typescript/events/types.d.ts +50 -0
- package/lib/typescript/events/types.d.ts.map +1 -0
- package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +10 -10
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +15 -3
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/lib/typescript/specs/index.d.ts +2 -3
- package/lib/typescript/specs/index.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +8 -4
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/system/types.d.ts +1 -34
- package/lib/typescript/system/types.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +0 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/api.ts +6 -3
- package/src/core/AudioBufferSourceNode.ts +2 -2
- package/src/core/AudioNode.ts +8 -3
- package/src/core/AudioParam.ts +5 -2
- package/src/core/AudioRecorder.ts +22 -62
- package/src/core/AudioScheduledSourceNode.ts +13 -2
- package/src/core/BiquadFilterNode.ts +4 -4
- package/src/core/GainNode.ts +1 -1
- package/src/core/OscillatorNode.ts +2 -2
- package/src/core/StereoPannerNode.ts +1 -1
- package/src/events/AudioEventEmitter.ts +29 -0
- package/src/events/AudioEventSubscription.ts +26 -0
- package/src/events/index.ts +4 -0
- package/src/events/types.ts +64 -0
- package/src/hooks/useSytemVolume.ts +2 -1
- package/src/interfaces.ts +19 -20
- package/src/specs/NativeAudioAPIModule.ts +23 -2
- package/src/specs/index.ts +2 -4
- package/src/system/AudioManager.ts +39 -38
- package/src/system/types.ts +1 -41
- package/src/types.ts +0 -8
- package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +0 -64
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +0 -88
- package/android/src/oldarch/NativeAudioManagerModuleSpec.java +0 -99
- package/ios/audioapi/ios/AudioManagerModule.h +0 -18
- package/ios/audioapi/ios/AudioManagerModule.mm +0 -93
- package/lib/commonjs/specs/NativeAudioManagerModule.js +0 -36
- package/lib/commonjs/specs/NativeAudioManagerModule.js.map +0 -1
- package/lib/module/specs/NativeAudioManagerModule.js +0 -33
- package/lib/module/specs/NativeAudioManagerModule.js.map +0 -1
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts +0 -15
- package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +0 -1
- package/src/specs/NativeAudioManagerModule.ts +0 -45
|
@@ -10,7 +10,10 @@ AudioAPIModule::AudioAPIModule(
|
|
|
10
10
|
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker)
|
|
11
11
|
: javaPart_(make_global(jThis)),
|
|
12
12
|
jsiRuntime_(jsiRuntime),
|
|
13
|
-
jsCallInvoker_(jsCallInvoker) {
|
|
13
|
+
jsCallInvoker_(jsCallInvoker) {
|
|
14
|
+
audioEventHandlerRegistry_ =
|
|
15
|
+
std::make_shared<AudioEventHandlerRegistry>(jsiRuntime, jsCallInvoker);
|
|
16
|
+
}
|
|
14
17
|
|
|
15
18
|
jni::local_ref<AudioAPIModule::jhybriddata> AudioAPIModule::initHybrid(
|
|
16
19
|
jni::alias_ref<jhybridobject> jThis,
|
|
@@ -26,10 +29,40 @@ void AudioAPIModule::registerNatives() {
|
|
|
26
29
|
registerHybrid({
|
|
27
30
|
makeNativeMethod("initHybrid", AudioAPIModule::initHybrid),
|
|
28
31
|
makeNativeMethod("injectJSIBindings", AudioAPIModule::injectJSIBindings),
|
|
32
|
+
makeNativeMethod(
|
|
33
|
+
"invokeHandlerWithEventNameAndEventBody",
|
|
34
|
+
AudioAPIModule::invokeHandlerWithEventNameAndEventBody),
|
|
29
35
|
});
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
void AudioAPIModule::injectJSIBindings() {
|
|
33
|
-
AudioAPIModuleInstaller::injectJSIBindings(
|
|
39
|
+
AudioAPIModuleInstaller::injectJSIBindings(
|
|
40
|
+
jsiRuntime_, jsCallInvoker_, audioEventHandlerRegistry_);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void AudioAPIModule::invokeHandlerWithEventNameAndEventBody(
|
|
44
|
+
jni::alias_ref<jni::JString> eventName,
|
|
45
|
+
jni::alias_ref<jni::JMap<jstring, jobject>> eventBody) {
|
|
46
|
+
std::unordered_map<std::string, EventValue> body = {};
|
|
47
|
+
|
|
48
|
+
for (const auto &entry : *eventBody) {
|
|
49
|
+
std::string name = entry.first->toStdString();
|
|
50
|
+
auto value = entry.second;
|
|
51
|
+
|
|
52
|
+
if (value->isInstanceOf(jni::JString::javaClassStatic())) {
|
|
53
|
+
body[name] = jni::static_ref_cast<jni::JString>(value)->toStdString();
|
|
54
|
+
} else if (value->isInstanceOf(jni::JInteger::javaClassStatic())) {
|
|
55
|
+
body[name] = jni::static_ref_cast<jni::JInteger>(value)->value();
|
|
56
|
+
} else if (value->isInstanceOf(jni::JDouble::javaClassStatic())) {
|
|
57
|
+
body[name] = jni::static_ref_cast<jni::JDouble>(value)->value();
|
|
58
|
+
} else if (value->isInstanceOf(jni::JFloat::javaClassStatic())) {
|
|
59
|
+
body[name] = jni::static_ref_cast<jni::JFloat>(value)->value();
|
|
60
|
+
} else if (value->isInstanceOf(jni::JBoolean::javaClassStatic())) {
|
|
61
|
+
body[name] = jni::static_ref_cast<jni::JBoolean>(value)->value();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
audioEventHandlerRegistry_->invokeHandlerWithEventBody(
|
|
66
|
+
eventName->toStdString(), body);
|
|
34
67
|
}
|
|
35
68
|
} // namespace audioapi
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <audioapi/AudioAPIModuleInstaller.h>
|
|
4
|
+
#include <audioapi/events/AudioEventHandlerRegistry.h>
|
|
4
5
|
|
|
5
6
|
#include <ReactCommon/CallInvokerHolder.h>
|
|
6
7
|
#include <fbjni/fbjni.h>
|
|
@@ -8,6 +9,7 @@
|
|
|
8
9
|
#include <react/jni/JMessageQueueThread.h>
|
|
9
10
|
#include <memory>
|
|
10
11
|
#include <utility>
|
|
12
|
+
#include <unordered_map>
|
|
11
13
|
|
|
12
14
|
namespace audioapi {
|
|
13
15
|
|
|
@@ -28,6 +30,7 @@ class AudioAPIModule : public jni::HybridClass<AudioAPIModule> {
|
|
|
28
30
|
static void registerNatives();
|
|
29
31
|
|
|
30
32
|
void injectJSIBindings();
|
|
33
|
+
void invokeHandlerWithEventNameAndEventBody(jni::alias_ref<jni::JString> eventName, jni::alias_ref<jni::JMap<jstring, jobject>> eventBody);
|
|
31
34
|
|
|
32
35
|
private:
|
|
33
36
|
friend HybridBase;
|
|
@@ -35,6 +38,7 @@ class AudioAPIModule : public jni::HybridClass<AudioAPIModule> {
|
|
|
35
38
|
jni::global_ref<AudioAPIModule::javaobject> javaPart_;
|
|
36
39
|
jsi::Runtime *jsiRuntime_;
|
|
37
40
|
std::shared_ptr<facebook::react::CallInvoker> jsCallInvoker_;
|
|
41
|
+
std::shared_ptr<AudioEventHandlerRegistry> audioEventHandlerRegistry_;
|
|
38
42
|
|
|
39
43
|
explicit AudioAPIModule(
|
|
40
44
|
jni::alias_ref<AudioAPIModule::jhybridobject> &jThis,
|
|
@@ -1,23 +1,17 @@
|
|
|
1
1
|
#include <audioapi/android/core/AndroidAudioRecorder.h>
|
|
2
2
|
#include <audioapi/core/Constants.h>
|
|
3
|
+
#include <audioapi/events/AudioEventHandlerRegistry.h>
|
|
3
4
|
#include <audioapi/utils/AudioArray.h>
|
|
4
5
|
#include <audioapi/utils/AudioBus.h>
|
|
6
|
+
#include <audioapi/utils/CircularAudioArray.h>
|
|
5
7
|
|
|
6
8
|
namespace audioapi {
|
|
7
9
|
|
|
8
10
|
AndroidAudioRecorder::AndroidAudioRecorder(
|
|
9
11
|
float sampleRate,
|
|
10
12
|
int bufferLength,
|
|
11
|
-
const std::
|
|
12
|
-
|
|
13
|
-
const std::function<void(std::shared_ptr<AudioBus>, int, double)>
|
|
14
|
-
&onAudioReady)
|
|
15
|
-
: AudioRecorder(
|
|
16
|
-
sampleRate,
|
|
17
|
-
bufferLength,
|
|
18
|
-
onError,
|
|
19
|
-
onStatusChange,
|
|
20
|
-
onAudioReady) {
|
|
13
|
+
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry)
|
|
14
|
+
: AudioRecorder(sampleRate, bufferLength, audioEventHandlerRegistry) {
|
|
21
15
|
AudioStreamBuilder builder;
|
|
22
16
|
builder.setSharingMode(SharingMode::Exclusive)
|
|
23
17
|
->setDirection(Direction::Input)
|
|
@@ -28,7 +22,6 @@ AndroidAudioRecorder::AndroidAudioRecorder(
|
|
|
28
22
|
->setSampleRateConversionQuality(SampleRateConversionQuality::Medium)
|
|
29
23
|
->setDataCallback(this)
|
|
30
24
|
->setSampleRate(static_cast<int>(sampleRate))
|
|
31
|
-
->setFramesPerDataCallback(bufferLength)
|
|
32
25
|
->openStream(mStream_);
|
|
33
26
|
}
|
|
34
27
|
|
|
@@ -43,29 +36,50 @@ AndroidAudioRecorder::~AndroidAudioRecorder() {
|
|
|
43
36
|
}
|
|
44
37
|
|
|
45
38
|
void AndroidAudioRecorder::start() {
|
|
39
|
+
if (isRunning_.load()) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
46
43
|
if (mStream_) {
|
|
47
44
|
mStream_->requestStart();
|
|
48
45
|
}
|
|
46
|
+
|
|
47
|
+
isRunning_.store(true);
|
|
49
48
|
}
|
|
50
49
|
|
|
51
50
|
void AndroidAudioRecorder::stop() {
|
|
51
|
+
if (!isRunning_.load()) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
isRunning_.store(false);
|
|
56
|
+
|
|
52
57
|
if (mStream_) {
|
|
53
58
|
mStream_->requestStop();
|
|
54
59
|
}
|
|
60
|
+
|
|
61
|
+
sendRemainingData();
|
|
55
62
|
}
|
|
56
63
|
|
|
57
64
|
DataCallbackResult AndroidAudioRecorder::onAudioReady(
|
|
58
65
|
oboe::AudioStream *oboeStream,
|
|
59
66
|
void *audioData,
|
|
60
67
|
int32_t numFrames) {
|
|
61
|
-
|
|
68
|
+
if (isRunning_.load()) {
|
|
69
|
+
auto *inputChannel = static_cast<float *>(audioData);
|
|
70
|
+
circularBuffer_->push_back(inputChannel, numFrames);
|
|
71
|
+
}
|
|
62
72
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
oboeStream->getTimestamp(CLOCK_MONOTONIC).value().timestamp);
|
|
73
|
+
while (circularBuffer_->getNumberOfAvailableFrames() >= bufferLength_) {
|
|
74
|
+
auto bus = std::make_shared<AudioBus>(bufferLength_, 1, sampleRate_);
|
|
75
|
+
auto *outputChannel = bus->getChannel(0)->getData();
|
|
67
76
|
|
|
68
|
-
|
|
77
|
+
circularBuffer_->pop_front(outputChannel, bufferLength_);
|
|
78
|
+
auto when = static_cast<double>(
|
|
79
|
+
oboeStream->getTimestamp(CLOCK_MONOTONIC).value().timestamp);
|
|
80
|
+
|
|
81
|
+
invokeOnAudioReadyCallback(bus, bufferLength_, when);
|
|
82
|
+
}
|
|
69
83
|
|
|
70
84
|
return DataCallbackResult::Continue;
|
|
71
85
|
}
|
|
@@ -16,9 +16,7 @@ class AndroidAudioRecorder : public AudioStreamDataCallback, public AudioRecorde
|
|
|
16
16
|
public:
|
|
17
17
|
AndroidAudioRecorder(float sampleRate,
|
|
18
18
|
int bufferLength,
|
|
19
|
-
const std::
|
|
20
|
-
const std::function<void(void)> &onStatusChange,
|
|
21
|
-
const std::function<void(std::shared_ptr<AudioBus>, int, double)> &onAudioReady);
|
|
19
|
+
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry);
|
|
22
20
|
|
|
23
21
|
~AndroidAudioRecorder() override;
|
|
24
22
|
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
package com.swmansion.audioapi
|
|
2
2
|
|
|
3
3
|
import com.facebook.jni.HybridData
|
|
4
|
+
import com.facebook.react.bridge.Promise
|
|
4
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
-
import com.facebook.react.bridge.
|
|
6
|
+
import com.facebook.react.bridge.ReadableArray
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
8
|
import com.facebook.react.common.annotations.FrameworkAPI
|
|
7
9
|
import com.facebook.react.module.annotations.ReactModule
|
|
8
10
|
import com.facebook.react.turbomodule.core.CallInvokerHolderImpl
|
|
11
|
+
import com.swmansion.audioapi.system.MediaSessionManager
|
|
12
|
+
import java.lang.ref.WeakReference
|
|
9
13
|
|
|
10
14
|
@OptIn(FrameworkAPI::class)
|
|
11
15
|
@ReactModule(name = AudioAPIModule.NAME)
|
|
@@ -16,6 +20,8 @@ class AudioAPIModule(
|
|
|
16
20
|
const val NAME = NativeAudioAPIModuleSpec.NAME
|
|
17
21
|
}
|
|
18
22
|
|
|
23
|
+
val reactContext: WeakReference<ReactApplicationContext> = WeakReference(reactContext)
|
|
24
|
+
|
|
19
25
|
private val mHybridData: HybridData
|
|
20
26
|
|
|
21
27
|
external fun initHybrid(
|
|
@@ -25,6 +31,11 @@ class AudioAPIModule(
|
|
|
25
31
|
|
|
26
32
|
private external fun injectJSIBindings()
|
|
27
33
|
|
|
34
|
+
external fun invokeHandlerWithEventNameAndEventBody(
|
|
35
|
+
eventName: String,
|
|
36
|
+
eventBody: Map<String, Any>,
|
|
37
|
+
)
|
|
38
|
+
|
|
28
39
|
init {
|
|
29
40
|
try {
|
|
30
41
|
System.loadLibrary("react-native-audio-api")
|
|
@@ -35,10 +46,53 @@ class AudioAPIModule(
|
|
|
35
46
|
}
|
|
36
47
|
}
|
|
37
48
|
|
|
38
|
-
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
39
49
|
override fun install(): Boolean {
|
|
50
|
+
MediaSessionManager.initialize(WeakReference(this), reactContext)
|
|
40
51
|
injectJSIBindings()
|
|
41
52
|
|
|
42
53
|
return true
|
|
43
54
|
}
|
|
55
|
+
|
|
56
|
+
override fun setLockScreenInfo(info: ReadableMap?) {
|
|
57
|
+
MediaSessionManager.setLockScreenInfo(info)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
override fun resetLockScreenInfo() {
|
|
61
|
+
MediaSessionManager.resetLockScreenInfo()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun enableRemoteCommand(
|
|
65
|
+
name: String?,
|
|
66
|
+
enabled: Boolean,
|
|
67
|
+
) {
|
|
68
|
+
MediaSessionManager.enableRemoteCommand(name!!, enabled)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
override fun setAudioSessionOptions(
|
|
72
|
+
category: String?,
|
|
73
|
+
mode: String?,
|
|
74
|
+
options: ReadableArray?,
|
|
75
|
+
) {
|
|
76
|
+
// noting to do here
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
override fun getDevicePreferredSampleRate(): Double = MediaSessionManager.getDevicePreferredSampleRate()
|
|
80
|
+
|
|
81
|
+
override fun observeAudioInterruptions(enabled: Boolean) {
|
|
82
|
+
MediaSessionManager.observeAudioInterruptions(enabled)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun observeVolumeChanges(enabled: Boolean) {
|
|
86
|
+
MediaSessionManager.observeVolumeChanges(enabled)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override fun requestRecordingPermissions(promise: Promise?) {
|
|
90
|
+
val res = MediaSessionManager.requestRecordingPermissions(currentActivity)
|
|
91
|
+
promise!!.resolve(res)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
override fun checkRecordingPermissions(promise: Promise?) {
|
|
95
|
+
val res = MediaSessionManager.checkRecordingPermissions()
|
|
96
|
+
promise!!.resolve(res)
|
|
97
|
+
}
|
|
44
98
|
}
|
|
@@ -10,7 +10,6 @@ import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
|
10
10
|
@ReactModuleList(
|
|
11
11
|
nativeModules = [
|
|
12
12
|
AudioAPIModule::class,
|
|
13
|
-
AudioManagerModule::class,
|
|
14
13
|
],
|
|
15
14
|
)
|
|
16
15
|
class AudioAPIPackage : BaseReactPackage() {
|
|
@@ -20,7 +19,6 @@ class AudioAPIPackage : BaseReactPackage() {
|
|
|
20
19
|
): NativeModule? {
|
|
21
20
|
when (name) {
|
|
22
21
|
AudioAPIModule.NAME -> return AudioAPIModule(reactContext)
|
|
23
|
-
AudioManagerModule.NAME -> return AudioManagerModule(reactContext)
|
|
24
22
|
}
|
|
25
23
|
return null
|
|
26
24
|
}
|
|
@@ -40,16 +38,6 @@ class AudioAPIPackage : BaseReactPackage() {
|
|
|
40
38
|
isTurboModule = isTurboModule,
|
|
41
39
|
)
|
|
42
40
|
|
|
43
|
-
moduleInfos[AudioManagerModule.NAME] =
|
|
44
|
-
ReactModuleInfo(
|
|
45
|
-
AudioManagerModule.NAME,
|
|
46
|
-
AudioManagerModule.NAME,
|
|
47
|
-
canOverrideExistingModule = true,
|
|
48
|
-
needsEagerInit = false,
|
|
49
|
-
hasConstants = true,
|
|
50
|
-
isCxxModule = false,
|
|
51
|
-
isTurboModule = false,
|
|
52
|
-
)
|
|
53
41
|
moduleInfos
|
|
54
42
|
}
|
|
55
43
|
}
|
|
@@ -4,11 +4,14 @@ import android.media.AudioFocusRequest
|
|
|
4
4
|
import android.media.AudioManager
|
|
5
5
|
import android.os.Build
|
|
6
6
|
import android.util.Log
|
|
7
|
+
import com.swmansion.audioapi.AudioAPIModule
|
|
8
|
+
import java.lang.ref.WeakReference
|
|
9
|
+
import java.util.HashMap
|
|
7
10
|
|
|
8
11
|
class AudioFocusListener(
|
|
9
|
-
private val audioManager: AudioManager
|
|
10
|
-
val
|
|
11
|
-
private val lockScreenManager: LockScreenManager
|
|
12
|
+
private val audioManager: WeakReference<AudioManager>,
|
|
13
|
+
private val audioAPIModule: WeakReference<AudioAPIModule>,
|
|
14
|
+
private val lockScreenManager: WeakReference<LockScreenManager>,
|
|
12
15
|
) : AudioManager.OnAudioFocusChangeListener {
|
|
13
16
|
private var playOnAudioFocus = false
|
|
14
17
|
private var focusRequest: AudioFocusRequest? = null
|
|
@@ -18,17 +21,37 @@ class AudioFocusListener(
|
|
|
18
21
|
when (focusChange) {
|
|
19
22
|
AudioManager.AUDIOFOCUS_LOSS -> {
|
|
20
23
|
playOnAudioFocus = false
|
|
21
|
-
|
|
24
|
+
val body =
|
|
25
|
+
HashMap<String, Any>().apply {
|
|
26
|
+
put("value", "began")
|
|
27
|
+
put("shouldResume", false)
|
|
28
|
+
}
|
|
29
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("interruption", body)
|
|
22
30
|
}
|
|
23
31
|
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
|
|
24
|
-
playOnAudioFocus = lockScreenManager.isPlaying
|
|
25
|
-
|
|
32
|
+
playOnAudioFocus = lockScreenManager.get()?.isPlaying == true
|
|
33
|
+
val body =
|
|
34
|
+
HashMap<String, Any>().apply {
|
|
35
|
+
put("value", "began")
|
|
36
|
+
put("shouldResume", playOnAudioFocus)
|
|
37
|
+
}
|
|
38
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("interruption", body)
|
|
26
39
|
}
|
|
27
40
|
AudioManager.AUDIOFOCUS_GAIN -> {
|
|
28
41
|
if (playOnAudioFocus) {
|
|
29
|
-
|
|
42
|
+
val body =
|
|
43
|
+
HashMap<String, Any>().apply {
|
|
44
|
+
put("value", "ended")
|
|
45
|
+
put("shouldResume", true)
|
|
46
|
+
}
|
|
47
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("interruption", body)
|
|
30
48
|
} else {
|
|
31
|
-
|
|
49
|
+
val body =
|
|
50
|
+
HashMap<String, Any>().apply {
|
|
51
|
+
put("value", "ended")
|
|
52
|
+
put("shouldResume", false)
|
|
53
|
+
}
|
|
54
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("interruption", body)
|
|
32
55
|
}
|
|
33
56
|
|
|
34
57
|
playOnAudioFocus = false
|
|
@@ -44,17 +67,17 @@ class AudioFocusListener(
|
|
|
44
67
|
.setOnAudioFocusChangeListener(this)
|
|
45
68
|
.build()
|
|
46
69
|
|
|
47
|
-
audioManager.requestAudioFocus(focusRequest!!)
|
|
70
|
+
audioManager.get()?.requestAudioFocus(focusRequest!!)
|
|
48
71
|
} else {
|
|
49
|
-
audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
|
72
|
+
audioManager.get()?.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
|
50
73
|
}
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
fun abandonAudioFocus() {
|
|
54
77
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && this.focusRequest != null) {
|
|
55
|
-
audioManager.abandonAudioFocusRequest(focusRequest!!)
|
|
78
|
+
audioManager.get()?.abandonAudioFocusRequest(focusRequest!!)
|
|
56
79
|
} else {
|
|
57
|
-
audioManager.abandonAudioFocus(this)
|
|
80
|
+
audioManager.get()?.abandonAudioFocus(this)
|
|
58
81
|
}
|
|
59
82
|
}
|
|
60
83
|
}
|
|
@@ -14,20 +14,20 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
14
14
|
import com.facebook.react.bridge.ReadableType
|
|
15
15
|
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper.Companion.instance
|
|
16
16
|
import java.io.IOException
|
|
17
|
+
import java.lang.ref.WeakReference
|
|
17
18
|
import java.net.URL
|
|
18
19
|
|
|
19
20
|
class LockScreenManager(
|
|
20
|
-
private val reactContext: ReactApplicationContext
|
|
21
|
-
private val mediaSession: MediaSessionCompat
|
|
22
|
-
private val mediaNotificationManager: MediaNotificationManager
|
|
23
|
-
val channelId: String,
|
|
21
|
+
private val reactContext: WeakReference<ReactApplicationContext>,
|
|
22
|
+
private val mediaSession: WeakReference<MediaSessionCompat>,
|
|
23
|
+
private val mediaNotificationManager: WeakReference<MediaNotificationManager>,
|
|
24
24
|
) {
|
|
25
25
|
private var pb: PlaybackStateCompat.Builder = PlaybackStateCompat.Builder()
|
|
26
26
|
private var state: PlaybackStateCompat = pb.build()
|
|
27
27
|
private var controls: Long = 0
|
|
28
28
|
var isPlaying: Boolean = false
|
|
29
29
|
|
|
30
|
-
private var nb: NotificationCompat.Builder = NotificationCompat.Builder(reactContext
|
|
30
|
+
private var nb: NotificationCompat.Builder = NotificationCompat.Builder(reactContext.get()!!, MediaSessionManager.CHANNEL_ID)
|
|
31
31
|
|
|
32
32
|
private var artworkThread: Thread? = null
|
|
33
33
|
|
|
@@ -49,7 +49,7 @@ class LockScreenManager(
|
|
|
49
49
|
|
|
50
50
|
updateNotificationMediaStyle()
|
|
51
51
|
|
|
52
|
-
mediaNotificationManager.updateActions(controls)
|
|
52
|
+
mediaNotificationManager.get()?.updateActions(controls)
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
fun setLockScreenInfo(info: ReadableMap?) {
|
|
@@ -112,17 +112,17 @@ class LockScreenManager(
|
|
|
112
112
|
try {
|
|
113
113
|
val bitmap: Bitmap? = artwork?.let { loadArtwork(it, artworkLocal) }
|
|
114
114
|
|
|
115
|
-
val currentMetadata
|
|
115
|
+
val currentMetadata = mediaSession.get()?.controller?.metadata
|
|
116
116
|
val newBuilder =
|
|
117
117
|
MediaMetadataCompat.Builder(
|
|
118
118
|
currentMetadata,
|
|
119
119
|
)
|
|
120
|
-
mediaSession.setMetadata(
|
|
120
|
+
mediaSession.get()?.setMetadata(
|
|
121
121
|
newBuilder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, bitmap).build(),
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
nb.setLargeIcon(bitmap)
|
|
125
|
-
mediaNotificationManager.show(nb, isPlaying)
|
|
125
|
+
mediaNotificationManager.get()?.show(nb, isPlaying)
|
|
126
126
|
|
|
127
127
|
artworkThread = null
|
|
128
128
|
} catch (ex: Exception) {
|
|
@@ -164,17 +164,17 @@ class LockScreenManager(
|
|
|
164
164
|
|
|
165
165
|
updatePlaybackState(this.playbackState)
|
|
166
166
|
|
|
167
|
-
mediaSession.setMetadata(md.build())
|
|
168
|
-
mediaSession.setActive(true)
|
|
169
|
-
mediaNotificationManager.show(nb, isPlaying)
|
|
167
|
+
mediaSession.get()?.setMetadata(md.build())
|
|
168
|
+
mediaSession.get()?.setActive(true)
|
|
169
|
+
mediaNotificationManager.get()?.show(nb, isPlaying)
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
fun resetLockScreenInfo() {
|
|
173
173
|
if (artworkThread != null && artworkThread!!.isAlive) artworkThread!!.interrupt()
|
|
174
174
|
artworkThread = null
|
|
175
175
|
|
|
176
|
-
mediaNotificationManager.hide()
|
|
177
|
-
mediaSession.setActive(false)
|
|
176
|
+
mediaNotificationManager.get()?.hide()
|
|
177
|
+
mediaSession.get()?.setActive(false)
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
fun enableRemoteCommand(
|
|
@@ -183,14 +183,15 @@ class LockScreenManager(
|
|
|
183
183
|
) {
|
|
184
184
|
var controlValue = 0L
|
|
185
185
|
when (name) {
|
|
186
|
-
"
|
|
187
|
-
"
|
|
188
|
-
"
|
|
189
|
-
"
|
|
190
|
-
"
|
|
191
|
-
"
|
|
192
|
-
"
|
|
193
|
-
"
|
|
186
|
+
"remotePlay" -> controlValue = PlaybackStateCompat.ACTION_PLAY
|
|
187
|
+
"remotePause" -> controlValue = PlaybackStateCompat.ACTION_PAUSE
|
|
188
|
+
"remoteStop" -> controlValue = PlaybackStateCompat.ACTION_STOP
|
|
189
|
+
"remoteTogglePlayPause" -> controlValue = PlaybackStateCompat.ACTION_PLAY_PAUSE
|
|
190
|
+
"remoteNextTrack" -> controlValue = PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
|
191
|
+
"remotePreviousTrack" -> controlValue = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
|
192
|
+
"remoteSkipForward" -> controlValue = PlaybackStateCompat.ACTION_FAST_FORWARD
|
|
193
|
+
"remoteSkipBackward" -> controlValue = PlaybackStateCompat.ACTION_REWIND
|
|
194
|
+
"remoteChangePlaybackPosition" -> controlValue = PlaybackStateCompat.ACTION_SEEK_TO
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
controls =
|
|
@@ -200,16 +201,16 @@ class LockScreenManager(
|
|
|
200
201
|
controls and controlValue.inv()
|
|
201
202
|
}
|
|
202
203
|
|
|
203
|
-
mediaNotificationManager.updateActions(controls)
|
|
204
|
+
mediaNotificationManager.get()?.updateActions(controls)
|
|
204
205
|
pb.setActions(controls)
|
|
205
206
|
|
|
206
207
|
state = pb.build()
|
|
207
|
-
mediaSession.setPlaybackState(state)
|
|
208
|
+
mediaSession.get()?.setPlaybackState(state)
|
|
208
209
|
|
|
209
210
|
updateNotificationMediaStyle()
|
|
210
211
|
|
|
211
|
-
if (mediaSession.isActive) {
|
|
212
|
-
mediaNotificationManager.show(nb, isPlaying)
|
|
212
|
+
if (mediaSession.get()?.isActive == true) {
|
|
213
|
+
mediaNotificationManager.get()?.show(nb, isPlaying)
|
|
213
214
|
}
|
|
214
215
|
}
|
|
215
216
|
|
|
@@ -224,7 +225,7 @@ class LockScreenManager(
|
|
|
224
225
|
if (local && !url.startsWith("http")) {
|
|
225
226
|
// Gets the drawable from the RN's helper for local resources
|
|
226
227
|
val helper = instance
|
|
227
|
-
val image = helper.getResourceDrawable(reactContext
|
|
228
|
+
val image = helper.getResourceDrawable(reactContext.get()!!, url)
|
|
228
229
|
|
|
229
230
|
bitmap =
|
|
230
231
|
if (image is BitmapDrawable) {
|
|
@@ -255,14 +256,14 @@ class LockScreenManager(
|
|
|
255
256
|
pb.setState(playbackState, elapsedTime, speed)
|
|
256
257
|
pb.setActions(controls)
|
|
257
258
|
state = pb.build()
|
|
258
|
-
mediaSession.setPlaybackState(state)
|
|
259
|
+
mediaSession.get()?.setPlaybackState(state)
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
private fun hasControl(control: Long): Boolean = (controls and control) == control
|
|
262
263
|
|
|
263
264
|
private fun updateNotificationMediaStyle() {
|
|
264
265
|
val style = MediaStyle()
|
|
265
|
-
style.setMediaSession(mediaSession.sessionToken)
|
|
266
|
+
style.setMediaSession(mediaSession.get()?.sessionToken)
|
|
266
267
|
var controlCount = 0
|
|
267
268
|
if (hasControl(PlaybackStateCompat.ACTION_PLAY) ||
|
|
268
269
|
hasControl(PlaybackStateCompat.ACTION_PAUSE) ||
|
|
@@ -21,9 +21,7 @@ import com.swmansion.audioapi.R
|
|
|
21
21
|
import java.lang.ref.WeakReference
|
|
22
22
|
|
|
23
23
|
class MediaNotificationManager(
|
|
24
|
-
val reactContext: ReactApplicationContext
|
|
25
|
-
val notificationId: Int,
|
|
26
|
-
val channelId: String,
|
|
24
|
+
private val reactContext: WeakReference<ReactApplicationContext>,
|
|
27
25
|
) {
|
|
28
26
|
private var smallIcon: Int = R.drawable.play
|
|
29
27
|
private var customIcon: Int = 0
|
|
@@ -80,12 +78,12 @@ class MediaNotificationManager(
|
|
|
80
78
|
|
|
81
79
|
builder.setSmallIcon(if (customIcon != 0) customIcon else smallIcon)
|
|
82
80
|
|
|
83
|
-
val packageName: String = reactContext.packageName
|
|
84
|
-
val openApp: Intent? = reactContext.packageManager
|
|
81
|
+
val packageName: String? = reactContext.get()?.packageName
|
|
82
|
+
val openApp: Intent? = reactContext.get()?.packageManager?.getLaunchIntentForPackage(packageName!!)
|
|
85
83
|
try {
|
|
86
84
|
builder.setContentIntent(
|
|
87
85
|
PendingIntent.getActivity(
|
|
88
|
-
reactContext,
|
|
86
|
+
reactContext.get(),
|
|
89
87
|
0,
|
|
90
88
|
openApp,
|
|
91
89
|
PendingIntent.FLAG_IMMUTABLE,
|
|
@@ -96,10 +94,10 @@ class MediaNotificationManager(
|
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
val remove = Intent(REMOVE_NOTIFICATION)
|
|
99
|
-
remove.putExtra(PACKAGE_NAME, reactContext.applicationInfo
|
|
97
|
+
remove.putExtra(PACKAGE_NAME, reactContext.get()?.applicationInfo?.packageName)
|
|
100
98
|
builder.setDeleteIntent(
|
|
101
99
|
PendingIntent.getBroadcast(
|
|
102
|
-
reactContext,
|
|
100
|
+
reactContext.get(),
|
|
103
101
|
0,
|
|
104
102
|
remove,
|
|
105
103
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
|
|
@@ -115,8 +113,8 @@ class MediaNotificationManager(
|
|
|
115
113
|
builder: NotificationCompat.Builder?,
|
|
116
114
|
isPlaying: Boolean,
|
|
117
115
|
) {
|
|
118
|
-
NotificationManagerCompat.from(reactContext).notify(
|
|
119
|
-
|
|
116
|
+
NotificationManagerCompat.from(reactContext.get()!!).notify(
|
|
117
|
+
MediaSessionManager.NOTIFICATION_ID,
|
|
120
118
|
prepareNotification(
|
|
121
119
|
builder!!,
|
|
122
120
|
isPlaying,
|
|
@@ -125,15 +123,15 @@ class MediaNotificationManager(
|
|
|
125
123
|
}
|
|
126
124
|
|
|
127
125
|
fun hide() {
|
|
128
|
-
NotificationManagerCompat.from(reactContext).cancel(
|
|
126
|
+
NotificationManagerCompat.from(reactContext.get()!!).cancel(MediaSessionManager.NOTIFICATION_ID)
|
|
129
127
|
|
|
130
128
|
try {
|
|
131
129
|
val myIntent =
|
|
132
130
|
Intent(
|
|
133
|
-
reactContext,
|
|
131
|
+
reactContext.get(),
|
|
134
132
|
NotificationService::class.java,
|
|
135
133
|
)
|
|
136
|
-
reactContext.stopService(myIntent)
|
|
134
|
+
reactContext.get()?.stopService(myIntent)
|
|
137
135
|
} catch (e: java.lang.Exception) {
|
|
138
136
|
Log.w("AudioManagerModule", "Error stopping service: ${e.message}")
|
|
139
137
|
}
|
|
@@ -188,9 +186,9 @@ class MediaNotificationManager(
|
|
|
188
186
|
return oldAction
|
|
189
187
|
}
|
|
190
188
|
|
|
191
|
-
val r: Resources = reactContext.resources
|
|
192
|
-
val packageName: String = reactContext.packageName
|
|
193
|
-
val icon = r
|
|
189
|
+
val r: Resources? = reactContext.get()?.resources
|
|
190
|
+
val packageName: String? = reactContext.get()?.packageName
|
|
191
|
+
val icon = r?.getIdentifier(iconName, "drawable", packageName)
|
|
194
192
|
|
|
195
193
|
val keyCode = PlaybackStateCompat.toKeyCode(action)
|
|
196
194
|
val intent = Intent(MEDIA_BUTTON)
|
|
@@ -198,13 +196,13 @@ class MediaNotificationManager(
|
|
|
198
196
|
intent.putExtra(ContactsContract.Directory.PACKAGE_NAME, packageName)
|
|
199
197
|
val i =
|
|
200
198
|
PendingIntent.getBroadcast(
|
|
201
|
-
reactContext,
|
|
199
|
+
reactContext.get(),
|
|
202
200
|
keyCode,
|
|
203
201
|
intent,
|
|
204
202
|
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
|
|
205
203
|
)
|
|
206
204
|
|
|
207
|
-
return NotificationCompat.Action(icon
|
|
205
|
+
return NotificationCompat.Action(icon!!, title, i)
|
|
208
206
|
}
|
|
209
207
|
|
|
210
208
|
class NotificationService : Service() {
|
|
@@ -232,8 +230,8 @@ class MediaNotificationManager(
|
|
|
232
230
|
ContextCompat.startForegroundService(this, intent)
|
|
233
231
|
notification =
|
|
234
232
|
MediaSessionManager.mediaNotificationManager
|
|
235
|
-
.prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.
|
|
236
|
-
startForeground(MediaSessionManager.
|
|
233
|
+
.prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.CHANNEL_ID), false)
|
|
234
|
+
startForeground(MediaSessionManager.NOTIFICATION_ID, notification)
|
|
237
235
|
}
|
|
238
236
|
}
|
|
239
237
|
|
|
@@ -242,8 +240,8 @@ class MediaNotificationManager(
|
|
|
242
240
|
try {
|
|
243
241
|
notification =
|
|
244
242
|
MediaSessionManager.mediaNotificationManager
|
|
245
|
-
.prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.
|
|
246
|
-
startForeground(MediaSessionManager.
|
|
243
|
+
.prepareNotification(NotificationCompat.Builder(this, MediaSessionManager.CHANNEL_ID), false)
|
|
244
|
+
startForeground(MediaSessionManager.NOTIFICATION_ID, notification)
|
|
247
245
|
} catch (ex: Exception) {
|
|
248
246
|
Log.w("AudioManagerModule", "Error starting service: ${ex.message}")
|
|
249
247
|
}
|