1.主界面
public class MainActivityextends AppCompatActivity {
private final int SDK_PERMISSION_REQUEST =127;
private ChronometermChronometer;
private boolean mStartRecording =true;
private int mRecordPromptCount =0;
private ImageViewimg_mic_phone;
private TextViewtvImageTip;
private FileViewerAdaptermFileViewerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_main);
getPersimmions();
initView();
initAdapater();
}
private void initAdapater() {
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager llm =new LinearLayoutManager(MainActivity.this);
llm.setOrientation(RecyclerView.VERTICAL);
//newest to oldest order (database stores from oldest to newest)
llm.setReverseLayout(true);
llm.setStackFromEnd(true);
mRecyclerView.setLayoutManager(llm);
mFileViewerAdapter =new FileViewerAdapter(MainActivity.this, llm);
mRecyclerView.setAdapter(mFileViewerAdapter);
}
private void initView() {
mChronometer = (Chronometer) findViewById(R.id.chronometer);
img_mic_phone = (ImageView) findViewById(R.id.img_mic_phone);
tvImageTip = (TextView) findViewById(R.id.tvImageTip);
img_mic_phone.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startCount(mStartRecording);
//点了一次 进入录音,再点则取消
mStartRecording = !mStartRecording;
}
});
}
private void startCount(boolean start) {
Intent intent =new Intent(MainActivity.this, RecordingService.class);
//重0开始,重新计时
if(start){
tvImageTip.setText("正在录音,点击关闭");
img_mic_phone.setBackgroundResource(R.drawable.stop);
// img_mic_phone.setImageResource(R.drawable.stop);
showMesg("开始录音");
//getExternalFilesDir
// File folder = new File(Environment.getExternalStorageDirectory() + "/SoundRecorder");
File folder =new File(getExternalFilesDir(null) +"/SoundRecorder");
if (!folder.exists()) {
//folder /SoundRecorder doesn't exist, create the folder
folder.mkdir();
}
mChronometer.setBase(SystemClock.elapsedRealtime());
mChronometer.start();
mChronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
if (mRecordPromptCount ==0) {
Log.i("checkCount",0+"");
}else if (mRecordPromptCount ==1) {
Log.i("checkCount",1+"");
}else if (mRecordPromptCount ==2) {
Log.i("checkCount",2+"");
mRecordPromptCount = -1;
}
mRecordPromptCount++;
}
});
//开启录音服务
startService(intent);
}else {
tvImageTip.setText("点击开始录音");
// img_mic_phone.setImageResource(R.drawable.mic_phone);
img_mic_phone.setBackgroundResource(R.drawable.mic_phone);
//终止录音
mChronometer.stop();
mChronometer.setBase(SystemClock.elapsedRealtime());
//关闭录音服务
stopService(intent);
}
}
//申请权限
@TargetApi(23)
private void getPersimmions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList permissions =new ArrayList();
/***
* 定位权限为必须权限,用户如果禁止,则每次进入都会申请
*/
// 定位精确位置
if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (getApplicationContext().checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.RECORD_AUDIO);
}
if (permissions.size() >0) {
requestPermissions(permissions.toArray(new String[permissions.size()]),SDK_PERMISSION_REQUEST);
}
}
}
@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode,@NonNull String[] permissions,@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
public void showMesg(String msg){
Toast.makeText(MainActivity.this.getApplicationContext(),msg,Toast.LENGTH_SHORT).show();
}
}
2.数据库openhelper
public class DBHelperextends SQLiteOpenHelper {
private ContextmContext;
private static final StringLOG_TAG ="DBHelper";
private static OnDatabaseChangedListenermOnDatabaseChangedListener;
public static final StringDATABASE_NAME ="saved_recordings.db";
private static final int DATABASE_VERSION =1;
public static abstract class DBHelperItemimplements BaseColumns {
public static final StringTABLE_NAME ="saved_recordings";
public static final StringCOLUMN_NAME_RECORDING_NAME ="recording_name";
public static final StringCOLUMN_NAME_RECORDING_FILE_PATH ="file_path";
public static final StringCOLUMN_NAME_RECORDING_LENGTH ="length";
public static final StringCOLUMN_NAME_TIME_ADDED ="time_added";
}
private static final StringTEXT_TYPE =" TEXT";
private static final StringCOMMA_SEP =",";
private static final StringSQL_CREATE_ENTRIES =
"CREATE TABLE " + DBHelperItem.TABLE_NAME +" (" +
DBHelperItem._ID +" INTEGER PRIMARY KEY" +COMMA_SEP +
DBHelperItem.COLUMN_NAME_RECORDING_NAME +TEXT_TYPE +COMMA_SEP +
DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH +TEXT_TYPE +COMMA_SEP +
DBHelperItem.COLUMN_NAME_RECORDING_LENGTH +" INTEGER " +COMMA_SEP +
DBHelperItem.COLUMN_NAME_TIME_ADDED +" INTEGER " +")";
@SuppressWarnings("unused")
private static final StringSQL_DELETE_ENTRIES ="DROP TABLE IF EXISTS " + DBHelperItem.TABLE_NAME;
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}
@Override
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion) {
}
public DBHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
mContext = context;
}
public static void setOnDatabaseChangedListener(OnDatabaseChangedListener listener) {
mOnDatabaseChangedListener = listener;
}
public RecordingItem getItemAt(int position) {
SQLiteDatabase db = getReadableDatabase();
String[] projection = {
DBHelperItem._ID,
DBHelperItem.COLUMN_NAME_RECORDING_NAME,
DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH,
DBHelperItem.COLUMN_NAME_RECORDING_LENGTH,
DBHelperItem.COLUMN_NAME_TIME_ADDED
};
Cursor c = db.query(DBHelperItem.TABLE_NAME, projection,null,null,null,null,null);
if (c.moveToPosition(position)) {
RecordingItem item =new RecordingItem();
item.setId(c.getInt(c.getColumnIndex(DBHelperItem._ID)));
item.setName(c.getString(c.getColumnIndex(DBHelperItem.COLUMN_NAME_RECORDING_NAME)));
item.setFilePath(c.getString(c.getColumnIndex(DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH)));
item.setLength(c.getInt(c.getColumnIndex(DBHelperItem.COLUMN_NAME_RECORDING_LENGTH)));
item.setTime(c.getLong(c.getColumnIndex(DBHelperItem.COLUMN_NAME_TIME_ADDED)));
c.close();
return item;
}
return null;
}
public void removeItemWithId(int id) {
SQLiteDatabase db = getWritableDatabase();
String[] whereArgs = { String.valueOf(id) };
db.delete(DBHelperItem.TABLE_NAME,"_ID=?", whereArgs);
}
public int getCount() {
SQLiteDatabase db = getReadableDatabase();
String[] projection = { DBHelperItem._ID };
Cursor c = db.query(DBHelperItem.TABLE_NAME, projection,null,null,null,null,null);
int count = c.getCount();
c.close();
return count;
}
public Context getContext() {
return mContext;
}
public class RecordingComparatorimplements Comparator {
public int compare(RecordingItem item1, RecordingItem item2) {
Long o1 = item1.getTime();
Long o2 = item2.getTime();
return o2.compareTo(o1);
}
}
public long addRecording(String recordingName, String filePath,long length) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv =new ContentValues();
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_NAME, recordingName);
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH, filePath);
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_LENGTH, length);
cv.put(DBHelperItem.COLUMN_NAME_TIME_ADDED, System.currentTimeMillis());
long rowId = db.insert(DBHelperItem.TABLE_NAME,null, cv);
if (mOnDatabaseChangedListener !=null) {
mOnDatabaseChangedListener.onNewDatabaseEntryAdded();
}
return rowId;
}
public void renameItem(RecordingItem item, String recordingName, String filePath) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv =new ContentValues();
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_NAME, recordingName);
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH, filePath);
db.update(DBHelperItem.TABLE_NAME, cv,
DBHelperItem._ID +"=" + item.getId(),null);
if (mOnDatabaseChangedListener !=null) {
mOnDatabaseChangedListener.onDatabaseEntryRenamed();
}
}
public long restoreRecording(RecordingItem item) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv =new ContentValues();
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_NAME, item.getName());
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_FILE_PATH, item.getFilePath());
cv.put(DBHelperItem.COLUMN_NAME_RECORDING_LENGTH, item.getLength());
cv.put(DBHelperItem.COLUMN_NAME_TIME_ADDED, item.getTime());
cv.put(DBHelperItem._ID, item.getId());
long rowId = db.insert(DBHelperItem.TABLE_NAME,null, cv);
if (mOnDatabaseChangedListener !=null) {
//mOnDatabaseChangedListener.onNewDatabaseEntryAdded();
}
return rowId;
}
}
3.Sp工具类
public class MySharedPreferences {
private static StringPREF_HIGH_QUALITY ="pref_high_quality";
public static void setPrefHighQuality(Context context,boolean isEnabled) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(PREF_HIGH_QUALITY, isEnabled);
editor.apply();
}
public static boolean getPrefHighQuality(Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return preferences.getBoolean(PREF_HIGH_QUALITY,false);
}
}
4.录音的服务
public class RecordingServiceextends Service {
private static final StringLOG_TAG ="RecordingService";
private StringmFileName =null;
private StringmFilePath =null;
private MediaRecordermRecorder =null;
private DBHelpermDatabase;
private long mStartingTimeMillis =0;
private long mElapsedMillis =0;
private int mElapsedSeconds =0;
private OnTimerChangedListeneronTimerChangedListener =null;
private static final SimpleDateFormatmTimerFormat =new SimpleDateFormat("mm:ss", Locale.getDefault());
private TimermTimer =null;
private TimerTaskmIncrementTimerTask =null;
@Override
public IBinder onBind(Intent intent) {
return null;
}
public interface OnTimerChangedListener {
void onTimerChanged(int seconds);
}
@Override
public void onCreate() {
super.onCreate();
mDatabase =new DBHelper(getApplicationContext());
}
@Override
public int onStartCommand(Intent intent,int flags,int startId) {
startRecording();
return START_STICKY;
}
@Override
public void onDestroy() {
if (mRecorder !=null) {
stopRecording();
}
super.onDestroy();
}
public void startRecording() {
setFileNameAndPath();
mRecorder =new MediaRecorder();
//音频来源 麦克风
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
//设置在录制过程中产生的输出文件的格式
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//设置音频完成后的 产出路径
mRecorder.setOutputFile(mFilePath);
//音频格式
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
//声道
mRecorder.setAudioChannels(1);
if (MySharedPreferences.getPrefHighQuality(this)) {
//设置录制的音频采样率
mRecorder.setAudioSamplingRate(44100);
//设置录制的音频编码比特率
mRecorder.setAudioEncodingBitRate(192000);
}
try {
mRecorder.prepare();
mRecorder.start();
mStartingTimeMillis = System.currentTimeMillis();
//startTimer();
//startForeground(1, createNotification());
}catch (IOException e) {
Log.e(LOG_TAG,"prepare() failed");
}
}
public void setFileNameAndPath(){
int count =0;
File f;
do{
count++;
//生成该音频的名字,根据数据库里的音频数量+1
mFileName = getString(R.string.default_file_name)
+"_" + (mDatabase.getCount() + count) +".mp4";
// mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
mFilePath = getExternalFilesDir(null) .getAbsolutePath();
mFilePath +="/SoundRecorder/" +mFileName;
f =new File(mFilePath);
}while (f.exists() && !f.isDirectory());
}
public void stopRecording() {
//关闭音频
mRecorder.stop();
//时长
mElapsedMillis = (System.currentTimeMillis() -mStartingTimeMillis);
mRecorder.release();
Toast.makeText(this,
"录制完成 存储本地地址为: " +mFilePath, Toast.LENGTH_LONG).show();
Log.i("Result",": "+mFilePath);
//remove notification
if (mIncrementTimerTask !=null) {
mIncrementTimerTask.cancel();
mIncrementTimerTask =null;
}
mRecorder =null;
try {
mDatabase.addRecording(mFileName,mFilePath,mElapsedMillis);
}catch (Exception e){
Log.e(LOG_TAG,"exception", e);
}
}
// private void startTimer() {
// mTimer = new Timer();
// mIncrementTimerTask = new TimerTask() {
// @Override
// public void run() {
// mElapsedSeconds++;
// if (onTimerChangedListener != null)
// onTimerChangedListener.onTimerChanged(mElapsedSeconds);
// NotificationManager mgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mgr.notify(1, createNotification());
// }
// };
// mTimer.scheduleAtFixedRate(mIncrementTimerTask, 1000, 1000);
// }
//TODO:
// private Notification createNotification() {
// NotificationCompat.Builder mBuilder =
// new NotificationCompat.Builder(getApplicationContext())
// .setSmallIcon(R.drawable.ic_mic_white_36dp)
// .setContentTitle(getString(R.string.notification_recording))
// .setContentText(mTimerFormat.format(mElapsedSeconds * 1000))
// .setOngoing(true);
//
// mBuilder.setContentIntent(PendingIntent.getActivities(getApplicationContext(), 0,
// new Intent[]{new Intent(getApplicationContext(), MainActivity.class)}, 0));
//
// return mBuilder.build();
// }
}
5.录音存储的bean类
public class RecordingItemimplements Parcelable {
private StringmName;// file name
private StringmFilePath;//file path
private int mId;//id in database
private int mLength;// length of recording in seconds
private long mTime;// date/time of the recording
public RecordingItem()
{
}
public RecordingItem(Parcel in) {
mName = in.readString();
mFilePath = in.readString();
mId = in.readInt();
mLength = in.readInt();
mTime = in.readLong();
}
public String getFilePath() {
return mFilePath;
}
public void setFilePath(String filePath) {
mFilePath = filePath;
}
public int getLength() {
return mLength;
}
public void setLength(int length) {
mLength = length;
}
public int getId() {
return mId;
}
public void setId(int id) {
mId = id;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public long getTime() {
return mTime;
}
public void setTime(long time) {
mTime = time;
}
public static final Parcelable.CreatorCREATOR =new Parcelable.Creator() {
public RecordingItem createFromParcel(Parcel in) {
return new RecordingItem(in);
}
public RecordingItem[] newArray(int size) {
return new RecordingItem[size];
}
};
@Override
public void writeToParcel(Parcel dest,int flags) {
dest.writeInt(mId);
dest.writeInt(mLength);
dest.writeLong(mTime);
dest.writeString(mFilePath);
dest.writeString(mName);
}
@Override
public int describeContents() {
return 0;
}
}
6.监听接口
public interface OnDatabaseChangedListener {
void onNewDatabaseEntryAdded();
void onDatabaseEntryRenamed();
}
7.播放的fragment
public class PlaybackFragmentextends DialogFragment {
private static final StringLOG_TAG ="PlaybackFragment";
private static final StringARG_ITEM ="recording_item";
private RecordingItemitem;
private HandlermHandler =new Handler();
private MediaPlayermMediaPlayer =null;
private SeekBarmSeekBar =null;
private ImageViewmPlayButton =null;
private TextViewmCurrentProgressTextView =null;
private TextViewmFileNameTextView =null;
private TextViewmFileLengthTextView =null;
//stores whether or not the mediaplayer is currently playing audio
private boolean isPlaying =false;
//stores minutes and seconds of the length of the file.
long minutes =0;
long seconds =0;
public PlaybackFragment newInstance(RecordingItem item) {
PlaybackFragment f =new PlaybackFragment();
Bundle b =new Bundle();
b.putParcelable(ARG_ITEM, item);
f.setArguments(b);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
item = getArguments().getParcelable(ARG_ITEM);
long itemDuration =item.getLength();
minutes = TimeUnit.MILLISECONDS.toMinutes(itemDuration);
seconds = TimeUnit.MILLISECONDS.toSeconds(itemDuration)
- TimeUnit.MINUTES.toSeconds(minutes);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog =super.onCreateDialog(savedInstanceState);
AlertDialog.Builder builder =new AlertDialog.Builder(getActivity());
View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_media_playback,null);
mFileNameTextView = (TextView) view.findViewById(R.id.file_name_text_view);
mFileLengthTextView = (TextView) view.findViewById(R.id.file_length_text_view);
mCurrentProgressTextView = (TextView) view.findViewById(R.id.current_progress_text_view);
mSeekBar = (SeekBar) view.findViewById(R.id.seekbar);
ColorFilter filter =new LightingColorFilter
(getResources().getColor(R.color.primary), getResources().getColor(R.color.primary));
mSeekBar.getProgressDrawable().setColorFilter(filter);
mSeekBar.getThumb().setColorFilter(filter);
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar,int progress,boolean fromUser) {
if(mMediaPlayer !=null && fromUser) {
mMediaPlayer.seekTo(progress);
mHandler.removeCallbacks(mRunnable);
long minutes = TimeUnit.MILLISECONDS.toMinutes(mMediaPlayer.getCurrentPosition());
long seconds = TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getCurrentPosition())
- TimeUnit.MINUTES.toSeconds(minutes);
mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes,seconds));
updateSeekBar();
}else if (mMediaPlayer ==null && fromUser) {
prepareMediaPlayerFromPoint(progress);
updateSeekBar();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if(mMediaPlayer !=null) {
// remove message Handler from updating progress bar
mHandler.removeCallbacks(mRunnable);
}
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mMediaPlayer !=null) {
mHandler.removeCallbacks(mRunnable);
mMediaPlayer.seekTo(seekBar.getProgress());
long minutes = TimeUnit.MILLISECONDS.toMinutes(mMediaPlayer.getCurrentPosition());
long seconds = TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getCurrentPosition())
- TimeUnit.MINUTES.toSeconds(minutes);
mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes,seconds));
updateSeekBar();
}
}
});
mPlayButton = (ImageView) view.findViewById(R.id.fab_play);
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onPlay(isPlaying);
isPlaying = !isPlaying;
}
});
mFileNameTextView.setText(item.getName());
mFileLengthTextView.setText(String.format("%02d:%02d",minutes,seconds));
builder.setView(view);
// request a window without the title
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return builder.create();
}
@Override
public void onStart() {
super.onStart();
//set transparent background
Window window = getDialog().getWindow();
window.setBackgroundDrawableResource(android.R.color.transparent);
//disable buttons from dialog
AlertDialog alertDialog = (AlertDialog) getDialog();
alertDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
alertDialog.getButton(Dialog.BUTTON_NEGATIVE).setEnabled(false);
alertDialog.getButton(Dialog.BUTTON_NEUTRAL).setEnabled(false);
}
@Override
public void onPause() {
super.onPause();
if (mMediaPlayer !=null) {
stopPlaying();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mMediaPlayer !=null) {
stopPlaying();
}
}
// Play start/stop
private void onPlay(boolean isPlaying){
if (!isPlaying) {
//currently MediaPlayer is not playing audio
if(mMediaPlayer ==null) {
startPlaying();//start from beginning
}else {
resumePlaying();//resume the currently paused MediaPlayer
}
}else {
//pause the MediaPlayer
pausePlaying();
}
}
private void startPlaying() {
mPlayButton.setBackgroundResource(R.drawable.ic_media_pause);
mMediaPlayer =new MediaPlayer();
try {
mMediaPlayer.setDataSource(item.getFilePath());
mMediaPlayer.prepare();
mSeekBar.setMax(mMediaPlayer.getDuration());
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mMediaPlayer.start();
}
});
}catch (IOException e) {
Log.e(LOG_TAG,"prepare() failed");
}
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopPlaying();
}
});
updateSeekBar();
//keep screen on while playing audio
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void prepareMediaPlayerFromPoint(int progress) {
//set mediaPlayer to start from middle of the audio file
mMediaPlayer =new MediaPlayer();
try {
mMediaPlayer.setDataSource(item.getFilePath());
mMediaPlayer.prepare();
mSeekBar.setMax(mMediaPlayer.getDuration());
mMediaPlayer.seekTo(progress);
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopPlaying();
}
});
}catch (IOException e) {
Log.e(LOG_TAG,"prepare() failed");
}
//keep screen on while playing audio
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void pausePlaying() {
mPlayButton.setBackgroundResource(R.drawable.ic_media_play);
mHandler.removeCallbacks(mRunnable);
mMediaPlayer.pause();
}
private void resumePlaying() {
mPlayButton.setBackgroundResource(R.drawable.ic_media_pause);
mHandler.removeCallbacks(mRunnable);
mMediaPlayer.start();
updateSeekBar();
}
private void stopPlaying() {
mPlayButton.setBackgroundResource(R.drawable.ic_media_play);
mHandler.removeCallbacks(mRunnable);
mMediaPlayer.stop();
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer =null;
mSeekBar.setProgress(mSeekBar.getMax());
isPlaying = !isPlaying;
mCurrentProgressTextView.setText(mFileLengthTextView.getText());
mSeekBar.setProgress(mSeekBar.getMax());
//allow the screen to turn off again once audio is finished playing
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
//updating mSeekBar
private RunnablemRunnable =new Runnable() {
@Override
public void run() {
if(mMediaPlayer !=null){
int mCurrentPosition =mMediaPlayer.getCurrentPosition();
mSeekBar.setProgress(mCurrentPosition);
long minutes = TimeUnit.MILLISECONDS.toMinutes(mCurrentPosition);
long seconds = TimeUnit.MILLISECONDS.toSeconds(mCurrentPosition)
- TimeUnit.MINUTES.toSeconds(minutes);
mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes, seconds));
updateSeekBar();
}
}
};
private void updateSeekBar() {
mHandler.postDelayed(mRunnable,1000);
}
}
8.主界面音频列表的adpater
public class FileViewerAdapterextends RecyclerView.Adapter
implements OnDatabaseChangedListener {
private static final StringLOG_TAG ="FileViewerAdapter";
private DBHelpermDatabase;
RecordingItemitem;
ContextmContext;
LinearLayoutManagerllm;
public FileViewerAdapter(Context context, LinearLayoutManager linearLayoutManager) {
super();
mContext = context;
mDatabase =new DBHelper(mContext);
mDatabase.setOnDatabaseChangedListener(this);
llm = linearLayoutManager;
}
@Override
public void onBindViewHolder(final RecordingsViewHolder holder,int position) {
item = getItem(position);
long itemDuration =item.getLength();
long minutes = TimeUnit.MILLISECONDS.toMinutes(itemDuration);
long seconds = TimeUnit.MILLISECONDS.toSeconds(itemDuration)
- TimeUnit.MINUTES.toSeconds(minutes);
holder.vName.setText(item.getName());
holder.vLength.setText(String.format("%02d:%02d", minutes, seconds));
holder.vDateAdded.setText(
DateUtils.formatDateTime(
mContext,
item.getTime(),
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NUMERIC_DATE | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR
)
);
// define an on click listener to open PlaybackFragment
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
PlaybackFragment playbackFragment =
new PlaybackFragment().newInstance(getItem(holder.getPosition()));
FragmentTransaction transaction = ((FragmentActivity)mContext)
.getSupportFragmentManager()
.beginTransaction();
playbackFragment.show(transaction,"dialog_playback");
}catch (Exception e) {
Log.e(LOG_TAG,"exception", e);
}
}
});
holder.cardView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ArrayList entrys =new ArrayList();
// entrys.add(mContext.getString(R.string.dialog_file_share));
// entrys.add(mContext.getString(R.string.dialog_file_rename));
entrys.add(mContext.getString(R.string.dialog_file_delete));
final CharSequence[] items = entrys.toArray(new CharSequence[entrys.size()]);
// File delete confirm
AlertDialog.Builder builder =new AlertDialog.Builder(mContext);
builder.setTitle("操作");
builder.setItems(items,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int item) {
// if (item == 0) {
// shareFileDialog(holder.getPosition());
// } if (item == 1) {
//// renameFileDialog(holder.getPosition());
// deleteFileDialog(holder.getPosition());
// }
deleteFileDialog(holder.getPosition());
// else if (item == 2) {
// deleteFileDialog(holder.getPosition());
// }
}
});
builder.setCancelable(true);
builder.setNegativeButton(mContext.getString(R.string.dialog_action_cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
return false;
}
});
}
@Override
public RecordingsViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View itemView = LayoutInflater.
from(parent.getContext()).
inflate(R.layout.card_view, parent,false);
mContext = parent.getContext();
return new RecordingsViewHolder(itemView);
}
public static class RecordingsViewHolderextends RecyclerView.ViewHolder {
protected TextViewvName;
protected TextViewvLength;
protected TextViewvDateAdded;
protected ViewcardView;
public RecordingsViewHolder(View v) {
super(v);
vName = (TextView) v.findViewById(R.id.file_name_text);
vLength = (TextView) v.findViewById(R.id.file_length_text);
vDateAdded = (TextView) v.findViewById(R.id.file_date_added_text);
cardView = v.findViewById(R.id.card_view);
}
}
@Override
public int getItemCount() {
return mDatabase.getCount();
}
public RecordingItem getItem(int position) {
return mDatabase.getItemAt(position);
}
@Override
public void onNewDatabaseEntryAdded() {
//item added to top of the list
notifyItemInserted(getItemCount() -1);
llm.scrollToPosition(getItemCount() -1);
}
@Override
//TODO
public void onDatabaseEntryRenamed() {
}
public void remove(int position) {
//remove item from database, recyclerview and storage
//delete file from storage
File file =new File(getItem(position).getFilePath());
file.delete();
Toast.makeText(
mContext,
String.format(
mContext.getString(R.string.toast_file_delete),
getItem(position).getName()
),
Toast.LENGTH_SHORT
).show();
mDatabase.removeItemWithId(getItem(position).getId());
notifyItemRemoved(position);
}
//TODO
public void removeOutOfApp(String filePath) {
//user deletes a saved recording out of the application through another application
}
public void rename(int position, String name) {
//rename a file
String mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
mFilePath +="/SoundRecorder/" + name;
File f =new File(mFilePath);
if (f.exists() && !f.isDirectory()) {
//file name is not unique, cannot rename file.
Toast.makeText(mContext,
String.format(mContext.getString(R.string.toast_file_exists), name),
Toast.LENGTH_SHORT).show();
}else {
//file name is unique, rename file
File oldFilePath =new File(getItem(position).getFilePath());
oldFilePath.renameTo(f);
mDatabase.renameItem(getItem(position), name, mFilePath);
notifyItemChanged(position);
}
}
public void shareFileDialog(int position) {
Intent shareIntent =new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getItem(position).getFilePath())));
shareIntent.setType("audio/mp4");
mContext.startActivity(Intent.createChooser(shareIntent,mContext.getText(R.string.send_to)));
}
public void deleteFileDialog (final int position) {
// File delete confirm
AlertDialog.Builder confirmDelete =new AlertDialog.Builder(mContext);
confirmDelete.setTitle(mContext.getString(R.string.dialog_title_delete));
confirmDelete.setMessage(mContext.getString(R.string.dialog_text_delete));
confirmDelete.setCancelable(true);
confirmDelete.setPositiveButton(mContext.getString(R.string.dialog_action_yes),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
try {
//remove item from database, recyclerview, and storage
remove(position);
}catch (Exception e) {
Log.e(LOG_TAG,"exception", e);
}
dialog.cancel();
}
});
confirmDelete.setNegativeButton(mContext.getString(R.string.dialog_action_no),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
AlertDialog alert = confirmDelete.create();
alert.show();
}
// public void renameFileDialog (final int position) {
// // File rename dialog
// AlertDialog.Builder renameFileBuilder = new AlertDialog.Builder(mContext);
//
// LayoutInflater inflater = LayoutInflater.from(mContext);
// View view = inflater.inflate(R.layout.dialog_rename_file, null);
//
// final EditText input = (EditText) view.findViewById(R.id.new_name);
//
// renameFileBuilder.setTitle(mContext.getString(R.string.dialog_title_rename));
// renameFileBuilder.setCancelable(true);
// renameFileBuilder.setPositiveButton(mContext.getString(R.string.dialog_action_ok),
// new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int id) {
// try {
// String value = input.getText().toString().trim() + ".mp4";
// rename(position, value);
//
// } catch (Exception e) {
// Log.e(LOG_TAG, "exception", e);
// }
//
// dialog.cancel();
// }
// });
// renameFileBuilder.setNegativeButton(mContext.getString(R.string.dialog_action_cancel),
// new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int id) {
// dialog.cancel();
// }
// });
//
// renameFileBuilder.setView(view);
// AlertDialog alert = renameFileBuilder.create();
// alert.show();
// }
}
main layout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/chronometer"
android:textSize="60sp"
android:fontFamily="sans-serif-light"
android:layout_centerHorizontal="true"
android:layout_margin="50dp"
/>
android:id="@+id/tvImageTip"
android:text="点击开始录音"
android:textSize="17sp"
android:layout_below="@+id/chronometer"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:id="@+id/img_mic_phone"
android:layout_marginTop="20dp"
android:layout_below="@+id/tvImageTip"
android:layout_centerHorizontal="true"
android:background="@drawable/mic_phone"
android:layout_width="40dp"
android:layout_height="40dp" />
android:id="@+id/recyclerView"
android:layout_below="@+id/img_mic_phone"
android:layout_width="match_parent"
android:layout_height="match_parent">
fragment_dialog
<RelativeLayout
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/mediaplayer_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transitionName="open_mediaplayer"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:orientation="vertical">
<TextView
android:id="@+id/file_name_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="7dp"
android:layout_marginBottom="7dp"
android:text="file_name.mp4"
android:textSize="18sp"
android:fontFamily="sans-serif-condensed"/>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/current_progress_text_view"
android:text="00:00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<ImageView
android:id="@+id/fab_play"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:background="@drawable/ic_media_play"
android:layout_marginBottom="10dp"
android:layout_marginTop="10dp"
/>
<TextView
android:id="@+id/file_length_text_view"
android:text="00:00"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
card
<RelativeLayout
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="75dp"
android:layout_gravity="center"
android:layout_margin="5dp"
android:foreground="?android:attr/selectableItemBackground"
android:transitionName="open_mediaplayer"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/mic_phone"
android:layout_gravity="center_vertical"
android:layout_marginLeft="7dp"
android:layout_marginRight="7dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/file_name_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="file_name"
android:textSize="15sp"
android:fontFamily="sans-serif-condensed"
android:textStyle="bold"/>
<TextView
android:id="@+id/file_length_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00:00"
android:textSize="12sp"
android:fontFamily="sans-serif-condensed"
android:layout_marginTop="7dp"/>
<TextView
android:id="@+id/file_date_added_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="mmm dd yyyy - hh:mm a"
android:textSize="12sp"
android:fontFamily="sans-serif-condensed"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
网友评论