From 1777c63c07a65d3b64bfeaa111b1355782fda5f8 Mon Sep 17 00:00:00 2001 From: luckydog7 Date: Sun, 18 May 2025 22:18:52 +0300 Subject: [PATCH 1/5] Add AudioManger --- extension/androidtools/media/AudioManager.hx | 293 ++++++++++++++++++ .../main/java/org/haxe/extension/Tools.java | 27 ++ 2 files changed, 320 insertions(+) create mode 100644 extension/androidtools/media/AudioManager.hx diff --git a/extension/androidtools/media/AudioManager.hx b/extension/androidtools/media/AudioManager.hx new file mode 100644 index 00000000..36f172e4 --- /dev/null +++ b/extension/androidtools/media/AudioManager.hx @@ -0,0 +1,293 @@ +package android.media; + +import android.jni.JNICache; +import cpp.RawPointer; +import lime.app.Event; +import lime.system.JNI; + +#if (!android && !native) +#error 'extension-androidtools is not supported on your current platform' +#end + + +/** + * Utility class for managing volume and ringer mode control. + */ +class AudioManager +{ + /** + * Constant representing the stream type that can be used for changing volume of that stream: voice call. + */ + public static final STREAM_VOICE_CALL:Int = 0; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: system sounds. + */ + public static final STREAM_SYSTEM:Int = 1; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: phone ring. + */ + public static final STREAM_RING:Int = 2; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: music playback. + */ + public static final STREAM_MUSIC:Int = 3; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: alarm. + */ + public static final STREAM_ALARM:Int = 4; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: notification. + */ + public static final STREAM_NOTIFICATION:Int = 5; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: phone calls when connected to bluetooth. + */ + public static final STREAM_BLUETOOTH_SCO:Int = 6; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: enforced system sounds. + */ + public static final STREAM_SYSTEM_ENFORCED:Int = 7; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: DTMF Tones. + */ + public static final STREAM_DTMF:Int = 8; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: tts transmitted through the speaker. + */ + public static final STREAM_TTS:Int = 9; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: accessibility prompts. + */ + public static final STREAM_ACCESSIBILITY:Int = 10; + + /** + * Constant representing the stream type that can be used for changing volume of that stream: virtual assistant. + */ + public static final STREAM_ASSISTANT:Int = 11; + + + /** + * Constant representing the direction of volume adjustment: raise the volume. + */ + public static final ADJUST_RAISE:Int = 1; + + /** + * Constant representing the direction of volume adjustment: lower the volume. + */ + public static final ADJUST_LOWER:Int = -1; + + /** + * Constant representing the direction of volume adjustment: same volume. + */ + public static final ADJUST_SAME:Int = 0; + + /** + * Constant representing the direction of volume adjustment: mute the volume. + */ + public static final ADJUST_MUTE:Int = -100; + + /** + * Constant representing the direction of volume adjustment: unmute the volume. + */ + public static final ADJUST_UNMUTE:Int = 100; + + /** + * Constant representing the direction of volume adjustment: toggle mute state. + */ + public static final ADJUST_TOGGLE_MUTE:Int = 101; + + + /** + * Constant representing the flags for volume adjustment: show ui. + */ + public static final FLAG_SHOW_UI:Int = 1 << 0; + + /** + * Constant representing the flags for volume adjustment: include ringer modes. + */ + public static final FLAG_ALLOW_RINGER_MODES:Int = 1 << 1; + /** + * Constant representing the flags for volume adjustment: play sound when changing volume. + */ + public static final FLAG_PLAY_SOUND:Int = 1 << 2; + + /** + * Constant representing the flags for volume adjustment: remove any sound and vibrate. + */ + public static final FLAG_REMOVE_SOUND_AND_VIBRATE:Int = 1 << 3; + + /** + * Constant representing the flags for volume adjustment: vibrate if going into the vibrate ringer mode. + */ + public static final FLAG_VIBRATE:Int = 1 << 4; + + + /** + * Constant representing the flags for audio focus status: nothing changed. + */ + public static final AUDIOFOCUS_NONE:Int = 0; + + /** + * Constant representing the flags for audio focus status: gain of audio focus. + */ + public static final AUDIOFOCUS_GAIN:Int = 1; + + /** + * Constant representing the flags for audio focus status: gain of temporary audio focus. + */ + public static final AUDIOFOCUS_GAIN_TRANSIENT:Int = 2; + + /** + * Constant representing the flags for audio focus status: gain of temporary audio focus with ducking another app. + */ + public static final AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:Int = 3; + + /** + * Constant representing the flags for audio focus status: gain of exclusive temporary audio focus. + */ + public static final AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:Int = 4; + + /** + * Constant representing the flags for audio focus status: loss of audio focus. + */ + public static final AUDIOFOCUS_LOSS:Int = -1 * AUDIOFOCUS_GAIN; + + /** + * Constant representing the flags for audio focus status: loss of temporary audio focus. + */ + public static final AUDIOFOCUS_LOSS_TRANSIENT:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT; + + /** + * Constant representing the flags for audio focus status: loss of temporary audio focus with ducking another app. + */ + public static final AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; + + + /** + * Constant representing the flags for audio focus change result: unable to change focus. + */ + public static final AUDIOFOCUS_REQUEST_FAILED:Int = 0; + + /** + * Constant representing the flags for audio focus change result: focus was changed successfully. + */ + public static final AUDIOFOCUS_REQUEST_GRANTED:Int = 1; + + /** + * Constant representing the flags for audio focus change result: focus was changed successfully but delayed. + */ + public static final AUDIOFOCUS_REQUEST_DELAYED:Int = 2; + + @:noCompletion + private var constructor:Dynamic; + + @:noCompletion + private var focusListener:Dynamic; + + private var onFocusChangeListener:OnAudioFocusChangeListener; + + /** + * Constructs a new instance of AudioManager. + */ + public function new():Void + { + constructor = JNICache.createStaticMethod('org/haxe/extension/Tools', 'getAudioManager', '()Landroid/media/AudioManager;')(); + + focusListener = JNICache.createStaticMethod('org/haxe/extension/Tools', 'createAudioFocusCallback', + "(Lorg/haxe/lime/HaxeObject;)Ljava/lang/Object;")(onFocusChangeListener = new OnAudioFocusChangeListener()); + } + + /** + * Adjust the volume of a stream. + */ + public function adjustStreamVolume(streamType:Int, direction:Int, flags:Int):Void + { + JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'adjustStreamVolume', '(III)V'), constructor, [streamType, direction, flags]); + } + + /** + * Get the volume of a stream. + */ + public function getStreamVolume(streamType:Int):Int + { + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'getStreamVolume', '(I)I'), constructor, [streamType]); + } + + /** + * Clears all audio focus callbacks that were passed on request and abandon. + */ + public function clearAllAudioFocusCallbacks() + { + onFocusChangeListener.clearAllCallbacks(); + } + + /** + * Requests audio focus. + */ + public function requestAudioFocus(?callback:Int->Void, streamType:Int, durationHint:Int):Int + { + if (callback != null) + onFocusChangeListener.addCallback(callback); + + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager\x24OnAudioFocusChangeListener;II)I"), constructor, [focusListener, streamType, durationHint]); + } + + /** + * Abandon audio focus. + */ + public function abandonAudioFocus(?callback:Int->Void):Int + { + if (callback != null) + onFocusChangeListener.addCallback(callback); + + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager\x24OnAudioFocusChangeListener;)I"), constructor, [focusListener]); + } +} + +/** + * Listener class for handling audio focus changes. + */ +@:noCompletion +private class OnAudioFocusChangeListener #if (lime >= "8.0.0") implements JNISafety #end +{ + private var onFocusChangeEvent:EventVoid> = new EventVoid>(); + + /** + * Creates a new audio focus listener with a specified callback function. + * + * @param focusChange The function to execute when the focus is changed. + */ + public function new(?focusChange:Int->Void):Void + { + if (focusChange != null) + onFocusChangeEvent.add(focusChange); + } + + public function addCallback(focusChange:Int->Void) + { + onFocusChangeEvent.add(focusChange); + } + + public function clearAllCallbacks() + { + onFocusChangeEvent.removeAll(); + } + + #if (lime >= "8.0.0") + @:runOnMainThread + #end + public function onAudioFocusChange(focusChange:Int):Void + { + onFocusChangeEvent.dispatch(focusChange); + } +} \ No newline at end of file diff --git a/project/androidtools/src/main/java/org/haxe/extension/Tools.java b/project/androidtools/src/main/java/org/haxe/extension/Tools.java index 079f2075..9d3e1f1a 100644 --- a/project/androidtools/src/main/java/org/haxe/extension/Tools.java +++ b/project/androidtools/src/main/java/org/haxe/extension/Tools.java @@ -10,6 +10,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Rect; +import android.media.AudioManager; import android.media.MediaCodecList; import android.media.MediaFormat; import android.net.Uri; @@ -607,6 +608,32 @@ public static BatteryManager getBatteryManager() return (BatteryManager) mainContext.getSystemService(Context.BATTERY_SERVICE); } + /** + * Retrieves the AudioManager system service for managing volume and ringer mode control. + * + * @return A AudioManager object for managing volume and ringer mode control. + */ + public static AudioManager getAudioManager() + { + return (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + } + + /** + * Creates the callback for focus changes. + * + * @return A OnAudioFocusChangeListener object for receiving callbacks. + */ + public static Object createAudioFocusCallback(final HaxeObject haxeObject) + { + return new AudioManager.OnAudioFocusChangeListener() { + @Override + public void onAudioFocusChange(int focusChange) { + if (haxeObject != null) + haxeObject.call1("onAudioFocusChange", focusChange); + } + }; + } + @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { From 0262cc94838b623c063d74993313090b79855ee0 Mon Sep 17 00:00:00 2001 From: luckydog7 Date: Sun, 18 May 2025 22:39:13 +0300 Subject: [PATCH 2/5] fix package and remove char escape --- extension/androidtools/media/AudioManager.hx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/extension/androidtools/media/AudioManager.hx b/extension/androidtools/media/AudioManager.hx index 36f172e4..e1294bbd 100644 --- a/extension/androidtools/media/AudioManager.hx +++ b/extension/androidtools/media/AudioManager.hx @@ -1,4 +1,4 @@ -package android.media; +package extension.androidtools.media; import android.jni.JNICache; import cpp.RawPointer; @@ -9,7 +9,6 @@ import lime.system.JNI; #error 'extension-androidtools is not supported on your current platform' #end - /** * Utility class for managing volume and ringer mode control. */ @@ -239,7 +238,7 @@ class AudioManager if (callback != null) onFocusChangeListener.addCallback(callback); - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager\x24OnAudioFocusChangeListener;II)I"), constructor, [focusListener, streamType, durationHint]); + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I"), constructor, [focusListener, streamType, durationHint]); } /** @@ -250,7 +249,7 @@ class AudioManager if (callback != null) onFocusChangeListener.addCallback(callback); - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager\x24OnAudioFocusChangeListener;)I"), constructor, [focusListener]); + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"), constructor, [focusListener]); } } From 351e347d5eb19ea1cfb5414c9745699d3d8ef785 Mon Sep 17 00:00:00 2001 From: luckydog7 Date: Sun, 18 May 2025 22:40:35 +0300 Subject: [PATCH 3/5] bruh --- extension/androidtools/media/AudioManager.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/androidtools/media/AudioManager.hx b/extension/androidtools/media/AudioManager.hx index e1294bbd..a64a0c52 100644 --- a/extension/androidtools/media/AudioManager.hx +++ b/extension/androidtools/media/AudioManager.hx @@ -1,6 +1,6 @@ package extension.androidtools.media; -import android.jni.JNICache; +import extension.androidtools.jni.JNICache; import cpp.RawPointer; import lime.app.Event; import lime.system.JNI; From cc4019338a46b5d7ca751e64f9ecf289becabe46 Mon Sep 17 00:00:00 2001 From: luckydog7 Date: Sun, 18 May 2025 23:40:42 +0300 Subject: [PATCH 4/5] null safety --- extension/androidtools/media/AudioManager.hx | 79 ++++++++++++++++---- 1 file changed, 66 insertions(+), 13 deletions(-) diff --git a/extension/androidtools/media/AudioManager.hx b/extension/androidtools/media/AudioManager.hx index a64a0c52..4332d6ca 100644 --- a/extension/androidtools/media/AudioManager.hx +++ b/extension/androidtools/media/AudioManager.hx @@ -1,7 +1,6 @@ package extension.androidtools.media; import extension.androidtools.jni.JNICache; -import cpp.RawPointer; import lime.app.Event; import lime.system.JNI; @@ -188,10 +187,7 @@ class AudioManager public static final AUDIOFOCUS_REQUEST_DELAYED:Int = 2; @:noCompletion - private var constructor:Dynamic; - - @:noCompletion - private var focusListener:Dynamic; + private var constructor:Null; private var onFocusChangeListener:OnAudioFocusChangeListener; @@ -200,10 +196,14 @@ class AudioManager */ public function new():Void { - constructor = JNICache.createStaticMethod('org/haxe/extension/Tools', 'getAudioManager', '()Landroid/media/AudioManager;')(); - - focusListener = JNICache.createStaticMethod('org/haxe/extension/Tools', 'createAudioFocusCallback', - "(Lorg/haxe/lime/HaxeObject;)Ljava/lang/Object;")(onFocusChangeListener = new OnAudioFocusChangeListener()); + final constructorJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'getAudioManager', '()Landroid/media/AudioManager;'); + + if (constructorJNI != null) + { + constructor = constructorJNI(); + } + + onFocusChangeListener = new OnAudioFocusChangeListener(); } /** @@ -211,7 +211,13 @@ class AudioManager */ public function adjustStreamVolume(streamType:Int, direction:Int, flags:Int):Void { - JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'adjustStreamVolume', '(III)V'), constructor, [streamType, direction, flags]); + if (constructor == null) + return; + + final adjustStreamVolumeJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'adjustStreamVolume', '(III)V'); + + if (adjustStreamVolumeJNI != null) + JNI.callMember(adjustStreamVolumeJNI, constructor, [streamType, direction, flags]); } /** @@ -219,7 +225,19 @@ class AudioManager */ public function getStreamVolume(streamType:Int):Int { - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'getStreamVolume', '(I)I'), constructor, [streamType]); + if (constructor == null) + return 0; + + final getStreamVolumeJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'getStreamVolume', '(I)I'); + + if (getStreamVolumeJNI != null) + { + return JNI.callMember(getStreamVolumeJNI, constructor, [streamType]); + } + else + { + return 0; + } } /** @@ -235,10 +253,22 @@ class AudioManager */ public function requestAudioFocus(?callback:Int->Void, streamType:Int, durationHint:Int):Int { + if (constructor == null && onFocusChangeListener.focusListenerJNI == null) + return 0; + if (callback != null) onFocusChangeListener.addCallback(callback); - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I"), constructor, [focusListener, streamType, durationHint]); + final requestAudioFocusJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I"); + + if (requestAudioFocusJNI != null) + { + return JNI.callMember(requestAudioFocusJNI, constructor, [onFocusChangeListener.focusListenerJNI, streamType, durationHint]); + } + else + { + return 0; + } } /** @@ -246,10 +276,22 @@ class AudioManager */ public function abandonAudioFocus(?callback:Int->Void):Int { + if (constructor == null && onFocusChangeListener.focusListenerJNI == null) + return 0; + if (callback != null) onFocusChangeListener.addCallback(callback); - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"), constructor, [focusListener]); + final abandonAudioFocusJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"); + + if (abandonAudioFocusJNI != null) + { + return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"), constructor, [onFocusChangeListener.focusListenerJNI]); + } + else + { + return 0; + } } } @@ -261,6 +303,9 @@ private class OnAudioFocusChangeListener #if (lime >= "8.0.0") implements JNISaf { private var onFocusChangeEvent:EventVoid> = new EventVoid>(); + @:noCompletion + public var focusListenerJNI(default, null):Null; + /** * Creates a new audio focus listener with a specified callback function. * @@ -270,6 +315,14 @@ private class OnAudioFocusChangeListener #if (lime >= "8.0.0") implements JNISaf { if (focusChange != null) onFocusChangeEvent.add(focusChange); + + final createAudioFocusCallbackJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'createAudioFocusCallback', + "(Lorg/haxe/lime/HaxeObject;)Ljava/lang/Object;"); + + if (createAudioFocusCallbackJNI != null) + { + focusListenerJNI = createAudioFocusCallbackJNI(this); + } } public function addCallback(focusChange:Int->Void) From e21b9593ec7799a722318b0f3c5520db8b80e11c Mon Sep 17 00:00:00 2001 From: MAJigsaw77 <77043862+MAJigsaw77@users.noreply.github.com> Date: Mon, 19 May 2025 23:37:50 +0300 Subject: [PATCH 5/5] Some adjustments --- extension/androidtools/media/AudioManager.hx | 277 +++++++----------- .../main/java/org/haxe/extension/Tools.java | 113 +++++-- 2 files changed, 198 insertions(+), 192 deletions(-) diff --git a/extension/androidtools/media/AudioManager.hx b/extension/androidtools/media/AudioManager.hx index 4332d6ca..176d50d2 100644 --- a/extension/androidtools/media/AudioManager.hx +++ b/extension/androidtools/media/AudioManager.hx @@ -1,134 +1,132 @@ package extension.androidtools.media; -import extension.androidtools.jni.JNICache; -import lime.app.Event; -import lime.system.JNI; - +import haxe.macro.Tools.TTypedExprTools; #if (!android && !native) #error 'extension-androidtools is not supported on your current platform' #end +import extension.androidtools.jni.JNICache; +import lime.app.Event; +import lime.system.JNI; /** * Utility class for managing volume and ringer mode control. */ -class AudioManager +class AudioManager { - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: voice call. */ public static final STREAM_VOICE_CALL:Int = 0; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: system sounds. */ public static final STREAM_SYSTEM:Int = 1; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: phone ring. */ public static final STREAM_RING:Int = 2; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: music playback. */ public static final STREAM_MUSIC:Int = 3; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: alarm. */ public static final STREAM_ALARM:Int = 4; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: notification. */ public static final STREAM_NOTIFICATION:Int = 5; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: phone calls when connected to bluetooth. */ public static final STREAM_BLUETOOTH_SCO:Int = 6; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: enforced system sounds. */ public static final STREAM_SYSTEM_ENFORCED:Int = 7; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: DTMF Tones. */ public static final STREAM_DTMF:Int = 8; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: tts transmitted through the speaker. */ public static final STREAM_TTS:Int = 9; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: accessibility prompts. */ public static final STREAM_ACCESSIBILITY:Int = 10; - /** + /** * Constant representing the stream type that can be used for changing volume of that stream: virtual assistant. */ public static final STREAM_ASSISTANT:Int = 11; - - /** + /** * Constant representing the direction of volume adjustment: raise the volume. */ public static final ADJUST_RAISE:Int = 1; - /** + /** * Constant representing the direction of volume adjustment: lower the volume. */ public static final ADJUST_LOWER:Int = -1; - /** + /** * Constant representing the direction of volume adjustment: same volume. */ public static final ADJUST_SAME:Int = 0; - /** + /** * Constant representing the direction of volume adjustment: mute the volume. */ public static final ADJUST_MUTE:Int = -100; - /** + /** * Constant representing the direction of volume adjustment: unmute the volume. */ public static final ADJUST_UNMUTE:Int = 100; - /** + /** * Constant representing the direction of volume adjustment: toggle mute state. */ public static final ADJUST_TOGGLE_MUTE:Int = 101; - - /** + /** * Constant representing the flags for volume adjustment: show ui. */ public static final FLAG_SHOW_UI:Int = 1 << 0; - /** + /** * Constant representing the flags for volume adjustment: include ringer modes. */ - public static final FLAG_ALLOW_RINGER_MODES:Int = 1 << 1; - /** + public static final FLAG_ALLOW_RINGER_MODES:Int = 1 << 1; + + /** * Constant representing the flags for volume adjustment: play sound when changing volume. */ - public static final FLAG_PLAY_SOUND:Int = 1 << 2; + public static final FLAG_PLAY_SOUND:Int = 1 << 2; - /** + /** * Constant representing the flags for volume adjustment: remove any sound and vibrate. */ - public static final FLAG_REMOVE_SOUND_AND_VIBRATE:Int = 1 << 3; + public static final FLAG_REMOVE_SOUND_AND_VIBRATE:Int = 1 << 3; - /** + /** * Constant representing the flags for volume adjustment: vibrate if going into the vibrate ringer mode. */ - public static final FLAG_VIBRATE:Int = 1 << 4; - + public static final FLAG_VIBRATE:Int = 1 << 4; /** * Constant representing the flags for audio focus status: nothing changed. @@ -138,161 +136,126 @@ class AudioManager /** * Constant representing the flags for audio focus status: gain of audio focus. */ - public static final AUDIOFOCUS_GAIN:Int = 1; + public static final AUDIOFOCUS_GAIN:Int = 1; /** * Constant representing the flags for audio focus status: gain of temporary audio focus. */ - public static final AUDIOFOCUS_GAIN_TRANSIENT:Int = 2; + public static final AUDIOFOCUS_GAIN_TRANSIENT:Int = 2; /** * Constant representing the flags for audio focus status: gain of temporary audio focus with ducking another app. */ - public static final AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:Int = 3; + public static final AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:Int = 3; /** * Constant representing the flags for audio focus status: gain of exclusive temporary audio focus. */ - public static final AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:Int = 4; + public static final AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:Int = 4; /** * Constant representing the flags for audio focus status: loss of audio focus. */ - public static final AUDIOFOCUS_LOSS:Int = -1 * AUDIOFOCUS_GAIN; + public static final AUDIOFOCUS_LOSS:Int = -1 * AUDIOFOCUS_GAIN; /** * Constant representing the flags for audio focus status: loss of temporary audio focus. */ - public static final AUDIOFOCUS_LOSS_TRANSIENT:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT; + public static final AUDIOFOCUS_LOSS_TRANSIENT:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT; /** * Constant representing the flags for audio focus status: loss of temporary audio focus with ducking another app. */ - public static final AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; - + public static final AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:Int = -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; - /** - * Constant representing the flags for audio focus change result: unable to change focus. - */ - public static final AUDIOFOCUS_REQUEST_FAILED:Int = 0; - /** - * Constant representing the flags for audio focus change result: focus was changed successfully. - */ - public static final AUDIOFOCUS_REQUEST_GRANTED:Int = 1; - + * Constant representing the flags for audio focus change result: unable to change focus. + */ + public static final AUDIOFOCUS_REQUEST_FAILED:Int = 0; + /** - * Constant representing the flags for audio focus change result: focus was changed successfully but delayed. - */ - public static final AUDIOFOCUS_REQUEST_DELAYED:Int = 2; - - @:noCompletion - private var constructor:Null; + * Constant representing the flags for audio focus change result: focus was changed successfully. + */ + public static final AUDIOFOCUS_REQUEST_GRANTED:Int = 1; - private var onFocusChangeListener:OnAudioFocusChangeListener; + /** + * Constant representing the flags for audio focus change result: focus was changed successfully but delayed. + */ + public static final AUDIOFOCUS_REQUEST_DELAYED:Int = 2; /** - * Constructs a new instance of AudioManager. + * Event that is triggered when the audio focus changes. + * + * Listeners can subscribe to this event to be notified when the audio focus state changes. + * + * The event handler receives a dynamic parameter containing information about the focus change. */ - public function new():Void - { - final constructorJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'getAudioManager', '()Landroid/media/AudioManager;'); - - if (constructorJNI != null) - { - constructor = constructorJNI(); - } - - onFocusChangeListener = new OnAudioFocusChangeListener(); - } + public static var onFocusChangeEvent(default, null):EventVoid> = new EventVoid>(); - /** - * Adjust the volume of a stream. + /** + * Adjusts the volume of a specified audio stream. + * + * @param streamType The type of audio stream to adjust (e.g., STREAM_MUSIC). + * @param direction The direction to adjust the volume (e.g., ADJUST_RAISE, ADJUST_LOWER). + * @param flags Additional operation flags (e.g., FLAG_SHOW_UI). */ - public function adjustStreamVolume(streamType:Int, direction:Int, flags:Int):Void + public static function adjustStreamVolume(streamType:Int, direction:Int, flags:Int):Void { - if (constructor == null) - return; - - final adjustStreamVolumeJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'adjustStreamVolume', '(III)V'); + final adjustStreamVolumeJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'adjustStreamVolume', '(III)V'); if (adjustStreamVolumeJNI != null) - JNI.callMember(adjustStreamVolumeJNI, constructor, [streamType, direction, flags]); + adjustStreamVolumeJNI(streamType, direction, flags); } - /** - * Get the volume of a stream. + /** + * Retrieves the current volume index for a specified audio stream. + * + * @param streamType The type of audio stream (e.g., STREAM_MUSIC). + * @return The current volume index for the specified stream, or 0 if an error occurs. */ - public function getStreamVolume(streamType:Int):Int - { - if (constructor == null) - return 0; - - final getStreamVolumeJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'getStreamVolume', '(I)I'); + public static function getStreamVolume(streamType:Int):Int + { + final getStreamVolumeJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'getStreamVolume', '(I)I'); if (getStreamVolumeJNI != null) - { - return JNI.callMember(getStreamVolumeJNI, constructor, [streamType]); - } - else - { - return 0; - } - } + return getStreamVolumeJNI(); - /** - * Clears all audio focus callbacks that were passed on request and abandon. - */ - public function clearAllAudioFocusCallbacks() - { - onFocusChangeListener.clearAllCallbacks(); + return 0; } /** - * Requests audio focus. + * Requests audio focus for a given stream and duration, and sets up a callback for focus changes. + * + * @param streamType The type of audio stream for which focus is requested. + * @param durationHint The duration of the audio focus request (e.g., AUDIOFOCUS_GAIN). + * @return The result of the audio focus request (e.g., AUDIOFOCUS_REQUEST_GRANTED or AUDIOFOCUS_REQUEST_FAILED). */ - public function requestAudioFocus(?callback:Int->Void, streamType:Int, durationHint:Int):Int - { - if (constructor == null && onFocusChangeListener.focusListenerJNI == null) - return 0; - - if (callback != null) - onFocusChangeListener.addCallback(callback); - - final requestAudioFocusJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'requestAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;II)I"); + public static function requestAudioFocus(?focusChange:Int->Void, streamType:Int, durationHint:Int):Int + { + final requestAudioFocusJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'requestAudioFocus', + '(Lorg/haxe/lime/HaxeObject;II)I'); if (requestAudioFocusJNI != null) - { - return JNI.callMember(requestAudioFocusJNI, constructor, [onFocusChangeListener.focusListenerJNI, streamType, durationHint]); - } - else - { - return 0; - } - } + return requestAudioFocusJNI(new OnAudioFocusChangeListener(), streamType, durationHint); + + return AUDIOFOCUS_REQUEST_FAILED; + } /** - * Abandon audio focus. + * Abandons audio focus for the given callback. + * + * @return The result of the abandon audio focus request (e.g., AUDIOFOCUS_REQUEST_GRANTED or AUDIOFOCUS_REQUEST_FAILED). */ - public function abandonAudioFocus(?callback:Int->Void):Int - { - if (constructor == null && onFocusChangeListener.focusListenerJNI == null) - return 0; - - if (callback != null) - onFocusChangeListener.addCallback(callback); - - final abandonAudioFocusJNI:Null = JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"); + public static function abandonAudioFocus():Int + { + final abandonAudioFocusJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'abandonAudioFocus', + '(Lorg/haxe/lime/HaxeObject;)I'); if (abandonAudioFocusJNI != null) - { - return JNI.callMember(JNICache.createMemberMethod('android/media/AudioManager', 'abandonAudioFocus', "(Landroid/media/AudioManager$OnAudioFocusChangeListener;)I"), constructor, [onFocusChangeListener.focusListenerJNI]); - } - else - { - return 0; - } - } + return abandonAudioFocusJNI(new OnAudioFocusChangeListener()); + + return AUDIOFOCUS_REQUEST_FAILED; + } } /** @@ -301,45 +264,15 @@ class AudioManager @:noCompletion private class OnAudioFocusChangeListener #if (lime >= "8.0.0") implements JNISafety #end { - private var onFocusChangeEvent:EventVoid> = new EventVoid>(); - - @:noCompletion - public var focusListenerJNI(default, null):Null; - - /** - * Creates a new audio focus listener with a specified callback function. - * - * @param focusChange The function to execute when the focus is changed. - */ - public function new(?focusChange:Int->Void):Void - { - if (focusChange != null) - onFocusChangeEvent.add(focusChange); - - final createAudioFocusCallbackJNI:Null = JNICache.createStaticMethod('org/haxe/extension/Tools', 'createAudioFocusCallback', - "(Lorg/haxe/lime/HaxeObject;)Ljava/lang/Object;"); - - if (createAudioFocusCallbackJNI != null) - { - focusListenerJNI = createAudioFocusCallbackJNI(this); - } - } - - public function addCallback(focusChange:Int->Void) - { - onFocusChangeEvent.add(focusChange); - } - - public function clearAllCallbacks() - { - onFocusChangeEvent.removeAll(); - } + public function new():Void {} + @:keep #if (lime >= "8.0.0") @:runOnMainThread #end public function onAudioFocusChange(focusChange:Int):Void { - onFocusChangeEvent.dispatch(focusChange); + if (AudioManager.onFocusChangeEvent != null) + AudioManager.onFocusChangeEvent.dispatch(focusChange); } -} \ No newline at end of file +} diff --git a/project/androidtools/src/main/java/org/haxe/extension/Tools.java b/project/androidtools/src/main/java/org/haxe/extension/Tools.java index 9d3e1f1a..b9f918fc 100644 --- a/project/androidtools/src/main/java/org/haxe/extension/Tools.java +++ b/project/androidtools/src/main/java/org/haxe/extension/Tools.java @@ -362,7 +362,7 @@ public static void requestPermissions(String[] permissions, int requestCode) { if (Extension.mainActivity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) ungrantedPermissions.add(permission); - } + } if (!ungrantedPermissions.isEmpty()) Extension.mainActivity.requestPermissions(ungrantedPermissions.toArray(new String[0]), requestCode); @@ -471,7 +471,7 @@ public void run() * Each rectangle represents an area of the display that is obstructed by the cutout. * * @return An array of Rect objects representing the bounding rectangles of the display cutout. - * Returns an empty array if there is no cutout or if cutouts are not supported on the device. + * Returns an empty array if there is no cutout or if cutouts are not supported on the device. */ public static Rect[] getCutoutDimensions() { @@ -599,39 +599,112 @@ public static File[] getObbDirs() } /** - * Retrieves the BatteryManager system service for managing battery-related information. + * Adjusts the volume of a specified audio stream. * - * @return A BatteryManager object for managing battery-related information. + * @param streamType The type of audio stream to adjust (e.g., AudioManager.STREAM_MUSIC). + * @param direction The direction to adjust the volume (e.g., AudioManager.ADJUST_RAISE, AudioManager.ADJUST_LOWER). + * @param flags Additional operation flags (e.g., AudioManager.FLAG_SHOW_UI). */ - public static BatteryManager getBatteryManager() + public static void adjustStreamVolume(final int streamType, final int direction, final int flags) { - return (BatteryManager) mainContext.getSystemService(Context.BATTERY_SERVICE); + try + { + final AudioManager audioManager = (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + + audioManager.adjustStreamVolume(streamType, direction, flags); + } + catch (Exception e) + { + Log.e(LOG_TAG, e.toString()); + } } /** - * Retrieves the AudioManager system service for managing volume and ringer mode control. + * Retrieves the current volume index for a specified audio stream. * - * @return A AudioManager object for managing volume and ringer mode control. + * @param streamType The type of audio stream (e.g., AudioManager.STREAM_MUSIC). + * @return The current volume index for the specified stream, or 0 if an error occurs. */ - public static AudioManager getAudioManager() + public static int getStreamVolume(final int streamType) { - return (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + try + { + final AudioManager audioManager = (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + + return audioManager.getStreamVolume(streamType); + } + catch (Exception e) + { + Log.e(LOG_TAG, e.toString()); + } + + return 0; } /** - * Creates the callback for focus changes. + * Requests audio focus for a given stream and duration, and sets up a callback for focus changes. * - * @return A OnAudioFocusChangeListener object for receiving callbacks. + * @param haxeCallbackObject The HaxeObject to receive audio focus change callbacks. + * @param streamType The type of audio stream for which focus is requested. + * @param durationHint The duration of the audio focus request (e.g., AudioManager.AUDIOFOCUS_GAIN). + * @return The result of the audio focus request (e.g., AudioManager.AUDIOFOCUS_REQUEST_GRANTED or AUDIOFOCUS_REQUEST_FAILED). */ - public static Object createAudioFocusCallback(final HaxeObject haxeObject) + public static int requestAudioFocus(final HaxeObject haxeCallbackObject, final int streamType, final int durationHint) { - return new AudioManager.OnAudioFocusChangeListener() { - @Override - public void onAudioFocusChange(int focusChange) { - if (haxeObject != null) - haxeObject.call1("onAudioFocusChange", focusChange); - } - }; + try + { + final AudioManager audioManager = (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + + final AudioManager.OnAudioFocusChangeListener focusChangeListener = new AudioManager.OnAudioFocusChangeListener() + { + @Override + public void onAudioFocusChange(int focusChange) + { + if (haxeCallbackObject != null) + haxeCallbackObject.call1("onAudioFocusChange", focusChange); + } + }; + + return audioManager.requestAudioFocus(focusChangeListener, streamType, durationHint); + } + catch (Exception e) + { + Log.e(LOG_TAG, e.toString()); + } + + return AudioManager.AUDIOFOCUS_REQUEST_FAILED; + } + + /** + * Abandons audio focus for the given HaxeObject callback. + * + * @param haxeCallbackObject The HaxeObject that was used to request audio focus. + * @return The result of the abandon audio focus request (e.g., AudioManager.AUDIOFOCUS_REQUEST_GRANTED or AUDIOFOCUS_REQUEST_FAILED). + */ + public static int abandonAudioFocus(final HaxeObject haxeCallbackObject) + { + try + { + final AudioManager audioManager = (AudioManager) mainContext.getSystemService(Context.AUDIO_SERVICE); + + final AudioManager.OnAudioFocusChangeListener focusChangeListener = new AudioManager.OnAudioFocusChangeListener() + { + @Override + public void onAudioFocusChange(int focusChange) + { + if (haxeCallbackObject != null) + haxeCallbackObject.call1("onAudioFocusChange", focusChange); + } + }; + + return audioManager.abandonAudioFocus(focusChangeListener); + } + catch (Exception e) + { + Log.e(LOG_TAG, e.toString()); + } + + return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } @Override