آموزش ساخت ضبط صوت در برنامه نویسی اندروید

سلام دوستان امیدوارم حالتان خوب باشد در این سری از آموزش برنامه نویسی اندروید به آموزش ساخت ضبط صوت در برنامه نویسی اندروید می پردازیم در این آموزش از کلاس MediaRecorder برای ذخیره صدا استفاده می شود از امکانات آن می توان به استفاده از RunTime Permission نمایش لیست صداهای ذخیره شده امکان Pause و Play اشاره کرددر ادامه می توانید پیش نمایش آن را مشاهده کنید.
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
در این آموزش از RecyclerView استفاده می شود پس لازم است آن را همانند زبر در به پروژه اضافه کنید
وارد فایل build.gradle  شده و در بخش dependencies خط زیر را اضافه کنید.

compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'

پروژه را Sync کنید.
یک فایل در ادامه برایتان قرار داده شده است آن را دانلود کنید و در پوشه drawable قرار دهید.
لینک دانلود عکس ها 
یک پوشه در بخش res به نام menu ایجاد کرده و یک لایه به نام list_menu.xml در آن ساخته و کد زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/item_list"
        android:title="List"
        app:showAsAction="always|withText"
        />
</menu>

وارد مسیر res/Values شده فایل strings.xml را باز کرد و خط های زیر را به آن اضافه کنید.

<resources>
    <string name="app_name">VoiceRecorderApp</string>
    <string name="_00_00">00:00</string>
</resources>

در همان مسیر فایل Styles.xml را باز کرده و کد زیر را جایگزین کد قبلی کنید.

 <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@android:color/white</item>
        <item name="colorPrimaryDark">@android:color/darker_gray</item>
        <item name="colorAccent">@android:color/holo_red_light</item>
        <item name="android:actionMenuTextColor">@android:color/holo_red_light</item>
        <item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
    </style>

سه layout به نام های زیر وجود دارد

  • activity_main.xml
  • activity_recording_list.xml
  • recording_item_layout.xml

اولی برای ذخیره صدا استفاده می شود.
دومی برای نمایش لیستی از صداهای ذخیره شده استفاده می شود.
سومی هم Item های RecyclerView هستند که در بخش قبلی نمایش داده می شوند.
به ترتیب کدها را قرار دهید.
layout اول یک فایل به نام activity_main.xml ایجاد کرده و کدهای زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <LinearLayout
        android:id="@+id/linearLayoutRecorder"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_below="@+id/toolbar"
        android:layout_marginTop="20dp"
        >
        <Chronometer
            android:id="@+id/chronometerTimer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="60sp"
            android:textColor="@android:color/darker_gray"
            android:layout_gravity="center_horizontal"
            />
        <LinearLayout
            android:id="@+id/linearLayoutPlay"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:visibility="gone"
            >
            <ImageView
                android:id="@+id/imageViewPlay"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_play"
                android:layout_gravity="center_vertical"
                android:clickable="true"
                android:tint="@android:color/darker_gray"
                android:focusable="true"
                android:background="?android:attr/selectableItemBackground"
                />
            <SeekBar
                android:id="@+id/seekBar"
                android:layout_width="match_parent"
                android:layout_weight="1"
                android:layout_gravity="center_vertical"
                android:layout_height="wrap_content"
                />
        </LinearLayout>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_gravity="center_horizontal"
            android:gravity="center_vertical"
            android:layout_marginTop="10dp"
            >
            <ImageView
                android:id="@+id/imageViewRecord"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_microphone"
                android:background="?android:attr/selectableItemBackground"
                android:layout_marginEnd="10dp"
                android:clickable="true"
                android:focusable="true"
                />
            <ImageView
                android:id="@+id/imageViewStop"
                android:layout_width="42dp"
                android:layout_height="42dp"
                android:src="@drawable/ic_stop"
                android:tint="@android:color/darker_gray"
                android:background="?android:attr/selectableItemBackground"
                android:layout_gravity="center_vertical"
                android:visibility="gone"
                android:clickable="true"
                android:focusable="true"
                />
        </LinearLayout>
    </LinearLayout>
</RelativeLayout>

 
یک لایه به نام activity_recording_list.xml ایجاد کرده و کدهای زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewRecordings"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar"
        />
    <TextView
        android:id="@+id/textViewNoRecordings"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="No Recordings found."
        android:visibility="gone"
        android:layout_centerInParent="true"
        android:textColor="@android:color/darker_gray"
        />
</RelativeLayout>

و در آخر یک لایه به نام recording_item_layout.xml ایجاد کرده و کدهای زیر را در آن قرار دهید.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:paddingTop="10dp"
    android:paddingBottom="10dp"
    android:paddingStart="10dp">
    <ImageView
        android:id="@+id/imageViewPlay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_play"
        android:layout_gravity="center_vertical"
        android:clickable="true"
        android:tint="@android:color/darker_gray"
        android:focusable="true"
        android:background="?android:attr/selectableItemBackground"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_toEndOf="@+id/imageViewPlay"
        android:layout_marginStart="30dp"
        >
        <TextView
            android:id="@+id/textViewRecordingname"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:text="Voice 001"
            android:textColor="@android:color/holo_red_light"
            android:textStyle="bold"
            />
        <SeekBar
            android:id="@+id/seekBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:visibility="gone"
            />
        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="@android:color/darker_gray"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="20dp"
            />
    </LinearLayout>
</RelativeLayout>

در نهایت بخش layout به پایان رسید.
بخش java که شامل  فایل جاوا می شود که عبارتند از :

  • MainActivity.java
  • Recording.java
  • RecordingAdapter.java
  • RecordingListActivity.java

اولی اکتیوتی اصلی ماست و function های اصلی در آنجا قرار دارد مثل ضبط صدا , runtimePermission و… .
دومی model ماست که برای پر کردن recyclerview استفاده خواهد شد.
سومی Adapter سفارشی ماست که با استفاده از model و لایه recording_item_layout در recyclver پر می شود یا آن را fill می کند.
و در نهایت چهارمی لیستی از صداهای ذخیره شده (ضبط شده ) را به ما نمایش  میدهد.
به ترتیب کدهای جاوا را قرار دهید.
یک فایل به نام Recording.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
/**
 * Created by JFP on 10/3/2018.
 */
public class Recording {
    String Uri, fileName;
    boolean isPlaying = false;
    public Recording(String uri, String fileName, boolean isPlaying) {
        Uri = uri;
        this.fileName = fileName;
        this.isPlaying = isPlaying;
    }
    public String getUri() {
        return Uri;
    }
    public String getFileName() {
        return fileName;
    }
    public boolean isPlaying() {
        return isPlaying;
    }
    public void setPlaying(boolean playing){
        this.isPlaying = playing;
    }
}

یک فایل دیگر به نام RecordingAdapter.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.transition.TransitionManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import java.io.IOException;
import java.util.ArrayList;
/**
 * Created by JFP on 10/3/2018.
 */
public class RecordingAdapter  extends RecyclerView.Adapter<RecordingAdapter.ViewHolder>{
    private Context context;
    private ArrayList<Recording> recordingArrayList;
    private MediaPlayer mPlayer;
    private boolean isPlaying = false;
    private int last_index = -1;
    public RecordingAdapter(Context context, ArrayList<Recording> recordingArrayList){
        this.context = context;
        this.recordingArrayList = recordingArrayList;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.recording_item_layout, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        setUpData(holder,position);
    }
    private void setUpData(ViewHolder holder, int position) {
        Recording recording = recordingArrayList.get(position);
        holder.textViewName.setText(recording.getFileName());
        if( recording.isPlaying() ){
            holder.imageViewPlay.setImageResource(R.drawable.ic_pause);
            TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
            holder.seekBar.setVisibility(View.VISIBLE);
            holder.seekUpdation(holder);
        }else{
            holder.imageViewPlay.setImageResource(R.drawable.ic_play);
            TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
            holder.seekBar.setVisibility(View.GONE);
        }
        holder.manageSeekBar(holder);
    }
    @Override
    public int getItemCount() {
        return recordingArrayList.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder {
        ImageView imageViewPlay;
        SeekBar seekBar;
        TextView textViewName;
        private String recordingUri;
        private int lastProgress = 0;
        private Handler mHandler = new Handler();
        ViewHolder holder;
        public ViewHolder(View itemView) {
            super(itemView);
            imageViewPlay = itemView.findViewById(R.id.imageViewPlay);
            seekBar = itemView.findViewById(R.id.seekBar);
            textViewName = itemView.findViewById(R.id.textViewRecordingname);
            imageViewPlay.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int position = getAdapterPosition();
                    Recording recording = recordingArrayList.get(position);
                    recordingUri = recording.getUri();
                        if( isPlaying ){
                            stopPlaying();
                            if( position == last_index ){
                                recording.setPlaying(false);
                                stopPlaying();
                                notifyItemChanged(position);
                            }else{
                                markAllPaused();
                                recording.setPlaying(true);
                                notifyItemChanged(position);
                                startPlaying(recording,position);
                                last_index = position;
                            }
                        }else {
                            if( recording.isPlaying() ){
                                recording.setPlaying(false);
                                stopPlaying();
                                Log.d("isPlayin","True");
                            }else {
                                startPlaying(recording,position);
                                recording.setPlaying(true);
                                seekBar.setMax(mPlayer.getDuration());
                                Log.d("isPlayin","False");
                            }
                            notifyItemChanged(position);
                            last_index = position;
                        }
                    }
            });
        }
        public void manageSeekBar(ViewHolder holder){
            holder.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                    if( mPlayer!=null && fromUser ){
                        mPlayer.seekTo(progress);
                    }
                }
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                }
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                }
            });
        }
        private void markAllPaused() {
            for( int i=0; i < recordingArrayList.size(); i++ ){
                recordingArrayList.get(i).setPlaying(false);
                recordingArrayList.set(i,recordingArrayList.get(i));
            }
            notifyDataSetChanged();
        }
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                seekUpdation(holder);
            }
        };
        private void seekUpdation(ViewHolder holder) {
            this.holder = holder;
            if(mPlayer != null){
                int mCurrentPosition = mPlayer.getCurrentPosition() ;
                holder.seekBar.setMax(mPlayer.getDuration());
                holder.seekBar.setProgress(mCurrentPosition);
                lastProgress = mCurrentPosition;
            }
            mHandler.postDelayed(runnable, 100);
        }
        private void stopPlaying() {
            try{
                mPlayer.release();
            }catch (Exception e){
                e.printStackTrace();
            }
            mPlayer = null;
            isPlaying = false;
        }
        private void startPlaying(final Recording audio, final int position) {
            mPlayer = new MediaPlayer();
            try {
                mPlayer.setDataSource(recordingUri);
                mPlayer.prepare();
                mPlayer.start();
            } catch (IOException e) {
                Log.e("LOG_TAG", "prepare() failed");
            }
            //showing the pause button
            seekBar.setMax(mPlayer.getDuration());
            isPlaying = true;
            mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    audio.setPlaying(false);
                    notifyItemChanged(position);
                }
            });
        }
    }
}

اکتیویتی به نام MainActivity.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.transition.TransitionManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Toolbar toolbar;
    private Chronometer chronometer;
    private ImageView imageViewRecord, imageViewPlay, imageViewStop;
    private SeekBar seekBar;
    private LinearLayout linearLayoutRecorder, linearLayoutPlay;
    private MediaRecorder mRecorder;
    private MediaPlayer mPlayer;
    private String fileName = null;
    private int lastProgress = 0;
    private Handler mHandler = new Handler();
    private int RECORD_AUDIO_REQUEST_CODE =123 ;
    private boolean isPlaying = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            getPermissionToRecordAudio();
        }
        initViews();
    }
    private void initViews() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("Voice Recorder");
        toolbar.setTitleTextColor(getResources().getColor(android.R.color.black));
        setSupportActionBar(toolbar);
        linearLayoutRecorder = (LinearLayout) findViewById(R.id.linearLayoutRecorder);
        chronometer = (Chronometer) findViewById(R.id.chronometerTimer);
        chronometer.setBase(SystemClock.elapsedRealtime());
        imageViewRecord = (ImageView) findViewById(R.id.imageViewRecord);
        imageViewStop = (ImageView) findViewById(R.id.imageViewStop);
        imageViewPlay = (ImageView) findViewById(R.id.imageViewPlay);
        linearLayoutPlay = (LinearLayout) findViewById(R.id.linearLayoutPlay);
        seekBar = (SeekBar) findViewById(R.id.seekBar);
        imageViewRecord.setOnClickListener(this);
        imageViewStop.setOnClickListener(this);
        imageViewPlay.setOnClickListener(this);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.list_menu,menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.item_list:
                gotoRecodingListActivity();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
    private void gotoRecodingListActivity() {
        Intent intent = new Intent(this, RecordingListActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
    @Override
    public void onClick(View view) {
        if( view == imageViewRecord ){
                prepareforRecording();
                startRecording();
        }else if( view == imageViewStop ){
            prepareforStop();
            stopRecording();
        }else if( view == imageViewPlay ){
            if( !isPlaying && fileName != null ){
                isPlaying = true;
                startPlaying();
            }else{
                isPlaying = false;
                stopPlaying();
            }
        }
    }
    private void prepareforStop() {
        TransitionManager.beginDelayedTransition(linearLayoutRecorder);
        imageViewRecord.setVisibility(View.VISIBLE);
        imageViewStop.setVisibility(View.GONE);
        linearLayoutPlay.setVisibility(View.VISIBLE);
    }
    private void prepareforRecording() {
        TransitionManager.beginDelayedTransition(linearLayoutRecorder);
        imageViewRecord.setVisibility(View.GONE);
        imageViewStop.setVisibility(View.VISIBLE);
        linearLayoutPlay.setVisibility(View.GONE);
    }
    private void stopPlaying() {
        try{
            mPlayer.release();
        }catch (Exception e){
            e.printStackTrace();
        }
        mPlayer = null;
        imageViewPlay.setImageResource(R.drawable.ic_play);
        chronometer.stop();
    }
    private void startRecording() {
        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        File root = android.os.Environment.getExternalStorageDirectory();
        File file = new File(root.getAbsolutePath() + "/VoiceRecorderSimplifiedCoding/Audios");
        if (!file.exists()) {
            file.mkdirs();
        }
        fileName =  root.getAbsolutePath() + "/VoiceRecorderSimplifiedCoding/Audios/" + String.valueOf(System.currentTimeMillis() + ".mp3");
        Log.d("filename",fileName);
        mRecorder.setOutputFile(fileName);
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        try {
            mRecorder.prepare();
            mRecorder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        lastProgress = 0;
        seekBar.setProgress(0);
        stopPlaying();
        // making the imageview a stop button
        //starting the chronometer
        chronometer.setBase(SystemClock.elapsedRealtime());
        chronometer.start();
    }
    private void stopRecording() {
        try{
            mRecorder.stop();
            mRecorder.release();
        }catch (Exception e){
            e.printStackTrace();
        }
        mRecorder = null;
        chronometer.stop();
        chronometer.setBase(SystemClock.elapsedRealtime());
        Toast.makeText(this, "Recording saved successfully.", Toast.LENGTH_SHORT).show();
    }
    private void startPlaying() {
        mPlayer = new MediaPlayer();
        try {
            mPlayer.setDataSource(fileName);
            mPlayer.prepare();
            mPlayer.start();
        } catch (IOException e) {
            Log.e("LOG_TAG", "prepare() failed");
        }
        imageViewPlay.setImageResource(R.drawable.ic_pause);
        seekBar.setProgress(lastProgress);
        mPlayer.seekTo(lastProgress);
        seekBar.setMax(mPlayer.getDuration());
        seekUpdation();
        chronometer.start();
        mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                imageViewPlay.setImageResource(R.drawable.ic_play);
                isPlaying = false;
                chronometer.stop();
            }
        });
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if( mPlayer!=null && fromUser ){
                    mPlayer.seekTo(progress);
                    chronometer.setBase(SystemClock.elapsedRealtime() - mPlayer.getCurrentPosition());
                    lastProgress = progress;
                }
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            seekUpdation();
        }
    };
    private void seekUpdation() {
        if(mPlayer != null){
            int mCurrentPosition = mPlayer.getCurrentPosition() ;
            seekBar.setProgress(mCurrentPosition);
            lastProgress = mCurrentPosition;
        }
        mHandler.postDelayed(runnable, 100);
    }
    @RequiresApi(api = Build.VERSION_CODES.M)
    public void getPermissionToRecordAudio() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    RECORD_AUDIO_REQUEST_CODE);
        }
    }
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        if (requestCode == RECORD_AUDIO_REQUEST_CODE) {
            if (grantResults.length == 3 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED
                    && grantResults[2] == PackageManager.PERMISSION_GRANTED){
            } else {
                Toast.makeText(this, "You must give permissions to use this app. App is exiting.", Toast.LENGTH_SHORT).show();
                finishAffinity();
            }
        }
    }
}

و در نهایت یک اکتیویتی دیگر به نام RecordingListActivity.java ایجاد کرده و کدهای زیر را در آن قرار دهید.

package ir.programchi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import java.io.File;
import java.util.ArrayList;
public class RecordingListActivity extends AppCompatActivity {
    private Toolbar toolbar;
    private RecyclerView recyclerViewRecordings;
    private ArrayList<Recording> recordingArraylist;
    private RecordingAdapter recordingAdapter;
    private TextView textViewNoRecordings;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recording_list);
        recordingArraylist = new ArrayList<Recording>();
        initViews();
        fetchRecordings();
    }
    private void fetchRecordings() {
        File root = android.os.Environment.getExternalStorageDirectory();
        String path = root.getAbsolutePath() + "/VoiceRecorderSimplifiedCoding/Audios";
        Log.d("Files", "Path: " + path);
        File directory = new File(path);
        File[] files = directory.listFiles();
        Log.d("Files", "Size: "+ files.length);
        if( files!=null ){
            for (int i = 0; i < files.length; i++) {
                Log.d("Files", "FileName:" + files[i].getName());
                String fileName = files[i].getName();
                String recordingUri = root.getAbsolutePath() + "/VoiceRecorderSimplifiedCoding/Audios/" + fileName;
                Recording recording = new Recording(recordingUri,fileName,false);
                recordingArraylist.add(recording);
            }
            textViewNoRecordings.setVisibility(View.GONE);
            recyclerViewRecordings.setVisibility(View.VISIBLE);
            setAdaptertoRecyclerView();
        }else{
            textViewNoRecordings.setVisibility(View.VISIBLE);
            recyclerViewRecordings.setVisibility(View.GONE);
        }
    }
    private void setAdaptertoRecyclerView() {
        recordingAdapter = new RecordingAdapter(this,recordingArraylist);
        recyclerViewRecordings.setAdapter(recordingAdapter);
    }
    private void initViews() {
        /** setting up the toolbar  **/
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("Recording List");
        toolbar.setTitleTextColor(getResources().getColor(android.R.color.black));
        setSupportActionBar(toolbar);
        /** enabling back button ***/
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        /** setting up recyclerView **/
        recyclerViewRecordings = (RecyclerView) findViewById(R.id.recyclerViewRecordings);
        recyclerViewRecordings.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL, false));
        recyclerViewRecordings.setHasFixedSize(true);
        textViewNoRecordings = (TextView) findViewById(R.id.textViewNoRecordings);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                this.finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

نکته باید اکتیویتی ها تعریف شده را در AndroidManifest تنظیم کنید برای اینکار وارد فایل AndroidManifest.xml شده و در تگ applicaition خط های زیر را اضافه کنید.

  <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".RecordingListActivity"
            />

دسترسی های زیر  فراموش نشود !
فایل AndrioidManifest.xml را باز کرده و سه دسترسی زیر را بالای تگ application قرار دهید.

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

 
 
این آموزش هم به پایان رسید.
 
موفق و پیروز باشید.

مطالعه بیشتر