Android Question Audio library and SDK target 29

Christian García S.

Active Member
Licensed User
Hello,

I have an application with SDK target 29, and now I want to incorporate the audio recording with the library that is included in the IDE, but I can't get it to work.

I use example code from this thread (POST 10): https://www.b4x.com/android/forum/t...-5-new-audiostreamer-object.30550/post-177599 but with SDK 29 I get issues.

I have tried wih File.DirRootExternal but I have permissions issues, but I read a comment that using that directory is a temporary solution, I read too that you can use rp.GetSafeDirDefaultExternal but trying to make this directory work I get the following errors:

B4X:
** Service (audiorecord) Destroy **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (activity_permissionresult)
running waiting messages (1)
** Activity (main) Resume **
** Activity (main) Pause, UserClosed = false **
sending message to waiting queue (activity_permissionresult)
running waiting messages (1)
** Activity (main) Resume **
** Receiver (audiorecord) OnReceive **
*** Service (audiorecord) Create ***
** Service (audiorecord) Start **
(RuntimeException) java.lang.RuntimeException: Object should first be initialized (OutputStream).
Error occurred on line: 209 (Main)
java.io.IOException: Prepare failed.: status=0x1
    at android.media.MediaPlayer._prepare(Native Method)
    at android.media.MediaPlayer.prepare(MediaPlayer.java:1274)
    at anywheresoftware.b4a.objects.MediaPlayerWrapper.loadAfterReset(MediaPlayerWrapper.java:101)
    at anywheresoftware.b4a.objects.MediaPlayerWrapper.Load(MediaPlayerWrapper.java:66)
    at b4a.AudioRecordingSample.main._btnplay_click(main.java:685)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:732)
    at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:348)
    at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:144)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:197)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:193)
    at anywheresoftware.b4a.objects.ViewWrapper$1.onClick(ViewWrapper.java:80)
    at android.view.View.performClick(View.java:7140)
    at android.view.View.performClickInternal(View.java:7117)
    at android.view.View.access$3500(View.java:801)
    at android.view.View$PerformClick.run(View.java:27355)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7403)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)

I use the same code, but with this:

In manifest for old android version I added:

B4X:
AddManifestText(<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
)

B4X:
    rp.CheckAndRequest(rp.PERMISSION_READ_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result1 As Boolean)
        
    If Result1 = False Then
        Log("1")
    End If
    
    rp.CheckAndRequest(rp.PERMISSION_WRITE_EXTERNAL_STORAGE)
    Wait For Activity_PermissionResult (Permission As String, Result2 As Boolean)
        
    If Result2 = False Then
        Log("2")
    End If
    
    rp.CheckAndRequest(rp.PERMISSION_RECORD_AUDIO)
    Wait For Activity_PermissionResult (Permission As String, Result3 As Boolean)
        
    If Result3 = False Then
        Log("3")
    End If

Which directory should I use, to work with this example to be able to use SDK 29

Thanks for your help.
 

roumei

Active Member
Licensed User
No need to use File.DirRootExternal with the temporary solution. Create a variable for the directory in Process_Globals:
B4X:
' Process_Globals
Private AudioDir As String
Private AudioPermissionOnStartup As Boolean
Private rp As RuntimePermissions
and use rp.GetSafeDirDefaultExternal in Activity_Create (check for PERMISSION_RECORD_AUDIO before initializing the streamer object)
B4X:
Sub Activity_Create(FirstTime As Boolean)
    
    AudioDir = rp.GetSafeDirDefaultExternal("")
    
    rp.CheckAndRequest(rp.PERMISSION_RECORD_AUDIO)
    Wait For Activity_PermissionResult (Permission As String, Result As Boolean)
    AudioPermissionOnStartup = Result
    
    Activity.LoadLayout("1")
    If FirstTime Then
        streamer.Initialize("streamer", mSampleRate, mMono, mBitRate, streamer.VOLUME_MUSIC)
        buffers.Initialize
        timer1.Initialize("timer1", 1000)
        mp.Initialize2("mp")
    End If
    
End Sub
Check for the permission in btnStartRecording_Click again:
B4X:
Sub btnStartRecording_Click
    
    If AudioPermissionOnStartup = False Then Return
    
    buffers.Clear
    output = StartWaveFile(AudioDir, mFileName, mSampleRate, mMono, mBitRate)
    recording = True
    streamer.StartRecording
    recordingStart = DateTime.Now
    timer1.Enabled = True
    Timer1_Tick
    btnPlay.Enabled = False
End Sub
Replace all File.DirRootExternal with AudioDir and it should work with targetSdkVersion="29" (at least it does for me). If you've still got an error, I can upload my test project.
 
Upvote 0
Top