Reputation: 55
I am recording audio in my app and I am struggling with the MediaRecorder class in
import android.media.MediaRecorder;
The problem is that the code compiles but does not seem to run on devices with API level < 26 because apparently the the function MediaRecorder.setOutputFormat()
does not exists prior to API 26 according to the inline error message in Android Studio. Similarly when I run the code on an emulator with API 24 I get a crash with runtime error:
java.lang.NoSuchMethodError: No virtual method setOutputFile(Ljava/io/File;)V in class Landroid/media/MediaRecorder; or its super classes (declaration of 'android.media.MediaRecorder' appears in /system/framework/framework.jar)
As a quick fix I just increased my minimal SDK level in the gradle file to 26 and everthing works just fine. However, I don't want my app to be restricted to Android 8.0 and higher, because 7.x is still so popular.
So my first question is: How can it be that only one function of the whole MediaRecorder
library is not available, how did people use the MediaRecorder
before API 26? I cannot to find anything about that online.
Second question: How can I fix the problem, so I can record audio for API level 24+? Do I have to use another library?
This is the part of my Activity where the I am setting up the recorder and start the recording. Again, this works fine when the minimal SDK is 26...
private MediaRecorder recorder;
private void startRecording(){
if(!recordingActive) {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setAudioChannels(1);
recorder.setOutputFormat(output_formats[currentFormat]);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
switch(activeAudioButton) {
case AUDIO_BUTTON_A:
recorder.setOutputFile(tempSoundFileA); // <--
break;
case AUDIO_BUTTON_B:
recorder.setOutputFile(tempSoundFileB); // <--
break;
}
recorder.setOnErrorListener(errorListener);
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
recordingActive = true;
runOnUiThread(new Runnable() {
@Override
public void run() {
speakNowTextView.setVisibility(View.VISIBLE);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is my gradle file:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.my.app"
minSdkVersion 24
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:support-v4:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'
implementation 'com.android.support:preference-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
}
Upvotes: 4
Views: 2918
Reputation: 330
When using an API level below 26, you can pass in a string containing the file path instead. If you specifically need to work with a File object, use file.getAbsolutePath()
in Java or file.absolutePath
in Kotlin.
Upvotes: 8
Reputation: 21
setOutputFile works works with a String as an argument not a file.
Upvotes: 0