How to design a simple Audio Recorder App in Android Studio?

This video shows the steps to create a simple Android Audio/ Sound Recorder App using Android Studio.

This video towards the end also shows how to debug the code and build the code into APK to be able to install in your phone.

We will be glad to hear from you regarding any query, suggestions or appreciations at: programmerworld1990@gmail.com

Source Code:

package com.example.myaudiorecorder.myaudiorecorder;

import android.Manifest;
import android.content.pm.PackageManager;
import android.media.MediaRecorder;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import java.io.File;

public class MainActivity extends AppCompatActivity {

MediaRecorder mediaRecorder;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PackageManager.PERMISSION_GRANTED);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PackageManager.PERMISSION_GRANTED);

mediaRecorder = new MediaRecorder();
}

public void startRecording(View view){

try {

mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file = new File(path, “/YouTubeAudio.3gp”);

mediaRecorder.setOutputFile(file);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

mediaRecorder.prepare();
mediaRecorder.start();

}
catch (Exception e){
e.printStackTrace();
}
}

public void stopRecording(View view){

mediaRecorder.stop();
mediaRecorder.release();

}

}

<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
package=”com.example.myaudiorecorder.myaudiorecorder”>

<uses-permission android:name=”android.permission.RECORD_AUDIO”/>
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE”/>

<application
android:allowBackup=”true”
android:icon=”@mipmap/ic_launcher”
android:label=”@string/app_name”
android:roundIcon=”@mipmap/ic_launcher_round”
android:supportsRtl=”true”
android:theme=”@style/AppTheme”>
<activity android:name=”.MainActivity”>
<intent-filter>
<action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
</application>

</manifest>

<?xml version=”1.0″ encoding=”utf-8″?>
<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android&#8221;
xmlns:app=”http://schemas.android.com/apk/res-auto&#8221;
xmlns:tools=”http://schemas.android.com/tools&#8221;
android:layout_width=”match_parent”
android:layout_height=”match_parent”
tools:context=”com.example.myaudiorecorder.myaudiorecorder.MainActivity”>

<Button
android:id=”@+id/button”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignParentStart=”true”
android:layout_alignParentTop=”true”
android:layout_marginStart=”129dp”
android:layout_marginTop=”93dp”
android:onClick=”startRecording”
android:text=”@string/start” />

<Button
android:id=”@+id/button2″
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignStart=”@+id/button”
android:layout_below=”@+id/button”
android:layout_marginTop=”146dp”
android:onClick=”stopRecording”
android:text=”@string/stop” />
</RelativeLayout>

Top YouTube comments:

My saved file in the emulator will not open. It says “can’t open file”. Do you know why?
Check whether the SDK level of your emulator is greater than the min SDK level of your App (you can check this in manifest file). You can also try different emulator and check. Some of the APIs may not be compliant in a specific version of Android.

As mentioned in the developers documentation, MediaRecorder would work only on real devices .

14 comments

  1. Start button code is encapsulated with Try-Catch. So, it should prevent the App from stopping or crashing. Please refer to the “startRecording” method code above.

    However, if stop button is also stopping the App (crashing), then the first step, I will suggest, is to bind it with try-catch as done in startRecording method. Please implement similar try-catch in the stopRecording method also.

    The above step will just prevent from the App to crash You will need to further analyse the issue. Either you can debug the code, or use some kind or print command like “Toast” command to show the exception being thrown.

    My guess is most likely the access to Record audio or write external storage permission are not granted. I hope you have defined the access in both java code and manifest file as shown in my code above.

    The other reason which could be possible is that MediaRecorder object is not created successfully in the App. However, it will be only certain once you are able to print the text of the exception being thrown.

    If above suggestions doesn’t solves the issue then please post the exception log which is being thrown. This will help us to troubleshoot your problem more accurately.

    Cheers
    Programmer World
    https://programmerworld.co

    1. Hello sir, thanks for your reply, try-catch implement to “stop” button is done, then permission from Manifests also done. but is not gonna solve till stopping the app.
      debug log is given below… please help

      02/24 11:42:55: Launching ‘MainActivity’ on htc m8.
      $ adb shell am start -n “com.example.myaudiorecorder/com.example.myaudiorecorder.MainActivity” -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
      Waiting for application to come online: com.example.myaudiorecorder | com.example.myaudiorecorder.test
      Waiting for application to come online: com.example.myaudiorecorder | com.example.myaudiorecorder.test
      Waiting for application to come online: com.example.myaudiorecorder | com.example.myaudiorecorder.test
      Waiting for application to come online: com.example.myaudiorecorder | com.example.myaudiorecorder.test
      Connecting to com.example.myaudiorecorder
      Connected to the target VM, address: ‘localhost:8622’, transport: ‘socket’
      Capturing and displaying logcat messages from application. This behavior can be disabled in the “Logcat output” section of the “Debugger” settings page.
      I/art: Debugger is active
      I/System.out: Debugger has connected
      waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: waiting for debugger to settle…
      I/System.out: debugger has settled (1461)
      W/System: ClassLoader referenced unknown path: /data/app/com.example.myaudiorecorder-2/lib/arm
      W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter androidx.vectordrawable.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
      I/art: Rejecting re-init on previously-failed class java.lang.Class: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
      at void androidx.core.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
      at void androidx.appcompat.widget.ActionBarContainer.(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
      at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
      at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
      at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
      at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
      at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
      at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
      at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
      at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
      at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
      at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
      at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
      at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
      at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
      at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
      at void com.example.myaudiorecorder.MainActivity.onCreate(android.os.Bundle) (MainActivity.java:27)
      at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6684)
      at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1119)
      at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2637)
      at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
      at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
      at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
      at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
      at void android.os.Looper.loop() (Looper.java:154)
      at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
      at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
      at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
      at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
      Caused by: java.lang.ClassNotFoundException: Didn’t find class “android.view.View$OnUnhandledKeyEventListener” on path: DexPathList[[zip file “/data/app/com.example.myaudiorecorder-2/base.apk”],nativeLibraryDirectories=[/data/app/com.example.myaudiorecorder-2/lib/arm, /system/lib, /vendor/lib]]
      at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:56)
      at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:380)
      at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
      at void androidx.core.view.ViewCompat.setBackground(android.view.View, android.graphics.drawable.Drawable) (ViewCompat.java:2341)
      at void androidx.appcompat.widget.ActionBarContainer.(android.content.Context, android.util.AttributeSet) (ActionBarContainer.java:62)
      at java.lang.Object java.lang.reflect.Constructor.newInstance0!(java.lang.Object[]) (Constructor.java:-2)
      at java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[]) (Constructor.java:430)
      at android.view.View android.view.LayoutInflater.createView(java.lang.String, java.lang.String, android.util.AttributeSet) (LayoutInflater.java:645)
      at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:787)
      at android.view.View android.view.LayoutInflater.createViewFromTag(android.view.View, java.lang.String, android.content.Context, android.util.AttributeSet) (LayoutInflater.java:727)
      at void android.view.LayoutInflater.rInflate(org.xmlpull.v1.XmlPullParser, android.view.View, android.content.Context, android.util.AttributeSet, boolean) (LayoutInflater.java:858)
      at void android.view.LayoutInflater.rInflateChildren(org.xmlpull.v1.XmlPullParser, android.view.View, android.util.AttributeSet, boolean) (LayoutInflater.java:821)
      at android.view.View android.view.LayoutInflater.inflate(org.xmlpull.v1.XmlPullParser, android.view.ViewGroup, boolean) (LayoutInflater.java:518)
      at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup, boolean) (LayoutInflater.java:426)
      at android.view.View android.view.LayoutInflater.inflate(int, android.view.ViewGroup) (LayoutInflater.java:377)
      at android.view.ViewGroup androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:607)
      at void androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
      at void androidx.appcompat.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
      at void androidx.appcompat.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
      at void com.example.myaudiorecorder.MainActivity.onCreate(android.os.Bundle) (MainActivity.java:27)
      at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6684)
      at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1119)
      at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2637)
      at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2751)
      at void android.app.ActivityThread.-wrap12(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
      at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1496)
      at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:102)
      at void android.os.Looper.loop() (Looper.java:154)
      at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6186)
      at java.lang.Object java.lang.reflect.Method.invoke!(java.lang.Object, java.lang.Object[]) (Method.java:-2)
      at void com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run() (ZygoteInit.java:889)
      at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:779)
      W/Activity: Can reqeust only one set of permissions at a time
      I/Adreno-EGL: : EGL 1.4 QUALCOMM build: Nondeterministic_AU_msm8974_LA.BF.1.1.3_RB1__release_AU (Ia6c73e7530)
      OpenGL ES Shader Compiler Version: E031.29.00.00
      Build Date: 12/04/15 Fri
      Local Branch: mybranch17080070
      Remote Branch: quic/LA.BF.1.1.3_rb1.5
      Local Patches: NONE
      Reconstruct Branch: NOTHING
      I/OpenGLRenderer: Initialized EGL, version 1.4
      D/OpenGLRenderer: Swap behavior 1
      W/Adreno-ES20: : open failed: errno 13
      D/AndroidRuntime: Shutting down VM
      E/AndroidRuntime: FATAL EXCEPTION: main
      Process: com.example.myaudiorecorder, PID: 32072
      java.lang.IllegalStateException: Could not execute method for android:onClick
      at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:390)
      at android.view.View.performClick(View.java:5637)
      at android.view.View$PerformClick.run(View.java:22433)
      at android.os.Handler.handleCallback(Handler.java:751)
      at android.os.Handler.dispatchMessage(Handler.java:95)
      at android.os.Looper.loop(Looper.java:154)
      at android.app.ActivityThread.main(ActivityThread.java:6186)
      at java.lang.reflect.Method.invoke(Native Method)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
      Caused by: java.lang.reflect.InvocationTargetException
      at java.lang.reflect.Method.invoke(Native Method)
      at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385)
      at android.view.View.performClick(View.java:5637) 
      at android.view.View$PerformClick.run(View.java:22433) 
      at android.os.Handler.handleCallback(Handler.java:751) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:154) 
      at android.app.ActivityThread.main(ActivityThread.java:6186) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
      Caused by: 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)
      at com.example.myaudiorecorder.MainActivity.startRecording(MainActivity.java:48)
      at java.lang.reflect.Method.invoke(Native Method) 
      at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:385) 
      at android.view.View.performClick(View.java:5637) 
      at android.view.View$PerformClick.run(View.java:22433) 
      at android.os.Handler.handleCallback(Handler.java:751) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:154) 
      at android.app.ActivityThread.main(ActivityThread.java:6186) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 

  2. On a quick glance through your log, it seems like it is throwing ClassNotFoundException. I am not sure why it is looking for the class as mentioned in the below error log:

    Caused by: java.lang.ClassNotFoundException: Didn’t find class “android.view.View$OnUnhandledKeyEventListener” on path: DexPathList[[zip file “/data/app/com.example.myaudiorecorder-2/base.apk”]

    It is because of this issue that later it is showing FATAL EXCEPTION and onClick method is not executing. As mentioned in the below error log:

    FATAL EXCEPTION: main
    Process: com.example.myaudiorecorder, PID: 32072
    java.lang.IllegalStateException: Could not execute method for android:onClick

    Would it be possible for you to copy the complete code, so that I can debug the code in my environment and let you know the solution. I think there is some very trivial issue in the code which we are missing. Please copy your code here.

    Cheers
    Programmer World
    https://programmerworld.co

    1. oh Sure… last night when i’m trying.. to solve it working but work only in emulator & the other problem is, recorded file saved in download but no audio playback i mean no sound out when the file i played. please check the code…

      package com.example.myaudiorecorder;

      import androidx.annotation.RequiresApi;
      import androidx.appcompat.app.AppCompatActivity;
      import androidx.core.app.ActivityCompat;

      import android.Manifest;
      import android.annotation.SuppressLint;
      import android.content.pm.PackageManager;
      import android.media.MediaRecorder;
      import android.os.Build;
      import android.os.Bundle;
      import android.os.Environment;
      import android.view.View;

      import java.io.File;

      import static android.os.Environment.getExternalStoragePublicDirectory;

      public class MainActivity extends AppCompatActivity {

      MediaRecorder mediaRecorder;

      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PackageManager.PERMISSION_GRANTED);
      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PackageManager.PERMISSION_GRANTED);

      mediaRecorder = new MediaRecorder();
      }

      @RequiresApi(api = Build.VERSION_CODES.O)
      public void startRecording(View view){

      try {

      mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
      mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_WB);

      File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
      File file = new File(path, “/YouTubeAudio.amr”);

      mediaRecorder.setOutputFile(file);
      mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_WB);

      mediaRecorder.prepare();
      mediaRecorder.start();

      }
      catch (Exception e){
      e.printStackTrace();
      }
      }

      public void stopRecording(View view){
      try {

      mediaRecorder.stop();
      mediaRecorder.release();
      } catch (Exception e) {
      e.printStackTrace();
      }
      }

      }

  3. I went through your code (thanks for posting it). It looks fine. There is no error in it. I could not run it at my end as I do not have the complete environment (Application folder with supporting files). So, it will be tough to say the exact reason why there is no sound while using it on your real phone.

    However, I will suggest you to try changing the format of your saved file to .3gp file format which I have used (rather than using .amr file type).

    Also, if possible try the DEFAULT audio source option in the “mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT)” command. Technically, using MIC option is correct but internally different phones models (OEMs) maps these options to different input source for the audio. So, best will be to use DEFAULT option which will automatically choose the default working input source (assuming your audio input is working for other activities such as during phone call).

    Please let me know if above suggestions help solve the issue.

    Good Luck
    Programmer World
    https://programmerworld.co

    1. It’s ok.. & Thank you for your reply… as per you suggest for changing the format i already did this, but nothings gonna happen. i’,m still working on it, if i success!!, then i’ll share with you.
      thank you sir. & i think i’ll disturb you again.. :p

  4. hey sir , when i press start or stop the app this going ( he leave’s the app totally)
    what can i do please !!

  5. hey sir,
    when i press stop the application is off . it leave’s the app how can i solve this problem please

Leave a Reply

%d bloggers like this: