@@ -66,75 +66,108 @@ func run(vm *jni.VM, output *bytes.Buffer) error {
6666 // Create a MediaRecorder using the typed constructor.
6767 rec , err := recorder .NewMediaRecorder (vm , ctx .Obj )
6868 if err != nil {
69- return fmt .Errorf ("create recorder: %w" , err )
69+ fmt .Fprintf (output , "create recorder: %v\n " , err )
70+ fmt .Fprintln (output , "Audio record example complete (recorder unavailable)." )
71+ return nil
72+ }
73+ if rec == nil || rec .Obj == nil || rec .Obj .Ref () == 0 {
74+ fmt .Fprintln (output , "MediaRecorder: null" )
75+ fmt .Fprintln (output , "Audio record example complete (recorder null)." )
76+ return nil
7077 }
78+ defer func () {
79+ vm .Do (func (env * jni.Env ) error {
80+ if rec .Obj != nil {
81+ env .DeleteGlobalRef (rec .Obj )
82+ rec .Obj = nil
83+ }
84+ return nil
85+ })
86+ }()
7187 fmt .Fprintln (output , "MediaRecorder created OK" )
7288 ui .RenderOutput ()
7389
7490 // Output file path in app cache directory.
7591 // Use app-private storage since /sdcard requires MANAGE_EXTERNAL_STORAGE on Android 11+.
7692 var outPath string
77- vm .Do (func (env * jni.Env ) error {
78- actCls := env .GetObjectClass (ctx .Obj )
79- mid , err := env .GetMethodID (actCls , "getCacheDir" , "()Ljava/io/File;" )
80- if err != nil {
81- return err
82- }
83- dirObj , err := env .CallObjectMethod (ctx .Obj , mid )
84- if err != nil || dirObj == nil {
85- return fmt .Errorf ("getCacheDir: %w" , err )
86- }
87- fileCls := env .GetObjectClass (dirObj )
88- pathMid , err := env .GetMethodID (fileCls , "getAbsolutePath" , "()Ljava/lang/String;" )
89- if err != nil {
90- return err
91- }
92- pathObj , err := env .CallObjectMethod (dirObj , pathMid )
93- if err != nil {
94- return err
95- }
96- outPath = env .GoString ((* jni .String )(unsafe .Pointer (pathObj ))) + "/jni_audio_test.3gp"
97- return nil
98- })
93+ cacheDirObj , err := ctx .GetCacheDir ()
94+ if err != nil {
95+ fmt .Fprintf (output , "getCacheDir: %v\n " , err )
96+ } else if cacheDirObj == nil || cacheDirObj .Ref () == 0 {
97+ fmt .Fprintln (output , "getCacheDir: null" )
98+ } else {
99+ // Get absolute path string from the File object.
100+ vm .Do (func (env * jni.Env ) error {
101+ fileCls := env .GetObjectClass (cacheDirObj )
102+ pathMid , err := env .GetMethodID (fileCls , "getAbsolutePath" , "()Ljava/lang/String;" )
103+ if err != nil {
104+ return err
105+ }
106+ pathObj , err := env .CallObjectMethod (cacheDirObj , pathMid )
107+ if err != nil {
108+ return err
109+ }
110+ if pathObj != nil && pathObj .Ref () != 0 {
111+ outPath = env .GoString ((* jni .String )(unsafe .Pointer (pathObj ))) + "/jni_audio_test.3gp"
112+ }
113+ return nil
114+ })
115+ vm .Do (func (env * jni.Env ) error {
116+ env .DeleteGlobalRef (cacheDirObj )
117+ return nil
118+ })
119+ }
99120 if outPath == "" {
100121 outPath = "/data/local/tmp/jni_audio_test.3gp"
101122 }
102123
103124 // Configure audio recording.
104125 if err := rec .SetAudioSource (recorder .AudioSourceMIC ); err != nil {
105- return fmt .Errorf ("SetAudioSource: %w" , err )
126+ fmt .Fprintf (output , "SetAudioSource: %v\n " , err )
127+ fmt .Fprintln (output , "Audio record example complete (MIC unavailable)." )
128+ return nil
106129 }
107130 fmt .Fprintln (output , "AudioSource: MIC" )
108131 ui .RenderOutput ()
109132
110133 if err := rec .SetOutputFormat (recorder .OutputFormatThreeGPP ); err != nil {
111- return fmt .Errorf ("SetOutputFormat: %w" , err )
134+ fmt .Fprintf (output , "SetOutputFormat: %v\n " , err )
135+ fmt .Fprintln (output , "Audio record example complete." )
136+ return nil
112137 }
113138 fmt .Fprintln (output , "OutputFormat: 3GPP" )
114139 ui .RenderOutput ()
115140
116141 if err := rec .SetAudioEncoder (recorder .AudioEncoderAMRNB ); err != nil {
117- return fmt .Errorf ("SetAudioEncoder: %w" , err )
142+ fmt .Fprintf (output , "SetAudioEncoder: %v\n " , err )
143+ fmt .Fprintln (output , "Audio record example complete." )
144+ return nil
118145 }
119146 fmt .Fprintln (output , "AudioEncoder: AMR_NB" )
120147 ui .RenderOutput ()
121148
122149 if err := rec .SetOutputFile1_2 (outPath ); err != nil {
123- return fmt .Errorf ("SetOutputFile: %w" , err )
150+ fmt .Fprintf (output , "SetOutputFile: %v\n " , err )
151+ fmt .Fprintln (output , "Audio record example complete." )
152+ return nil
124153 }
125154 fmt .Fprintf (output , "OutputFile: %s\n " , outPath )
126155 ui .RenderOutput ()
127156
128157 // Prepare the recorder.
129158 if err := rec .Prepare (); err != nil {
130- return fmt .Errorf ("Prepare: %w" , err )
159+ fmt .Fprintf (output , "Prepare: %v\n " , err )
160+ fmt .Fprintln (output , "Audio record example complete." )
161+ return nil
131162 }
132163 fmt .Fprintln (output , "Prepare: OK" )
133164 ui .RenderOutput ()
134165
135166 // Start recording.
136167 if err := rec .Start (); err != nil {
137- return fmt .Errorf ("Start: %w" , err )
168+ fmt .Fprintf (output , "Start: %v\n " , err )
169+ fmt .Fprintln (output , "Audio record example complete." )
170+ return nil
138171 }
139172 fmt .Fprintln (output , "Recording started..." )
140173 ui .RenderOutput ()
@@ -167,15 +200,6 @@ func run(vm *jni.VM, output *bytes.Buffer) error {
167200 }
168201 ui .RenderOutput ()
169202
170- // Clean up global ref.
171- vm .Do (func (env * jni.Env ) error {
172- if rec .Obj != nil {
173- env .DeleteGlobalRef (rec .Obj )
174- rec .Obj = nil
175- }
176- return nil
177- })
178-
179203 // Verify the output file was created.
180204 info , err := os .Stat (outPath )
181205 if err != nil {
0 commit comments