11//go:build android
22
3- // Command audiomanager demonstrates the Android AudioManager for
4- // controlling audio routing, volume, and device enumeration. It is
5- // built as a c-shared library and packaged into an APK using the
6- // shared apk.mk infrastructure.
7- //
8- // The audiomanager package wraps android.media.AudioManager.
9- // Most methods are unexported (getStreamVolume, setStreamVolume, etc.)
10- // and are intended to be wrapped by higher-level helpers.
3+ // Command audiomanager demonstrates the Android AudioManager by
4+ // querying live audio state: stream volumes, ringer mode, audio mode,
5+ // and boolean flags such as isMusicActive and isSpeakerphoneOn.
116package main
127
138/*
@@ -26,17 +21,17 @@ import (
2621
2722 "github.com/AndroidGoLab/jni"
2823 "github.com/AndroidGoLab/jni/capi"
29- "github.com/AndroidGoLab/jni/exampleui "
24+ "github.com/AndroidGoLab/jni/examples/common/ui "
3025 "github.com/AndroidGoLab/jni/media/audiomanager"
3126)
3227
3328func main () {}
3429
35- func init () { exampleui .Register (run ) }
30+ func init () { ui .Register (run ) }
3631
3732//export ANativeActivity_onCreate
3833func ANativeActivity_onCreate (activity * C.ANativeActivity , savedState unsafe.Pointer , savedStateSize C.size_t ) {
39- exampleui .OnCreate (
34+ ui .OnCreate (
4035 jni .VMFromPtr (unsafe .Pointer (activity .vm )),
4136 jni .ObjectFromRef (capi .Object (uintptr (unsafe .Pointer (activity .clazz )))),
4237 )
@@ -45,18 +40,18 @@ func ANativeActivity_onCreate(activity *C.ANativeActivity, savedState unsafe.Poi
4540
4641//export goOnResume
4742func goOnResume (activity * C.ANativeActivity ) {
48- exampleui .OnResume (
43+ ui .OnResume (
4944 jni .ObjectFromRef (capi .Object (uintptr (unsafe .Pointer (activity .clazz )))),
5045 )
5146}
5247
5348//export goOnNativeWindowCreated
5449func goOnNativeWindowCreated (activity * C.ANativeActivity , window * C.ANativeWindow ) {
55- exampleui .OnNativeWindowCreated (unsafe .Pointer (window ))
50+ ui .OnNativeWindowCreated (unsafe .Pointer (window ))
5651}
5752
5853func run (vm * jni.VM , output * bytes.Buffer ) error {
59- ctx , err := exampleui .GetAppContext (vm )
54+ ctx , err := ui .GetAppContext (vm )
6055 if err != nil {
6156 return fmt .Errorf ("get context: %w" , err )
6257 }
@@ -68,39 +63,97 @@ func run(vm *jni.VM, output *bytes.Buffer) error {
6863 }
6964 defer mgr .Close ()
7065
71- // Audio device type constants from android.media.AudioDeviceInfo.
72- fmt .Fprintf (output , "device types: speaker=%d, mic=%d, wired_headset=%d, wired_headphones=%d, bluetooth_a2dp=%d, usb=%d, hdmi=%d\n " ,
73- audiomanager .TypeBuiltinSpeaker , audiomanager .TypeBuiltinMic ,
74- audiomanager .TypeWiredHeadset , audiomanager .TypeWiredHeadphones ,
75- audiomanager .TypeBluetoothA2dp ,
76- audiomanager .TypeUsbDevice , audiomanager .TypeHdmi )
77-
78- // Audio focus request constants.
79- fmt .Fprintf (output , "focus gain: gain=%d, transient=%d, transient_duck=%d\n " ,
80- audiomanager .AudiofocusGain , audiomanager .AudiofocusGainTransient ,
81- audiomanager .AudiofocusGainTransientMayDuck )
82- fmt .Fprintf (output , "focus loss: loss=%d, transient=%d, transient_duck=%d\n " ,
83- audiomanager .AudiofocusLoss , audiomanager .AudiofocusLossTransient ,
84- audiomanager .AudiofocusLossTransientCanDuck )
85-
86- // Stream type constants for volume control.
87- fmt .Fprintf (output , "streams: voice_call=%d, system=%d, ring=%d, music=%d, alarm=%d, notification=%d\n " ,
88- audiomanager .StreamVoiceCall , audiomanager .StreamSystem ,
89- audiomanager .StreamRing , audiomanager .StreamMusic ,
90- audiomanager .StreamAlarm , audiomanager .StreamNotification )
91-
92- // Device filter constants for getDevices.
93- fmt .Fprintf (output , "device filters: input=%d, output=%d, all=%d\n " ,
94- audiomanager .GetDevicesInputs , audiomanager .GetDevicesOutputs , audiomanager .GetDevicesAll )
95-
96- // The Manager also provides unexported methods for:
97- // - getDevicesRaw(flags) - enumerate audio devices
98- // - getStreamVolume(streamType) / setStreamVolume(streamType, index, flags)
99- // - getStreamMaxVolume(streamType)
100- // - isSpeakerphoneOn() / setSpeakerphoneOn(on)
101- // - requestAudioFocusRaw(request) / abandonAudioFocusRequest(request)
102- // - registerAudioDeviceCallback / unregisterAudioDeviceCallback
103- fmt .Fprintln (output , "AudioManager created successfully" )
66+ fmt .Fprintln (output , "=== AudioManager ===" )
67+
68+ // Stream volumes.
69+ type streamInfo struct {
70+ name string
71+ constant int32
72+ }
73+ streams := []streamInfo {
74+ {"voice_call" , int32 (audiomanager .StreamVoiceCall )},
75+ {"system" , int32 (audiomanager .StreamSystem )},
76+ {"ring" , int32 (audiomanager .StreamRing )},
77+ {"music" , int32 (audiomanager .StreamMusic )},
78+ {"alarm" , int32 (audiomanager .StreamAlarm )},
79+ {"notification" , int32 (audiomanager .StreamNotification )},
80+ }
81+ for _ , s := range streams {
82+ vol , err := mgr .GetStreamVolume (s .constant )
83+ if err != nil {
84+ fmt .Fprintf (output , " %s volume: error: %v\n " , s .name , err )
85+ continue
86+ }
87+ maxVol , err := mgr .GetStreamMaxVolume (s .constant )
88+ if err != nil {
89+ fmt .Fprintf (output , " %s volume: %d (max: error: %v)\n " , s .name , vol , err )
90+ continue
91+ }
92+ minVol , _ := mgr .GetStreamMinVolume (s .constant )
93+ muted , _ := mgr .IsStreamMute (s .constant )
94+ fmt .Fprintf (output , " %s: vol=%d min=%d max=%d muted=%v\n " , s .name , vol , minVol , maxVol , muted )
95+ }
96+
97+ // Ringer mode.
98+ ringerMode , err := mgr .GetRingerMode ()
99+ if err != nil {
100+ fmt .Fprintf (output , "ringer mode: error: %v\n " , err )
101+ } else {
102+ name := "unknown"
103+ switch int (ringerMode ) {
104+ case audiomanager .RingerModeSilent :
105+ name = "silent"
106+ case audiomanager .RingerModeVibrate :
107+ name = "vibrate"
108+ case audiomanager .RingerModeNormal :
109+ name = "normal"
110+ }
111+ fmt .Fprintf (output , "ringer mode: %s (%d)\n " , name , ringerMode )
112+ }
113+
114+ // Audio mode.
115+ mode , err := mgr .GetMode ()
116+ if err != nil {
117+ fmt .Fprintf (output , "audio mode: error: %v\n " , err )
118+ } else {
119+ name := "unknown"
120+ switch int (mode ) {
121+ case audiomanager .ModeNormal :
122+ name = "normal"
123+ case audiomanager .ModeRingtone :
124+ name = "ringtone"
125+ case audiomanager .ModeInCall :
126+ name = "in_call"
127+ case audiomanager .ModeInCommunication :
128+ name = "in_communication"
129+ case audiomanager .ModeCallScreening :
130+ name = "call_screening"
131+ }
132+ fmt .Fprintf (output , "audio mode: %s (%d)\n " , name , mode )
133+ }
134+
135+ // Boolean flags.
136+ type boolQuery struct {
137+ name string
138+ fn func () (bool , error )
139+ }
140+ boolQueries := []boolQuery {
141+ {"music active" , mgr .IsMusicActive },
142+ {"speakerphone on" , mgr .IsSpeakerphoneOn },
143+ {"mic mute" , mgr .IsMicrophoneMute },
144+ {"bluetooth A2DP on" , mgr .IsBluetoothA2dpOn },
145+ {"bluetooth SCO on" , mgr .IsBluetoothScoOn },
146+ {"wired headset on" , mgr .IsWiredHeadsetOn },
147+ {"volume fixed" , mgr .IsVolumeFixed },
148+ }
149+ for _ , q := range boolQueries {
150+ val , err := q .fn ()
151+ if err != nil {
152+ fmt .Fprintf (output , "%s: error: %v\n " , q .name , err )
153+ } else {
154+ fmt .Fprintf (output , "%s: %v\n " , q .name , val )
155+ }
156+ }
104157
105158 return nil
106159}
0 commit comments