Android studio won't let me build on SDK version lower than 25

I have an older Android phone, and I think this is the reason why I’ve been unable to get the recordAudio permission. So, I tried to set project to build on version 21, but Android Studio says that the project will only allow version 25 as a minimum. I can’t understand this, and it is frustrating. I wish I knew what I was doing wrong.

Hmmm that’s odd. The JUCE Demo will compile out-of-the-box for SDK level 10. Can you try the JUCE Demo? You’ll need to open it in the projucer once and then save the project so that the Android build folder picks up your Android sdk folder.

I noticed this and commented here on this thread - not sure if it was picked up though:

This seems to have broken the default Min SDK Version of 10 - added in 16.

/Users/lee/Development/cpp/JUCE/Projects/MIDISynth-Circuit/Builds/Android/app/src/main/java/com/sigabort/midisynthcircuit/MIDISynthCircuit.java
Error:(109, 85) error: cannot find symbol variable READ_EXTERNAL_STORAGE
Error:Execution failed for task ‘:app:compileDebug_DebugJavaWithJavac’.

Compilation failed; see the compiler error output for details.

If you are targeting SDK 10 then you need to unclick READ/WRITE_EXTERNAL_STORAGE in the Projucer and re-save. You cannot use those permissions if you are trying to compile for anything <16.

1 Like

I had problems with compiling the JUCE Demo too, but found a solution: I opened a project that used a more recent SDK level, then I manually changed the build.gradle file. Android Studio asked me to sync the gradle changes. It complained that I did not have android-10 in my SDK folder, but this time it offered a link to install SDK level 10.

I got the JUCE Demo to run on my tablet (which is running Android 5.0.1), but the recording demo doesn’t work. When I click record, nothing happens. The button text changes to say “stop”, but the waveform display shows nothing, and the stop button is non-responsive. I checked my “Documents” folder to see if something is there, but nothing.

We test that the JUCE demo works out-of-the-box with Android Studio all the time. I’m really surprised you need to do this.

Also, we have disabled audio recording if you are trying to record in the emulator. There was a version of AS recently which would crash the emulator if you tried to record anything, so I disabled it.

It’s not that surprising, if you think about it. It was only a problem for me because I am new to Android development and had never previously installed SDK level 10. But since you guys are testing all the time, you must already have the older SDKs installed.

If you have disabled audio recording in the JUCE Demo, and then I copied the code from the JUCE Demo to write my app, do you think its possible that I inadvertantly disabled audio recording in my app in the same way? That maybe this is the reason I can’t record audio on my android devices?

I test on a fresh install of Android Studio regularly and AS will then ask me to install SDK level 10 when I open the JuceDemo. So I still don’t understand why you need to open another project first.

Did you tick the ‘Specify audio record permission’ check-box in the Projucer (always remember to re-save your project so that the exporters are re-created after changing anything in the Projucer)?

If you are supporting newer SDKs (I think >= 21) then you will also need to get the permission at runtime. See lines MainWindow.cpp:642 and MainWindow.cpp:648 of the JUCE demo to see how to do this. This will also work for older SDKs as the permission will simply be immediately granted on these SDKs (but it’s not necessary).

Yes, the “Specify audio record permission” was ticked by default, and I double checked it again, to be sure. Also, I had copied that RuntimePermission function and callback.

Interestingly enough, it seems that the RuntimePermission succeeds. But then I think something goes wrong when I initialise the AudioDeviceManager. See the log entries in the screenshot below.

The second screenshot shows where my app inevitably crashes as soon as it begins recording. It crashes because the pointer, inputChannelData, in my audioDeviceIOCallback is NULL.

Just before the first red line in your first screenshot, there is a long line starting with “OpenSL:”. Can you send me a full copy of that line?

For some reason it seems like floatingPointSupport in juce_android_OpenSL.cpp:1030 is true on your phone (when it should be false on any SDK < 21).

I have two devices, and am currently testing on a tablet that has Android 5.0.1 (SDK 21).
Here is the plain text from the log:

07-07 11:11:15.646 30389-30389/com.juxtapus.mymuse I/JUCE: JUCE v5.0.2
07-07 11:11:15.660 30389-30389/com.juxtapus.mymuse I/JUCE: Audio recording granted
07-07 11:11:17.991 30389-30389/com.juxtapus.mymuse I/JUCE: Audio device - min buffers: 16384, 7056; 44100 Hz; input chans: 2
07-07 11:11:18.563 30389-30389/com.juxtapus.mymuse I/JUCE: OpenSL: numInputChannels = 1, numOutputChannels = 2, nativeBufferSize = 1024, nativeSampleRate = 44100, actualBufferSize = 6144, audioBuffersToEnqueue = 8, sampleRate = 44100, supportsFloatingPoint = true
07-07 11:11:18.565 30389-30389/com.juxtapus.mymuse E/libOpenSLES: Cannot create AudioRecorder: data sink must be in PCM format
07-07 11:11:18.566 30389-30389/com.juxtapus.mymuse E/libOpenSLES: Cannot create AudioRecorder: invalid source or sink
07-07 11:11:18.567 30389-30389/com.juxtapus.mymuse W/libOpenSLES: Leaving Engine::CreateAudioRecorder (SL_RESULT_PARAMETER_INVALID)
07-07 11:11:18.569 30389-30389/com.juxtapus.mymuse D/AudioTrack: audiotrack 0xafc42980 set Type 3, rate 44100, fmt 5, chn 3, fcnt 0, flags 0004
07-07 11:11:18.570 30389-30389/com.juxtapus.mymuse D/AudioTrack: mChannelMask 0x3
07-07 11:11:18.575 30389-30389/com.juxtapus.mymuse D/AudioTrackCenter: addTrack, trackId:0xa2b02000, frameCount:4096, sampleRate:44100, trackPtr:0xafc42980
07-07 11:11:18.575 30389-30389/com.juxtapus.mymuse D/AudioTrackCenter: mAfSampleRate 44100, sampleRate 44100, AfFrameCount 1024 , mAfSampleRate 44100, frameCount 4096
07-07 11:11:18.616 30389-30389/com.juxtapus.mymuse I/JUCE: Created 2 channels
07-07 11:11:30.033 30389-30389/com.juxtapus.mymuse I/JUCE: Audio device - min buffers: 16384, 7056; 44100 Hz; input chans: 2
07-07 11:11:30.037 30389-30389/com.juxtapus.mymuse I/JUCE: OpenSL: numInputChannels = 1, numOutputChannels = 2, nativeBufferSize = 1024, nativeSampleRate = 44100, actualBufferSize = 6144, audioBuffersToEnqueue = 8, sampleRate = 44100, supportsFloatingPoint = true
07-07 11:11:30.038 30389-30389/com.juxtapus.mymuse E/libOpenSLES: Cannot create AudioRecorder: data sink must be in PCM format
07-07 11:11:30.038 30389-30389/com.juxtapus.mymuse E/libOpenSLES: Cannot create AudioRecorder: invalid source or sink
07-07 11:11:30.038 30389-30389/com.juxtapus.mymuse W/libOpenSLES: Leaving Engine::CreateAudioRecorder (SL_RESULT_PARAMETER_INVALID)
07-07 11:11:30.043 30389-30389/com.juxtapus.mymuse D/AudioTrack: audiotrack 0xafc42e80 set Type 3, rate 44100, fmt 5, chn 3, fcnt 0, flags 0004
07-07 11:11:30.045 30389-30389/com.juxtapus.mymuse D/AudioTrack: mChannelMask 0x3
07-07 11:11:30.046 30389-30389/com.juxtapus.mymuse D/AudioTrackCenter: addTrack, trackId:0xa2b0a040, frameCount:4096, sampleRate:44100, trackPtr:0xafc42e80
07-07 11:11:30.046 30389-30389/com.juxtapus.mymuse D/AudioTrackCenter: mAfSampleRate 44100, sampleRate 44100, AfFrameCount 1024 , mAfSampleRate 44100, frameCount 4096

Hmmm ok it seems that JUCE thinks that your device support floating point audio. Can you, just for debugging, temporarily override this by forcing the function at juce_android_OpenSL.cpp:1020 to return false;

1 Like

This completely solved the problem! Recording is working and the error message has disappeared from the log:

07-07 18:38:33.527 5404-5404/com.juxtapus.mymuse I/JUCE: Audio recording granted
07-07 18:38:37.822 5404-5404/com.juxtapus.mymuse I/JUCE: Audio device - min buffers: 16384, 7056; 44100 Hz; input chans: 2
07-07 18:38:38.421 5404-5404/com.juxtapus.mymuse I/JUCE: OpenSL: numInputChannels = 1, numOutputChannels = 2, nativeBufferSize = 1024, nativeSampleRate = 44100, actualBufferSize = 6144, audioBuffersToEnqueue = 8, sampleRate = 44100, supportsFloatingPoint = false
07-07 18:38:38.424 5404-5404/com.juxtapus.mymuse D/AudioRecord: openRecord_l
07-07 18:38:38.547 5404-5404/com.juxtapus.mymuse D/AudioTrack: audiotrack 0xb4a8f080 set Type 3, rate 44100, fmt 1, chn 3, fcnt 0, flags 0004
07-07 18:38:38.561 5404-5404/com.juxtapus.mymuse D/AudioTrack: mChannelMask 0x3
07-07 18:38:38.570 5404-5404/com.juxtapus.mymuse D/AudioTrackCenter: addTrack, trackId:0xa2b04040, frameCount:4096, sampleRate:44100, trackPtr:0xb4a8f080
07-07 18:38:38.570 5404-5404/com.juxtapus.mymuse D/AudioTrackCenter: mAfSampleRate 44100, sampleRate 44100, AfFrameCount 1024 , mAfSampleRate 44100, frameCount 4096
07-07 18:38:38.570 5404-5404/com.juxtapus.mymuse D/AudioRecord: stop
07-07 18:38:38.664 5404-5404/com.juxtapus.mymuse D/AudioRecord: return status 0
07-07 18:38:38.665 5404-5404/com.juxtapus.mymuse I/JUCE: Created 2 channels
07-07 18:38:50.402 5404-5404/com.juxtapus.mymuse I/JUCE: Audio device - min buffers: 16384, 7056; 44100 Hz; input chans: 2
07-07 18:38:50.405 5404-5404/com.juxtapus.mymuse I/JUCE: OpenSL: numInputChannels = 1, numOutputChannels = 2, nativeBufferSize = 1024, nativeSampleRate = 44100, actualBufferSize = 6144, audioBuffersToEnqueue = 8, sampleRate = 44100, supportsFloatingPoint = false
07-07 18:38:50.407 5404-5404/com.juxtapus.mymuse D/AudioRecord: openRecord_l
07-07 18:38:50.428 5404-5404/com.juxtapus.mymuse D/AudioTrack: audiotrack 0xb4a8a580 set Type 3, rate 44100, fmt 1, chn 3, fcnt 0, flags 0004
07-07 18:38:50.430 5404-5404/com.juxtapus.mymuse D/AudioTrack: mChannelMask 0x3
07-07 18:38:50.431 5404-5404/com.juxtapus.mymuse D/AudioTrackCenter: addTrack, trackId:0xa2b0a0c0, frameCount:4096, sampleRate:44100, trackPtr:0xb4a8a580
07-07 18:38:50.431 5404-5404/com.juxtapus.mymuse D/AudioTrackCenter: mAfSampleRate 44100, sampleRate 44100, AfFrameCount 1024 , mAfSampleRate 44100, frameCount 4096
07-07 18:38:50.431 5404-5404/com.juxtapus.mymuse D/AudioRecord: stop
07-07 18:38:50.532 5404-5404/com.juxtapus.mymuse D/AudioRecord: return status 0

Arrggghhh the joy of android. Any device with an SDK target of >= 21 should be able to support floating point audio on any interface. But I guess OEMs don’t really always follow the guidelines. Now I need to think of some workaround for this issue…

2 Likes

Thanks for your help. I’m looking forward to whatever you come up with for a permanent solution. For now, I will continue with forcing the function to return false. (My app is only at the alpha stage, and not public, so this should be OK)

Hey Fabian. Any updates?

This is fixed on develop with commit 0d601fa.

2 Likes

@fabian Just wanted to show some appreciation for linking the commit hashes on the regular!

Thanks Fabian.

I thought I should add that I found another potential issue. It is not so serious, and I can easily work around it, but I thought I should mention it. I recently decided to create an OS/X version of my app, so that it is easier to generate reports based on my DSP algorithm performance etc and have access to my hard drive. Anyway, the sound wasn’t working at all (everything was silent) and I couldn’t understand why. The audio initialisation seemed to have worked, at least as far as the log output showed.

Eventually, I realised that the sound problem could be fixed so long as a I commented out the line asking for record audio permissions. For some reason OS/X seems to hate this call and shuts down all audio after that.

Actually, maybe the problem is a bit more significant than I initially thought. It is not occurring because I asked for record audio permissions. It is occurring when I try to initialise the AudioDeviceManager. After that my AudioAppComponent is mute.