11package com .rtmalone .volumecontrol ;
22
3+ import android .app .Activity ;
34import android .content .Context ;
5+ import android .content .Intent ;
6+ import android .content .BroadcastReceiver ;
7+ import android .content .IntentFilter ;
8+ import android .media .AudioManager ;
9+
410import android .support .annotation .Nullable ;
511import android .util .Log ;
6- import android .media .AudioManager ;
712
13+ import com .facebook .react .bridge .ActivityEventListener ;
814import com .facebook .react .bridge .Arguments ;
15+ import com .facebook .react .bridge .LifecycleEventListener ;
916import com .facebook .react .bridge .ReactApplicationContext ;
1017import com .facebook .react .bridge .ReactContext ;
1118import com .facebook .react .bridge .ReactContextBaseJavaModule ;
1421import com .facebook .react .bridge .Promise ;
1522import 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}
0 commit comments