Skip to content

Commit 2dd41b2

Browse files
authored
Android volume change event (#7)
* Adds volume change event in Android * Updates podspec and ios module with correct name * Adds getVolume method to README * Use correct package name in README example * Update event Type
1 parent 9f4389c commit 2dd41b2

File tree

5 files changed

+114
-26
lines changed

5 files changed

+114
-26
lines changed

README.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,25 @@ This component only exposes an api to update device volume and listens for `Volu
4646

4747
import VolumeControl, {
4848
VolumeControlEvents
49-
} from "react-native-volume-controller";
49+
} from "react-native-volume-control";
5050
import Slider from '@react-native-community/slider';
5151

5252
class App extends React.Component {
53+
state = {
54+
volume: 0
55+
}
5356

54-
componentDidMount() {
55-
// Add and store event listener
56-
this.volEvent = VolumeControlEvents.addListener(
57-
"VolumeChanged",
58-
this.volumeEvent
59-
);
60-
}
57+
async componentDidMount() {
58+
this.setState({
59+
volume: await VolumeControl.getVolume()
60+
});
61+
62+
// Add and store event listener
63+
this.volEvent = VolumeControlEvents.addListener(
64+
"VolumeChanged",
65+
this.volumeEvent
66+
);
67+
}
6168

6269
// Updates Slider UI when hardware buttons change volume
6370
volumeEvent = event => {

RNVolumeController.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ require 'json'
33
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
44

55
Pod::Spec.new do |s|
6-
s.name = "RNVolumeController"
6+
s.name = "RNVolumeControl"
77
s.version = package['version']
88
s.summary = package['description']
9-
s.homepage = "https://github.com/tlenclos/react-native-volume-controller"
9+
s.homepage = "https://github.com/rtmalone/react-native-volume-control"
1010
s.license = package['license']
1111
s.author = package['author']
1212
s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" }
@@ -16,6 +16,6 @@ Pod::Spec.new do |s|
1616
s.preserve_paths = "**/*.js"
1717

1818
s.subspec 'Main' do |ss|
19-
ss.source_files = "ios/ReactNativeVolumeController.{h,m}"
19+
ss.source_files = "ios/RNVolumeControl.{h,m}"
2020
end
2121
end
Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
package com.rtmalone.volumecontrol;
22

3+
import android.app.Activity;
34
import android.content.Context;
5+
import android.content.Intent;
6+
import android.content.BroadcastReceiver;
7+
import android.content.IntentFilter;
8+
import android.media.AudioManager;
9+
410
import android.support.annotation.Nullable;
511
import android.util.Log;
6-
import android.media.AudioManager;
712

13+
import com.facebook.react.bridge.ActivityEventListener;
814
import com.facebook.react.bridge.Arguments;
15+
import com.facebook.react.bridge.LifecycleEventListener;
916
import com.facebook.react.bridge.ReactApplicationContext;
1017
import com.facebook.react.bridge.ReactContext;
1118
import com.facebook.react.bridge.ReactContextBaseJavaModule;
@@ -14,39 +21,79 @@
1421
import com.facebook.react.bridge.Promise;
1522
import com.facebook.react.modules.core.DeviceEventManagerModule;
1623

17-
public class RNVolumeControlModule extends ReactContextBaseJavaModule {
24+
public class RNVolumeControlModule extends ReactContextBaseJavaModule
25+
implements ActivityEventListener, LifecycleEventListener {
1826

19-
private ReactApplicationContext context;
27+
private String TAG = RNVolumeControlModule.class.getSimpleName();
28+
private ReactApplicationContext rContext;
2029
private float max_volume = (float) 0.0;
2130
private AudioManager am;
31+
private VolumeBroadcastReceiver volumeBR;
2232

2333
public RNVolumeControlModule(ReactApplicationContext reactContext) {
2434
super(reactContext);
25-
this.context = reactContext;
35+
this.rContext = reactContext;
2636
}
2737

2838
@Override
2939
public String getName() {
3040
return "VolumeControl";
3141
}
3242

43+
@Override
44+
public void onNewIntent(Intent intent) {
45+
}
46+
47+
@Override
48+
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
49+
}
50+
51+
@Override
52+
public void onHostResume() {
53+
registerVolumeReceiver();
54+
}
55+
56+
@Override
57+
public void onHostPause() {
58+
unregisterVolumeReceiver();
59+
}
60+
61+
@Override
62+
public void onHostDestroy() {
63+
}
64+
3365
@Override
3466
public void initialize() {
3567
super.initialize();
3668

3769
try {
38-
am = (AudioManager) this.context.getSystemService(Context.AUDIO_SERVICE);
70+
am = (AudioManager) this.rContext.getSystemService(Context.AUDIO_SERVICE);
3971
max_volume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
72+
volumeBR = new VolumeBroadcastReceiver();
73+
registerVolumeReceiver();
4074
} catch (Exception e) {
41-
Log.e("ERROR", e.getMessage());
75+
Log.e(TAG, "Initialize Error", e);
4276
}
4377
}
4478

45-
// public void sendEvent(ReactContext reactContext, String eventName, @Nullable
46-
// WritableMap params) {
47-
// this.context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName,
48-
// params);
49-
// }
79+
private void registerVolumeReceiver() {
80+
if (!volumeBR.isRegistered()) {
81+
IntentFilter filter = new IntentFilter("android.media.VOLUME_CHANGED_ACTION");
82+
this.rContext.registerReceiver(volumeBR, filter);
83+
volumeBR.setRegistered(true);
84+
}
85+
}
86+
87+
private void unregisterVolumeReceiver() {
88+
if (volumeBR.isRegistered()) {
89+
this.rContext.unregisterReceiver(volumeBR);
90+
volumeBR.setRegistered(false);
91+
}
92+
}
93+
94+
public void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
95+
this.rContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, params);
96+
}
5097

5198
@ReactMethod
5299
public void getVolume(Promise promise) {
@@ -55,10 +102,44 @@ public void getVolume(Promise promise) {
55102

56103
@ReactMethod
57104
public void change(float volume) {
58-
am.setStreamVolume(AudioManager.STREAM_MUSIC, (int) (volume * max_volume), 0);
105+
unregisterVolumeReceiver();
106+
try {
107+
am.setStreamVolume(AudioManager.STREAM_MUSIC, (int) (volume * max_volume), 0);
108+
} catch (Exception e) {
109+
Log.e(TAG, "Error Setting Volume", e);
110+
}
111+
registerVolumeReceiver();
59112
}
60113

61114
private float getNormalizedVolume() {
62-
return am.getStreamVolume(AudioManager.STREAM_MUSIC) * 1.0f / am.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
115+
return am.getStreamVolume(AudioManager.STREAM_MUSIC) * 1.0f / max_volume;
116+
}
117+
118+
public class VolumeBroadcastReceiver extends BroadcastReceiver {
119+
120+
private boolean isRegistered = false;
121+
122+
public void setRegistered(boolean registered) {
123+
isRegistered = registered;
124+
}
125+
126+
public boolean isRegistered() {
127+
return isRegistered;
128+
}
129+
130+
@Override
131+
public void onReceive(Context context, Intent intent) {
132+
if (intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")) {
133+
float volume = getNormalizedVolume();
134+
WritableMap params = Arguments.createMap();
135+
params.putDouble("volume", volume);
136+
try {
137+
sendEvent(rContext, "VolumeChanged", params);
138+
} catch (RuntimeException e) {
139+
// Possible to interact with volume before JS bundle execution is finished.
140+
// This is here to avoid app crashing.
141+
}
142+
}
143+
}
63144
}
64145
}

index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ declare namespace RNVolumeControl {
1111
volume: number;
1212
};
1313

14-
export class RNVCEvents extends NativeEventEmitter {}
14+
export class VolumeControlEvents extends NativeEventEmitter {}
1515
}

ios/RNVolumeControl/RNVolumeControl.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ @implementation RNVolumeControl {
1818
bool hasListeners;
1919
}
2020

21-
RCT_EXPORT_MODULE()
21+
RCT_EXPORT_MODULE(VolumeControl)
2222

2323
- (NSArray<NSString *> *)supportedEvents
2424
{

0 commit comments

Comments
 (0)