Needs
1.recording_item_layout.xml
2.activity_recording_list.xml
3.activity_record.xml
4.Recording.java
5.RecordingAdapter.java
6.RecordingListActivity.java
7.RecordActivity.java
Step 1:
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">
<ImageView
android:id="@+id/imageViewPlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/play_audio"
android:layout_gravity="center_vertical"
android:clickable="true"
android:layout_marginLeft="10sp"
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"
>
<TextView
android:id="@+id/textViewRecordingname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="Voice 001"
android:layout_marginLeft="50sp"
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" />
</LinearLayout>
</RelativeLayout>
Step 2:
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"
tools:context=".RecordingListActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Recording List"/>
</android.support.v7.widget.Toolbar>
<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>
Step 3:
activity_record.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="wrap_content"
android:background="@android:color/white"
tools:context=".Test">
<LinearLayout
android:id="@+id/linearLayoutRecorder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:layout_margin="10sp"
android:orientation="vertical">
<TextView
android:id="@+id/text_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|right"
android:padding="20sp"
android:text="Close"
android:textColor="@color/colorPrimary"
android:textSize="17sp" />
<Chronometer
android:id="@+id/chronometerTimer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textColor="@color/colorPrimary"
android:textSize="60sp" />
<TextView
android:id="@+id/text_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="10sp"
android:textSize="15sp" />
<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="invisible">
<LinearLayout
android:id="@+id/layout_play_pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageViewPlay"
android:layout_width="20sp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/play_audio" />
<ImageView
android:id="@+id/imageViewPause"
android:layout_width="20sp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:visibility="gone"
android:src="@mipmap/stop_audio" />
</LinearLayout>
<SeekBar
android:id="@+id/seekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageViewRecord"
android:layout_width="70sp"
android:layout_height="match_parent"
android:src="@mipmap/microphone" />
<ImageView
android:id="@+id/imageViewStop"
android:layout_width="70sp"
android:layout_height="match_parent"
android:src="@mipmap/muted"
android:visibility="gone" />
</LinearLayout>
<Button
android:id="@+id/button_submit"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="40dp"
android:layout_marginTop="30sp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40sp"
android:background="@drawable/layout_shape1"
android:text="@string/submit"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
android:textColor="@android:color/white" />
</LinearLayout>
</RelativeLayout>
Step 4:
Recording.java
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;
}
}
Step 5:
RecordingAdapter.java
public class RecordingAdapter extends RecyclerView.Adapter<RecordingAdapter.ViewHolder>{
private ArrayList<Recording> recordingArrayList;
private Context context;
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);
}
@Override
public int getItemCount() {
return recordingArrayList.size();
}
private void setUpData(ViewHolder holder, int position) {
Recording recording = recordingArrayList.get(position);
holder.textViewName.setText(recording.getFileName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (recording.isPlaying()) {
holder.imageViewPlay.setImageResource(R.mipmap.play_audio);
TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
holder.seekBar.setVisibility(View.VISIBLE);
holder.seekUpdation(holder);
} else {
holder.imageViewPlay.setImageResource(R.mipmap.play_audio);
TransitionManager.beginDelayedTransition((ViewGroup) holder.itemView);
holder.seekBar.setVisibility(View.GONE);
}
}
holder.manageSeekBar(holder);
}
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 {
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);
}
});
}
}
}
Step 6:
RecordingListActivity.java
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);
initViews();
fetchRecordings();
}
private void initViews() {
recordingArraylist = new ArrayList<Recording>();
/** 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);
}
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);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Step 7:
RecordActivity.java
public class RecordActivity extends AppCompatActivity implements View.OnClickListener { private int RECORD_AUDIO_REQUEST_CODE =123 ; private Toolbar toolbar; TextView tx_list; 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 boolean isPlaying = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_record); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { getPermissionToRecordAudio(); } //initializingViews initViews(); /* tx_list.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(Test.this, RecordingListActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } });*/ } private void initViews() { //tx_list=(TextView)findViewById(R.id.text_list); 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(new View.OnClickListener() { @Override public void onClick(View v) { } }); imageViewStop.setOnClickListener(this); imageViewPlay.setOnClickListener(this); } @RequiresApi(api = Build.VERSION_CODES.M) public void getPermissionToRecordAudio() { // 1) Use the support library version ContextCompat.checkSelfPermission(...) to avoid // checking the build version since Context.checkSelfPermission(...) is only available // in Marshmallow // 2) Always check for permission (even if permission has already been granted) // since the user can revoke permissions at any time through Settings 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 ) { // The permission is NOT already granted. // Check if the user has been asked about this permission already and denied // it. If so, we want to give more explanation about why the permission is needed. // Fire off an async request to actually get the permission // This will show the standard permission request dialog UI requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, RECORD_AUDIO_REQUEST_CODE); } } // Callback with the request from calling requestPermissions(...) @RequiresApi(api = Build.VERSION_CODES.M) @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { // Make sure it's our original READ_CONTACTS request 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){ //Toast.makeText(this, "Record Audio permission granted", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(this, "You must give permissions to use this app. App is exiting.", Toast.LENGTH_SHORT).show(); finishAffinity(); } } } @RequiresApi(api = Build.VERSION_CODES.KITKAT) @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 prepareforRecording() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { TransitionManager.beginDelayedTransition(linearLayoutRecorder); imageViewRecord.setVisibility(View.GONE); imageViewStop.setVisibility(View.VISIBLE); linearLayoutPlay.setVisibility(View.GONE); } } private void startRecording() { //we use the MediaRecorder class to record mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); /**In the lines below, we create a directory named VoiceRecorderSimplifiedCoding/Audios in the phone storage * and the audios are being stored in the Audios folder **/ 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(); //starting the chronometer chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); } private void stopPlaying() { try{ mPlayer.release(); }catch (Exception e){ e.printStackTrace(); } mPlayer = null; //showing the play button imageViewPlay.setImageResource(R.mipmap.play_audio); chronometer.stop(); } @RequiresApi(api = Build.VERSION_CODES.KITKAT) private void prepareforStop() { TransitionManager.beginDelayedTransition(linearLayoutRecorder); imageViewRecord.setVisibility(View.VISIBLE); imageViewStop.setVisibility(View.GONE); linearLayoutPlay.setVisibility(View.VISIBLE); } private void stopRecording() { try{ mRecorder.stop(); mRecorder.release(); }catch (Exception e){ e.printStackTrace(); } mRecorder = null; //starting the chronometer chronometer.stop(); chronometer.setBase(SystemClock.elapsedRealtime()); //showing the play button Toast.makeText(this, "Recording saved successfully.", Toast.LENGTH_SHORT).show(); } private void startPlaying() { mPlayer = new MediaPlayer(); Log.d("instartPlaying",fileName); try { mPlayer.setDataSource(fileName); mPlayer.prepare(); mPlayer.start(); } catch (IOException e) { Log.e("LOG_TAG", "prepare() failed"); } //making the imageview pause button imageViewPlay.setImageResource(R.mipmap.play_audio); seekBar.setProgress(lastProgress); mPlayer.seekTo(lastProgress); seekBar.setMax(mPlayer.getDuration()); seekUpdation(); chronometer.start(); /** once the audio is complete, timer is stopped here**/ mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { imageViewPlay.setImageResource(R.mipmap.play_audio); isPlaying = false; chronometer.stop(); } }); /** moving the track as per the seekBar's position**/ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( mPlayer!=null && fromUser ){ //here the track's progress is being changed as per the progress bar mPlayer.seekTo(progress); //timer is being updated as per the progress of the seekbar 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); } @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: Intent intent = new Intent(this, RecordingListActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); return true; default: return super.onOptionsItemSelected(item); } } }
No comments:
Post a Comment