آموزش ساخت ضبط صوت در برنامه نویسی اندروید
سلام دوستان امیدوارم حالتان خوب باشد در این سری از آموزش برنامه نویسی اندروید به آموزش ساخت ضبط صوت در برنامه نویسی اندروید می پردازیم در این آموزش از کلاس MediaRecorder برای ذخیره صدا استفاده می شود از امکانات آن می توان به استفاده از RunTime Permission نمایش لیست صداهای ذخیره شده امکان Pause و Play اشاره کرددر ادامه می توانید پیش نمایش آن را مشاهده کنید.
در این آموزش از RecyclerView استفاده می شود پس لازم است آن را همانند زبر در به پروژه اضافه کنید
وارد فایل build.gradle شده و در بخش dependencies خط زیر را اضافه کنید.
1 | compile 'com.android.support:recyclerview-v7:26.0.0-alpha1' |
پروژه را Sync کنید.
یک فایل در ادامه برایتان قرار داده شده است آن را دانلود کنید و در پوشه drawable قرار دهید.
لینک دانلود عکس ها
یک پوشه در بخش res به نام menu ایجاد کرده و یک لایه به نام list_menu.xml در آن ساخته و کد زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 | <?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 را باز کرد و خط های زیر را به آن اضافه کنید.
1 2 3 4 | <resources> <string name="app_name">VoiceRecorderApp</string> <string name="_00_00">00:00</string> </resources> |
در همان مسیر فایل Styles.xml را باز کرده و کد زیر را جایگزین کد قبلی کنید.
1 2 3 4 5 6 7 8 9 | <!-- 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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | <?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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <?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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | 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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | 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 ایجاد کرده و کدهای زیر را در آن قرار دهید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 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 خط های زیر را اضافه کنید.
1 2 3 4 5 6 7 8 | <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 قرار دهید.
1 2 3 | <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" /> |
این آموزش هم به پایان رسید.
موفق و پیروز باشید.
سلام، آیا راهی برای ضبط خود صدای دستگاه وجود دارد؟ منظورم صدای خروجی گوشی هستش..
سلام. کاش پروژه را در گیت هاب هم میذاشتید
سلام وقت بخیر
کد Delete و Edit Name برای آیتم های Recycler View در این پروژه چیه هست؟