Android本地麦克风的存储播放

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>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容