zoukankan      html  css  js  c++  java
  • android录音功能的实现

    这个录音实现是我在Bus上看到并下载的,他那个源码不完整,再次把我整理完整的代码贴出,源码地址在这:http://download.csdn.net/detail/chaozhung/5618649

    Bus上的那个网址找不到了,见谅!!!

    下为核心代码:

    核心代码1..

    package com.lv.reco;
    
    import java.io.File;
    
    public class SoundRecorder extends Activity implements Button.OnClickListener,
            Recorder.OnStateChangedListener {
        private static final String TAG = "SoundRecorder";
    
        private static final String RECORDER_STATE_KEY = "recorder_state";
    
        private static final String SAMPLE_INTERRUPTED_KEY = "sample_interrupted";
    
        private static final String MAX_FILE_SIZE_KEY = "max_file_size";
    
        private static final String AUDIO_3GPP = "audio/3gpp";
    
        private static final String AUDIO_AMR = "audio/amr";
    
        private static final String AUDIO_ANY = "audio/*";
    
        private static final String ANY_ANY = "*/*";
    
        private static final String FILE_EXTENSION_AMR = ".amr";
    
        private static final String FILE_EXTENSION_3GPP = ".3gpp";
    
        public static final int BITRATE_AMR = 2 * 1024 * 8; // bits/sec
    
        public static final int BITRATE_3GPP = 20 * 1024 * 8; // bits/sec
    
        private static final int SEEK_BAR_MAX = 10000;
    
        private static final long WHEEL_SPEED_NORMAL = 1800;
    
        private static final long WHEEL_SPEED_FAST = 300;
    
        private static final long WHEEL_SPEED_SUPER_FAST = 100;
    
        private static final long SMALL_WHEEL_SPEED_NORMAL = 900;
    
        private static final long SMALL_WHEEL_SPEED_FAST = 200;
    
        private static final long SMALL_WHEEL_SPEED_SUPER_FAST = 200;
    
        private String mRequestedType = AUDIO_ANY;
    
        private boolean mCanRequestChanged = false;
    
        private Recorder mRecorder;
    
        private RecorderReceiver mReceiver;
    
        private boolean mSampleInterrupted = false;
    
        private boolean mShowFinishButton = false;
    
        private String mErrorUiMessage = null; // Some error messages are displayed
                                               // in the UI, not a dialog. This
                                               // happens when a recording
                                               // is interrupted for some reason.
    
        private long mMaxFileSize = -1; // can be specified in the intent
    
        private RemainingTimeCalculator mRemainingTimeCalculator;
    
        private String mTimerFormat;
    
        private SoundPool mSoundPool;
    
        private int mPlaySound;
    
        private int mPauseSound;
    
        private HashSet<String> mSavedRecord;
    
        private long mLastClickTime;
    
        private int mLastButtonId;
    
        private final Handler mHandler = new Handler();
    
        private Runnable mUpdateTimer = new Runnable() {
            public void run() {
                if (!mStopUiUpdate) {
                    updateTimerView();
                }
            }
        };
    
        private Runnable mUpdateSeekBar = new Runnable() {
            @Override
            public void run() {
                if (!mStopUiUpdate) {
                    updateSeekBar();
                }
            }
        };
    
        private Runnable mUpdateVUMetur = new Runnable() {
            @Override
            public void run() {
                if (!mStopUiUpdate) {
                    updateVUMeterView();
                }
            }
        };
    
        private ImageButton mNewButton;
    
        private ImageButton mFinishButton;
    
        private ImageButton mRecordButton;
    
        private ImageButton mStopButton;
    
        private ImageButton mPlayButton;
    
        private ImageButton mPauseButton;
    
        private ImageButton mDeleteButton;
    
        private WheelImageView mWheelLeft;
    
        private WheelImageView mWheelRight;
    
        private WheelImageView mSmallWheelLeft;
    
        private WheelImageView mSmallWheelRight;
    
        private RecordNameEditText mFileNameEditText;
    
        private LinearLayout mTimerLayout;
    
        private LinearLayout mVUMeterLayout;
    
        private LinearLayout mSeekBarLayout;
    
        private TextView mStartTime;
    
        private TextView mTotalTime;
    
        private SeekBar mPlaySeekBar;
    
        private BroadcastReceiver mSDCardMountEventReceiver = null;
    
        private int mPreviousVUMax;
    
        private boolean mStopUiUpdate;
    
        @Override
        public void onCreate(Bundle icycle) {
            super.onCreate(icycle);
            initInternalState(getIntent());
            setContentView(R.layout.main);
    
            mRecorder = new Recorder(this);
            mRecorder.setOnStateChangedListener(this);
            mReceiver = new RecorderReceiver();
            mRemainingTimeCalculator = new RemainingTimeCalculator();
            mSavedRecord = new HashSet<String>();
    
            initResourceRefs();
    
            setResult(RESULT_CANCELED);
            registerExternalStorageListener();
            if (icycle != null) {
                Bundle recorderState = icycle.getBundle(RECORDER_STATE_KEY);
                if (recorderState != null) {
                    mRecorder.restoreState(recorderState);
                    mSampleInterrupted = recorderState.getBoolean(SAMPLE_INTERRUPTED_KEY, false);
                    mMaxFileSize = recorderState.getLong(MAX_FILE_SIZE_KEY, -1);
                }
            }
    
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
    
            if (mShowFinishButton) {
                // reset state if it is a recording request
                mRecorder.reset();
                resetFileNameEditText();
            }
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
    
            boolean preShowFinishButton = mShowFinishButton;
            initInternalState(intent);
    
            if (mShowFinishButton || preShowFinishButton != mShowFinishButton) {
                // reset state if it is a recording request or state is changed
                mRecorder.reset();
                resetFileNameEditText();
            }
        }
    
        private void initInternalState(Intent i) {
            mRequestedType = AUDIO_ANY;
            mShowFinishButton = false;
            if (i != null) {
                String s = i.getType();
                if (AUDIO_AMR.equals(s) || AUDIO_3GPP.equals(s) || AUDIO_ANY.equals(s)
                        || ANY_ANY.equals(s)) {
                    mRequestedType = s;
                    mShowFinishButton = true;
                } else if (s != null) {
                    // we only support amr and 3gpp formats right now
                    setResult(RESULT_CANCELED);
                    finish();
                    return;
                }
    
                final String EXTRA_MAX_BYTES = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES;
                mMaxFileSize = i.getLongExtra(EXTRA_MAX_BYTES, -1);
            }
    
            if (AUDIO_ANY.equals(mRequestedType)) {
                mRequestedType = SoundRecorderPreferenceActivity.getRecordType(this);
            } else if (ANY_ANY.equals(mRequestedType)) {
                mRequestedType = AUDIO_3GPP;
            }
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
    
            setContentView(R.layout.main);
            initResourceRefs();
            updateUi(false);
        }
    
        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
    
            if (mRecorder.sampleLength() == 0)
                return;
    
            Bundle recorderState = new Bundle();
    
            if (mRecorder.state() != Recorder.RECORDING_STATE) {
                mRecorder.saveState(recorderState);
            }
            recorderState.putBoolean(SAMPLE_INTERRUPTED_KEY, mSampleInterrupted);
            recorderState.putLong(MAX_FILE_SIZE_KEY, mMaxFileSize);
    
            outState.putBundle(RECORDER_STATE_KEY, recorderState);
        }
    
        /*
         * Whenever the UI is re-created (due f.ex. to orientation change) we have
         * to reinitialize references to the views.
         */
        private void initResourceRefs() {
            mNewButton = (ImageButton) findViewById(R.id.newButton);
            mFinishButton = (ImageButton) findViewById(R.id.finishButton);
            mRecordButton = (ImageButton) findViewById(R.id.recordButton);
            mStopButton = (ImageButton) findViewById(R.id.stopButton);
            mPlayButton = (ImageButton) findViewById(R.id.playButton);
            mPauseButton = (ImageButton) findViewById(R.id.pauseButton);
            mDeleteButton = (ImageButton) findViewById(R.id.deleteButton);
            mNewButton.setOnClickListener(this);
            mFinishButton.setOnClickListener(this);
            mRecordButton.setOnClickListener(this);
            mStopButton.setOnClickListener(this);
            mPlayButton.setOnClickListener(this);
            mPauseButton.setOnClickListener(this);
            mDeleteButton.setOnClickListener(this);
    
            mWheelLeft = (WheelImageView) findViewById(R.id.wheel_left);
            mWheelRight = (WheelImageView) findViewById(R.id.wheel_right);
            mSmallWheelLeft = (WheelImageView) findViewById(R.id.wheel_small_left);
            mSmallWheelRight = (WheelImageView) findViewById(R.id.wheel_small_right);
            mFileNameEditText = (RecordNameEditText) findViewById(R.id.file_name);
    
            resetFileNameEditText();
            mFileNameEditText.setNameChangeListener(new RecordNameEditText.OnNameChangeListener() {
                @Override
                public void onNameChanged(String name) {
                    if (!TextUtils.isEmpty(name)) {
                        mRecorder.renameSampleFile(name);
                    }
                }
            });
    
            mTimerLayout = (LinearLayout) findViewById(R.id.time_calculator);
            mVUMeterLayout = (LinearLayout) findViewById(R.id.vumeter_layout);
            mSeekBarLayout = (LinearLayout) findViewById(R.id.play_seek_bar_layout);
            mStartTime = (TextView) findViewById(R.id.starttime);
            mTotalTime = (TextView) findViewById(R.id.totaltime);
            mPlaySeekBar = (SeekBar) findViewById(R.id.play_seek_bar);
            mPlaySeekBar.setMax(SEEK_BAR_MAX);
            mPlaySeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
    
            mTimerFormat = getResources().getString(R.string.timer_format);
    
            if (mShowFinishButton) {
                mNewButton.setVisibility(View.GONE);
                mFinishButton.setVisibility(View.VISIBLE);
                mNewButton = mFinishButton; // use mNewButon variable for left
                // button in the control panel
            }
    
            mSoundPool = new SoundPool(5, AudioManager.STREAM_SYSTEM, 5);
            mPlaySound = mSoundPool.load("/system/media/audio/ui/SoundRecorderPlay.ogg", 1);
            mPauseSound = mSoundPool.load("/system/media/audio/ui/SoundRecorderPause.ogg", 1);
    
            mLastClickTime = 0;
            mLastButtonId = 0;
        }
    
        private void resetFileNameEditText() {
            String extension = "";
            if (AUDIO_AMR.equals(mRequestedType)) {
                extension = FILE_EXTENSION_AMR;
            } else if (AUDIO_3GPP.equals(mRequestedType)) {
                extension = FILE_EXTENSION_3GPP;
            }
    
            // for audio which is used for mms, we can only use english file name
            // mShowFinishButon indicates whether this is an audio for mms
            mFileNameEditText.initFileName(mRecorder.getRecordDir(), extension, mShowFinishButton);
        }
    
        private void startRecordPlayingAnimation() {
            mWheelLeft.startAnimation(WHEEL_SPEED_NORMAL, true);
            mWheelRight.startAnimation(WHEEL_SPEED_NORMAL, true);
            mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_NORMAL, true);
            mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_NORMAL, true);
        }
    
        private void stopRecordPlayingAnimation() {
            stopAnimation();
            startRecordPlayingDoneAnimation();
        }
    
        private void startRecordPlayingDoneAnimation() {
            mWheelLeft.startAnimation(WHEEL_SPEED_SUPER_FAST, false, 4);
            mWheelRight.startAnimation(WHEEL_SPEED_SUPER_FAST, false, 4);
            mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_SUPER_FAST, false, 2);
            mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_SUPER_FAST, false, 2);
        }
    
        private void startForwardAnimation() {
            mWheelLeft.startAnimation(WHEEL_SPEED_FAST, true);
            mWheelRight.startAnimation(WHEEL_SPEED_FAST, true);
            mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_FAST, true);
            mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_FAST, true);
        }
    
        private void startBackwardAnimation() {
            mWheelLeft.startAnimation(WHEEL_SPEED_FAST, false);
            mWheelRight.startAnimation(WHEEL_SPEED_FAST, false);
            mSmallWheelLeft.startAnimation(SMALL_WHEEL_SPEED_FAST, false);
            mSmallWheelRight.startAnimation(SMALL_WHEEL_SPEED_FAST, false);
        }
    
        private void stopAnimation() {
            mWheelLeft.stopAnimation();
            mWheelRight.stopAnimation();
            mSmallWheelLeft.stopAnimation();
            mSmallWheelRight.stopAnimation();
        }
    
        /*
         * Make sure we're not recording music playing in the background, ask the
         * MediaPlaybackService to pause playback.
         */
        private void stopAudioPlayback() {
            // Shamelessly copied from MediaPlaybackService.java, which
            // should be public, but isn't.
            Intent i = new Intent("com.android.music.musicservicecommand");
            i.putExtra("command", "pause");
    
            sendBroadcast(i);
        }
    
        /*
         * Handle the buttons.
         */
        public void onClick(View button) {
            if (System.currentTimeMillis() - mLastClickTime < 300) {
                // in order to avoid user click bottom too quickly
                return;
            }
    
            if (!button.isEnabled())
                return;
    
            if (button.getId() == mLastButtonId && button.getId() != R.id.newButton) {
                // as the recorder state is async with the UI
                // we need to avoid launching the duplicated action
                return;
            }
    
            if (button.getId() == R.id.stopButton && System.currentTimeMillis() - mLastClickTime < 1500) {
                // it seems that the media recorder is not robust enough
                // sometime it crashes when stop recording right after starting
                return;
            }
    
            mLastClickTime = System.currentTimeMillis();
            mLastButtonId = button.getId();
    
            switch (button.getId()) {
                case R.id.newButton:
                    mFileNameEditText.clearFocus();
                    saveSample();
                    mRecorder.reset();
                    resetFileNameEditText();
                    break;
                case R.id.recordButton:
                    showOverwriteConfirmDialogIfConflicts();
                    break;
                case R.id.stopButton:
                    mRecorder.stop();
                    break;
                case R.id.playButton:
                    mRecorder.startPlayback(mRecorder.playProgress());
                    break;
                case R.id.pauseButton:
                    mRecorder.pausePlayback();
                    break;
                case R.id.finishButton:
                    mRecorder.stop();
                    saveSample();
                    finish();
                    break;
                case R.id.deleteButton:
                    showDeleteConfirmDialog();
                    break;
            }
        }
    
        private void startRecording() {
            mRemainingTimeCalculator.reset();
            if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                mSampleInterrupted = true;
                mErrorUiMessage = getResources().getString(R.string.insert_sd_card);
                updateUi(false);
            } else if (!mRemainingTimeCalculator.diskSpaceAvailable()) {
                mSampleInterrupted = true;
                mErrorUiMessage = getResources().getString(R.string.storage_is_full);
                updateUi(false);
            } else {
                stopAudioPlayback();
    
                boolean isHighQuality = SoundRecorderPreferenceActivity.isHighQuality(this);
                if (AUDIO_AMR.equals(mRequestedType)) {
                    mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
                    int outputfileformat = isHighQuality ? MediaRecorder.OutputFormat.RAW_AMR
                            : MediaRecorder.OutputFormat.RAW_AMR;
                    mRecorder.startRecording(outputfileformat, mFileNameEditText.getText().toString(),
                            FILE_EXTENSION_AMR, isHighQuality, mMaxFileSize);
                } else if (AUDIO_3GPP.equals(mRequestedType)) {
                    // HACKME: for HD2, there is an issue with high quality 3gpp
                    // use low quality instead
                    if (Build.MODEL.equals("HTC HD2")) {
                        isHighQuality = false;
                    }
    
                    mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
                    mRecorder.startRecording(MediaRecorder.OutputFormat.THREE_GPP, mFileNameEditText
                            .getText().toString(), FILE_EXTENSION_3GPP, isHighQuality, mMaxFileSize);
                } else {
                    throw new IllegalArgumentException("Invalid output file type requested");
                }
    
                if (mMaxFileSize != -1) {
                    mRemainingTimeCalculator.setFileSizeLimit(mRecorder.sampleFile(), mMaxFileSize);
                }
            }
        }
    
        /*
         * Handle the "back" hardware key.
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            if (keyCode == KeyEvent.KEYCODE_BACK) {
                switch (mRecorder.state()) {
                    case Recorder.IDLE_STATE:
                    case Recorder.PLAYING_PAUSED_STATE:
                        if (mRecorder.sampleLength() > 0)
                            saveSample();
                        finish();
                        break;
                    case Recorder.PLAYING_STATE:
                        mRecorder.stop();
                        saveSample();
                        break;
                    case Recorder.RECORDING_STATE:
                        if (mShowFinishButton) {
                            mRecorder.clear();
                        } else {
                            finish();
                        }
                        break;
                }
                return true;
            } else {
                return super.onKeyDown(keyCode, event);
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            String type = SoundRecorderPreferenceActivity.getRecordType(this);
            if (mCanRequestChanged && !TextUtils.equals(type, mRequestedType)) {
                saveSample();
                mRecorder.reset();
                mRequestedType = type;
                resetFileNameEditText();
            }
            mCanRequestChanged = false;
    
            if (!mRecorder.syncStateWithService()) {
                mRecorder.reset();
                resetFileNameEditText();
            }
    
            if (mRecorder.state() == Recorder.RECORDING_STATE) {
                String preExtension = AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR
                        : FILE_EXTENSION_3GPP;
                if (!mRecorder.sampleFile().getName().endsWith(preExtension)) {
                    // the extension is changed need to stop current recording
                    mRecorder.reset();
                    resetFileNameEditText();
                } else {
                    // restore state
                    if (!mShowFinishButton) {
                        String fileName = mRecorder.sampleFile().getName().replace(preExtension, "");
                        mFileNameEditText.setText(fileName);
                    }
    
                    if (AUDIO_AMR.equals(mRequestedType)) {
                        mRemainingTimeCalculator.setBitRate(BITRATE_AMR);
                    } else if (AUDIO_3GPP.equals(mRequestedType)) {
                        mRemainingTimeCalculator.setBitRate(BITRATE_3GPP);
                    }
                }
            } else {
                File file = mRecorder.sampleFile();
                if (file != null && !file.exists()) {
                    mRecorder.reset();
                    resetFileNameEditText();
                }
            }
    
            IntentFilter filter = new IntentFilter();
            filter.addAction(RecorderService.RECORDER_SERVICE_BROADCAST_NAME);
            registerReceiver(mReceiver, filter);
    
            mStopUiUpdate = false;
            updateUi(true);
    
            if (RecorderService.isRecording()) {
                Intent intent = new Intent(this, RecorderService.class);
                intent.putExtra(RecorderService.ACTION_NAME,
                        RecorderService.ACTION_DISABLE_MONITOR_REMAIN_TIME);
                startService(intent);
            }
        }
    
        @Override
        protected void onPause() {
            if (mRecorder.state() != Recorder.RECORDING_STATE || mShowFinishButton
                    || mMaxFileSize != -1) {
                mRecorder.stop();
                saveSample();
                mFileNameEditText.clearFocus();
                ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
                        .cancel(RecorderService.NOTIFICATION_ID);
            }
    
            if (mReceiver != null) {
                unregisterReceiver(mReceiver);
            }
    
            mCanRequestChanged = true;
            mStopUiUpdate = true;
            stopAnimation();
    
            if (RecorderService.isRecording()) {
                Intent intent = new Intent(this, RecorderService.class);
                intent.putExtra(RecorderService.ACTION_NAME,
                        RecorderService.ACTION_ENABLE_MONITOR_REMAIN_TIME);
                startService(intent);
            }
    
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            if (mShowFinishButton) {
                finish();
            }
            super.onStop();
        }
    
        /*
         * If we have just recorded a sample, this adds it to the media data base
         * and sets the result to the sample's URI.
         */
        private void saveSample() {
            if (mRecorder.sampleLength() == 0)
                return;
            if (!mSavedRecord.contains(mRecorder.sampleFile().getAbsolutePath())) {
                Uri uri = null;
                try {
                    uri = this.addToMediaDB(mRecorder.sampleFile());
                } catch (UnsupportedOperationException ex) { // Database
                    // manipulation
                    // failure
                    return;
                }
                if (uri == null) {
                    return;
                }
                mSavedRecord.add(mRecorder.sampleFile().getAbsolutePath());
                setResult(RESULT_OK, new Intent().setData(uri));
            }
        }
    
        private void showDeleteConfirmDialog() {
            AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
            dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
            dialogBuilder.setTitle(R.string.delete_dialog_title);
            dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    mRecorder.delete();
                }
            });
            dialogBuilder.setNegativeButton(android.R.string.cancel,
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            mLastButtonId = 0;
                        }
                    });
            dialogBuilder.show();
        }
    
        private void showOverwriteConfirmDialogIfConflicts() {
            String fileName = mFileNameEditText.getText().toString()
                    + (AUDIO_AMR.equals(mRequestedType) ? FILE_EXTENSION_AMR : FILE_EXTENSION_3GPP);
    
            if (mRecorder.isRecordExisted(fileName) && !mShowFinishButton) {
                // file already existed and it's not a recording request from other
                // app
                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
                dialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
                dialogBuilder.setTitle(getString(R.string.overwrite_dialog_title, fileName));
                dialogBuilder.setPositiveButton(android.R.string.ok,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                startRecording();
                            }
                        });
                dialogBuilder.setNegativeButton(android.R.string.cancel,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                mLastButtonId = 0;
                            }
                        });
                dialogBuilder.show();
            } else {
                startRecording();
            }
        }
    
        /*
         * Called on destroy to unregister the SD card mount event receiver.
         */
        @Override
        public void onDestroy() {
            if (mSDCardMountEventReceiver != null) {
                unregisterReceiver(mSDCardMountEventReceiver);
                mSDCardMountEventReceiver = null;
            }
            mSoundPool.release();
    
            super.onDestroy();
        }
    
        /*
         * Registers an intent to listen for
         * ACTION_MEDIA_EJECT/ACTION_MEDIA_UNMOUNTED/ACTION_MEDIA_MOUNTED
         * notifications.
         */
        private void registerExternalStorageListener() {
            if (mSDCardMountEventReceiver == null) {
                mSDCardMountEventReceiver = new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        mSampleInterrupted = false;
                        mRecorder.reset();
                        resetFileNameEditText();
                        updateUi(false);
                    }
                };
                IntentFilter iFilter = new IntentFilter();
                iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
                iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
                iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
                iFilter.addDataScheme("file");
                registerReceiver(mSDCardMountEventReceiver, iFilter);
            }
        }
    
        /*
         * A simple utility to do a query into the databases.
         */
        private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                String sortOrder) {
            try {
                ContentResolver resolver = getContentResolver();
                if (resolver == null) {
                    return null;
                }
                return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
            } catch (UnsupportedOperationException ex) {
                return null;
            }
        }
    
        /*
         * Add the given audioId to the playlist with the given playlistId; and
         * maintain the play_order in the playlist.
         */
        private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) {
            String[] cols = new String[] {
                "count(*)"
            };
            Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
            Cursor cur = resolver.query(uri, cols, null, null, null);
            cur.moveToFirst();
            final int base = cur.getInt(0);
            cur.close();
            ContentValues values = new ContentValues();
            values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId));
            values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
            resolver.insert(uri, values);
        }
    
        /*
         * Obtain the id for the default play list from the audio_playlists table.
         */
        private int getPlaylistId(Resources res) {
            Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
            final String[] ids = new String[] {
                MediaStore.Audio.Playlists._ID
            };
            final String where = MediaStore.Audio.Playlists.NAME + "=?";
            final String[] args = new String[] {
                res.getString(R.string.audio_db_playlist_name)
            };
            Cursor cursor = query(uri, ids, where, args, null);
            if (cursor == null) {
                Log.v(TAG, "query returns null");
            }
            int id = -1;
            if (cursor != null) {
                cursor.moveToFirst();
                if (!cursor.isAfterLast()) {
                    id = cursor.getInt(0);
                }
                cursor.close();
            }
            return id;
        }
    
        /*
         * Create a playlist with the given default playlist name, if no such
         * playlist exists.
         */
        private Uri createPlaylist(Resources res, ContentResolver resolver) {
            ContentValues cv = new ContentValues();
            cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name));
            Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv);
            if (uri == null) {
                new AlertDialog.Builder(this).setTitle(R.string.app_name)
                        .setMessage(R.string.error_mediadb_new_record)
                        .setPositiveButton(R.string.button_ok, null).setCancelable(false).show();
            }
            return uri;
        }
    
        /*
         * Adds file and returns content uri.
         */
        private Uri addToMediaDB(File file) {
            Resources res = getResources();
            ContentValues cv = new ContentValues();
            long current = System.currentTimeMillis();
            long modDate = file.lastModified();
            Date date = new Date(current);
            SimpleDateFormat formatter = new SimpleDateFormat(
                    res.getString(R.string.audio_db_title_format));
            String title = formatter.format(date);
            long sampleLengthMillis = mRecorder.sampleLength() * 1000L;
    
            // Lets label the recorded audio file as NON-MUSIC so that the file
            // won't be displayed automatically, except for in the playlist.
            cv.put(MediaStore.Audio.Media.IS_MUSIC, "0");
    
            cv.put(MediaStore.Audio.Media.TITLE, title);
            cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
            cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
            cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
            cv.put(MediaStore.Audio.Media.DURATION, sampleLengthMillis);
            cv.put(MediaStore.Audio.Media.MIME_TYPE, mRequestedType);
            cv.put(MediaStore.Audio.Media.ARTIST, res.getString(R.string.audio_db_artist_name));
            cv.put(MediaStore.Audio.Media.ALBUM, res.getString(R.string.audio_db_album_name));
            Log.d(TAG, "Inserting audio record: " + cv.toString());
            ContentResolver resolver = getContentResolver();
            Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            Log.d(TAG, "ContentURI: " + base);
            Uri result = resolver.insert(base, cv);
            if (result == null) {
                Log.w(TAG, getString(R.string.error_mediadb_new_record));
                return null;
            }
    
            if (getPlaylistId(res) == -1) {
                createPlaylist(res, resolver);
            }
            int audioId = Integer.valueOf(result.getLastPathSegment());
            addToPlaylist(resolver, audioId, getPlaylistId(res));
    
            // Notify those applications such as Music listening to the
            // scanner events that a recorded audio file just created.
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
            return result;
        }
    
        private ImageView getTimerImage(char number) {
            ImageView image = new ImageView(this);
            LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            if (number != ':') {
                image.setBackgroundResource(R.drawable.background_number);
            }
            switch (number) {
                case '0':
                    image.setImageResource(R.drawable.number_0);
                    break;
                case '1':
                    image.setImageResource(R.drawable.number_1);
                    break;
                case '2':
                    image.setImageResource(R.drawable.number_2);
                    break;
                case '3':
                    image.setImageResource(R.drawable.number_3);
                    break;
                case '4':
                    image.setImageResource(R.drawable.number_4);
                    break;
                case '5':
                    image.setImageResource(R.drawable.number_5);
                    break;
                case '6':
                    image.setImageResource(R.drawable.number_6);
                    break;
                case '7':
                    image.setImageResource(R.drawable.number_7);
                    break;
                case '8':
                    image.setImageResource(R.drawable.number_8);
                    break;
                case '9':
                    image.setImageResource(R.drawable.number_9);
                    break;
                case ':':
                    image.setImageResource(R.drawable.colon);
                    break;
            }
            image.setLayoutParams(lp);
            return image;
        }
    
        /**
         * Update the big MM:SS timer. If we are in playback, also update the
         * progress bar.
         */
        private void updateTimerView() {
            int state = mRecorder.state();
    
            boolean ongoing = state == Recorder.RECORDING_STATE || state == Recorder.PLAYING_STATE;
    
            long time = mRecorder.progress();
            String timeStr = String.format(mTimerFormat, time / 60, time % 60);
            mTimerLayout.removeAllViews();
            for (int i = 0; i < timeStr.length(); i++) {
                mTimerLayout.addView(getTimerImage(timeStr.charAt(i)));
            }
    
            if (state == Recorder.RECORDING_STATE) {
                updateTimeRemaining();
            }
    
            if (ongoing) {
                mHandler.postDelayed(mUpdateTimer, 500);
            }
        }
    
        private void setTimerView(float progress) {
            long time = (long) (progress * mRecorder.sampleLength());
            String timeStr = String.format(mTimerFormat, time / 60, time % 60);
            mTimerLayout.removeAllViews();
            for (int i = 0; i < timeStr.length(); i++) {
                mTimerLayout.addView(getTimerImage(timeStr.charAt(i)));
            }
        }
    
        private void updateSeekBar() {
            if (mRecorder.state() == Recorder.PLAYING_STATE) {
                mPlaySeekBar.setProgress((int) (SEEK_BAR_MAX * mRecorder.playProgress()));
                mHandler.postDelayed(mUpdateSeekBar, 10);
            }
        }
    
        /*
         * Called when we're in recording state. Find out how much longer we can go
         * on recording. If it's under 5 minutes, we display a count-down in the UI.
         * If we've run out of time, stop the recording.
         */
        private void updateTimeRemaining() {
            long t = mRemainingTimeCalculator.timeRemaining();
    
            if (t <= 0) {
                mSampleInterrupted = true;
    
                int limit = mRemainingTimeCalculator.currentLowerLimit();
                switch (limit) {
                    case RemainingTimeCalculator.DISK_SPACE_LIMIT:
                        mErrorUiMessage = getResources().getString(R.string.storage_is_full);
                        break;
                    case RemainingTimeCalculator.FILE_SIZE_LIMIT:
                        mErrorUiMessage = getResources().getString(R.string.max_length_reached);
                        break;
                    default:
                        mErrorUiMessage = null;
                        break;
                }
    
                mRecorder.stop();
                return;
            }
        }
    
        private void updateVUMeterView() {
            final int MAX_VU_SIZE = 11;
            boolean showVUArray[] = new boolean[MAX_VU_SIZE];
    
            if (mVUMeterLayout.getVisibility() == View.VISIBLE
                    && mRecorder.state() == Recorder.RECORDING_STATE) {
                int vuSize = MAX_VU_SIZE * mRecorder.getMaxAmplitude() / 32768;
                if (vuSize >= MAX_VU_SIZE) {
                    vuSize = MAX_VU_SIZE - 1;
                }
    
                if (vuSize >= mPreviousVUMax) {
                    mPreviousVUMax = vuSize;
                } else if (mPreviousVUMax > 0) {
                    mPreviousVUMax--;
                }
    
                for (int i = 0; i < MAX_VU_SIZE; i++) {
                    if (i <= vuSize) {
                        showVUArray[i] = true;
                    } else if (i == mPreviousVUMax) {
                        showVUArray[i] = true;
                    } else {
                        showVUArray[i] = false;
                    }
                }
    
                mHandler.postDelayed(mUpdateVUMetur, 100);
            } else if (mVUMeterLayout.getVisibility() == View.VISIBLE) {
                mPreviousVUMax = 0;
                for (int i = 0; i < MAX_VU_SIZE; i++) {
                    showVUArray[i] = false;
                }
            }
    
            if (mVUMeterLayout.getVisibility() == View.VISIBLE) {
                mVUMeterLayout.removeAllViews();
                for (boolean show : showVUArray) {
                    ImageView imageView = new ImageView(this);
                    imageView.setBackgroundResource(R.drawable.background_vumeter);
                    if (show) {
                        imageView.setImageResource(R.drawable.icon_vumeter);
                    }
                    imageView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                            LayoutParams.WRAP_CONTENT));
                    mVUMeterLayout.addView(imageView);
                }
            }
        }
    
        /**
         * Shows/hides the appropriate child views for the new state.
         */
        private void updateUi(boolean skipRewindAnimation) {
            switch (mRecorder.state()) {
                case Recorder.IDLE_STATE:
                    mLastButtonId = 0;
                case Recorder.PLAYING_PAUSED_STATE:
                    if (mRecorder.sampleLength() == 0) {
                        mNewButton.setEnabled(true);
                        mNewButton.setVisibility(View.VISIBLE);
                        mRecordButton.setVisibility(View.VISIBLE);
                        mStopButton.setVisibility(View.GONE);
                        mPlayButton.setVisibility(View.GONE);
                        mPauseButton.setVisibility(View.GONE);
                        mDeleteButton.setEnabled(false);
                        mRecordButton.requestFocus();
    
                        mVUMeterLayout.setVisibility(View.VISIBLE);
                        mSeekBarLayout.setVisibility(View.GONE);
                    } else {
                        mNewButton.setEnabled(true);
                        mNewButton.setVisibility(View.VISIBLE);
                        mRecordButton.setVisibility(View.GONE);
                        mStopButton.setVisibility(View.GONE);
                        mPlayButton.setVisibility(View.VISIBLE);
                        mPauseButton.setVisibility(View.GONE);
                        mDeleteButton.setEnabled(true);
                        mPauseButton.requestFocus();
    
                        mVUMeterLayout.setVisibility(View.GONE);
                        mSeekBarLayout.setVisibility(View.VISIBLE);
                        mStartTime.setText(String.format(mTimerFormat, 0, 0));
                        mTotalTime.setText(String.format(mTimerFormat, mRecorder.sampleLength() / 60,
                                mRecorder.sampleLength() % 60));
                    }
                    mFileNameEditText.setEnabled(true);
                    mFileNameEditText.clearFocus();
    
                    if (mRecorder.sampleLength() > 0) {
                        if (mRecorder.state() == Recorder.PLAYING_PAUSED_STATE) {
                            stopAnimation();
                            if (SoundRecorderPreferenceActivity.isEnabledSoundEffect(this)) {
                                mSoundPool.play(mPauseSound, 1.0f, 1.0f, 0, 0, 1);
                            }
                        } else {
                            mPlaySeekBar.setProgress(0);
                            if (!skipRewindAnimation) {
                                stopRecordPlayingAnimation();
                            } else {
                                stopAnimation();
                            }
                        }
                    } else {
                        stopAnimation();
                    }
    
                    // we allow only one toast at one time
                    if (mSampleInterrupted && mErrorUiMessage == null) {
                        Toast.makeText(this, R.string.recording_stopped, Toast.LENGTH_SHORT).show();
                    }
    
                    if (mErrorUiMessage != null) {
                        Toast.makeText(this, mErrorUiMessage, Toast.LENGTH_SHORT).show();
                    }
    
                    break;
                case Recorder.RECORDING_STATE:
                    mNewButton.setEnabled(false);
                    mNewButton.setVisibility(View.VISIBLE);
                    mRecordButton.setVisibility(View.GONE);
                    mStopButton.setVisibility(View.VISIBLE);
                    mPlayButton.setVisibility(View.GONE);
                    mPauseButton.setVisibility(View.GONE);
                    mDeleteButton.setEnabled(false);
                    mStopButton.requestFocus();
    
                    mVUMeterLayout.setVisibility(View.VISIBLE);
                    mSeekBarLayout.setVisibility(View.GONE);
    
                    mFileNameEditText.setEnabled(false);
    
                    startRecordPlayingAnimation();
                    mPreviousVUMax = 0;
                    break;
    
                case Recorder.PLAYING_STATE:
                    mNewButton.setEnabled(false);
                    mNewButton.setVisibility(View.VISIBLE);
                    mRecordButton.setVisibility(View.GONE);
                    mStopButton.setVisibility(View.GONE);
                    mPlayButton.setVisibility(View.GONE);
                    mPauseButton.setVisibility(View.VISIBLE);
                    mDeleteButton.setEnabled(false);
                    mPauseButton.requestFocus();
    
                    mVUMeterLayout.setVisibility(View.GONE);
                    mSeekBarLayout.setVisibility(View.VISIBLE);
    
                    mFileNameEditText.setEnabled(false);
    
                    if (SoundRecorderPreferenceActivity.isEnabledSoundEffect(this)) {
                        mSoundPool.play(mPlaySound, 1.0f, 1.0f, 0, 0, 1);
                    }
                    startRecordPlayingAnimation();
                    break;
            }
    
            updateTimerView();
            updateSeekBar();
            updateVUMeterView();
    
        }
    
        /*
         * Called when Recorder changed it's state.
         */
        public void onStateChanged(int state) {
            if (state == Recorder.PLAYING_STATE || state == Recorder.RECORDING_STATE) {
                mSampleInterrupted = false;
                mErrorUiMessage = null;
            }
    
            updateUi(false);
        }
    
        /*
         * Called when MediaPlayer encounters an error.
         */
        public void onError(int error) {
            Resources res = getResources();
    
            String message = null;
            switch (error) {
                case Recorder.STORAGE_ACCESS_ERROR:
                    message = res.getString(R.string.error_sdcard_access);
                    break;
                case Recorder.IN_CALL_RECORD_ERROR:
                    // TODO: update error message to reflect that the recording
                    // could not be
                    // performed during a call.
                case Recorder.INTERNAL_ERROR:
                    message = res.getString(R.string.error_app_internal);
                    break;
            }
            if (message != null) {
                new AlertDialog.Builder(this).setTitle(R.string.app_name).setMessage(message)
                        .setPositiveButton(R.string.button_ok, null).setCancelable(false).show();
            }
        }
    
        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
            menu.clear();
            if (mRecorder.state() == Recorder.RECORDING_STATE
                    || mRecorder.state() == Recorder.PLAYING_STATE) {
                return false;
            } else {
                getMenuInflater().inflate(R.layout.view_list_menu, menu);
                return true;
            }
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            Intent intent;
            switch (item.getItemId()) {
                case R.id.menu_fm:
                    saveSample();
                    intent = new Intent();
                    intent.addCategory(Intent.CATEGORY_DEFAULT);
                    intent.setData(Uri.parse("file://" + mRecorder.getRecordDir()));
                    startActivity(intent);
                    break;
                case R.id.menu_setting:
                    intent = new Intent(this, SoundRecorderPreferenceActivity.class);
                    startActivity(intent);
                    break;
                default:
                    break;
            }
            return true;
        }
    
        private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
            private final int DELTA = SEEK_BAR_MAX / 20;
    
            private int mProgress = 0;
    
            private boolean mPlayingAnimation = false;
    
            private boolean mForwardAnimation = true;
    
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                stopAnimation();
                mRecorder.startPlayback((float) seekBar.getProgress() / SEEK_BAR_MAX);
            }
    
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                mRecorder.pausePlayback();
                mPlayingAnimation = false;
            }
    
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    if (!mPlayingAnimation) {
                        mForwardAnimation = true;
                        startForwardAnimation();
                        mPlayingAnimation = true;
                        mProgress = progress;
                    }
    
                    if (progress >= mProgress + DELTA) {
                        if (!mForwardAnimation) {
                            mForwardAnimation = true;
                            stopAnimation();
                            startForwardAnimation();
                        }
                        mProgress = progress;
                    } else if (progress < mProgress - DELTA) {
                        if (mForwardAnimation) {
                            mForwardAnimation = false;
                            stopAnimation();
                            startBackwardAnimation();
                        }
                        mProgress = progress;
                    }
    
                    setTimerView(((float) progress) / SEEK_BAR_MAX);
                    mLastButtonId = 0;
                }
            }
        };
    
        private class RecorderReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_STATE)) {
                    boolean isRecording = intent.getBooleanExtra(
                            RecorderService.RECORDER_SERVICE_BROADCAST_STATE, false);
                    mRecorder.setState(isRecording ? Recorder.RECORDING_STATE : Recorder.IDLE_STATE);
                } else if (intent.hasExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR)) {
                    int error = intent.getIntExtra(RecorderService.RECORDER_SERVICE_BROADCAST_ERROR, 0);
                    mRecorder.setError(error);
                }
            }
        }
    }
    

    核心代码2...

    package com.lv.reco;
    
    import java.io.File;
    import java.io.IOException;
    
    import android.app.KeyguardManager;
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.media.AudioManager;
    import android.media.MediaRecorder;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.PowerManager;
    import android.os.PowerManager.WakeLock;
    import android.telephony.PhoneStateListener;
    import android.telephony.TelephonyManager;
    
    public class RecorderService extends Service implements MediaRecorder.OnErrorListener {
    
        public final static String ACTION_NAME = "action_type";
    
        public final static int ACTION_INVALID = 0;
    
        public final static int ACTION_START_RECORDING = 1;
    
        public final static int ACTION_STOP_RECORDING = 2;
    
        public final static int ACTION_ENABLE_MONITOR_REMAIN_TIME = 3;
    
        public final static int ACTION_DISABLE_MONITOR_REMAIN_TIME = 4;
    
        public final static String ACTION_PARAM_FORMAT = "format";
    
        public final static String ACTION_PARAM_PATH = "path";
    
        public final static String ACTION_PARAM_HIGH_QUALITY = "high_quality";
    
        public final static String ACTION_PARAM_MAX_FILE_SIZE = "max_file_size";
    
        public final static String RECORDER_SERVICE_BROADCAST_NAME = "com.android.soundrecorder.broadcast";
    
        public final static String RECORDER_SERVICE_BROADCAST_STATE = "is_recording";
    
        public final static String RECORDER_SERVICE_BROADCAST_ERROR = "error_code";
    
        public final static int NOTIFICATION_ID = 62343234;
    
        private static MediaRecorder mRecorder = null;
    
        private static String mFilePath = null;
    
        private static long mStartTime = 0;
    
        private RemainingTimeCalculator mRemainingTimeCalculator;
    
        private NotificationManager mNotifiManager;
    
        private Notification mLowStorageNotification;
    
        private TelephonyManager mTeleManager;
    
        private WakeLock mWakeLock;
    
        private KeyguardManager mKeyguardManager;
    
        private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (state != TelephonyManager.CALL_STATE_IDLE) {
                    localStopRecording();
                }
            }
        };
    
        private final Handler mHandler = new Handler();
    
        private Runnable mUpdateRemainingTime = new Runnable() {
            public void run() {
                if (mRecorder != null && mNeedUpdateRemainingTime) {
                    updateRemainingTime();
                }
            }
        };
    
        private boolean mNeedUpdateRemainingTime;
    
        @Override
        public void onCreate() {
            super.onCreate();
            mRecorder = null;
            mLowStorageNotification = null;
            mRemainingTimeCalculator = new RemainingTimeCalculator();
            mNeedUpdateRemainingTime = false;
            mNotifiManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            mTeleManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            mTeleManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SoundRecorder");
            mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Bundle bundle = intent.getExtras();
            if (bundle != null && bundle.containsKey(ACTION_NAME)) {
                switch (bundle.getInt(ACTION_NAME, ACTION_INVALID)) {
                    case ACTION_START_RECORDING:
                        localStartRecording(bundle.getInt(ACTION_PARAM_FORMAT),
                                bundle.getString(ACTION_PARAM_PATH),
                                bundle.getBoolean(ACTION_PARAM_HIGH_QUALITY),
                                bundle.getLong(ACTION_PARAM_MAX_FILE_SIZE));
                        break;
                    case ACTION_STOP_RECORDING:
                        localStopRecording();
                        break;
                    case ACTION_ENABLE_MONITOR_REMAIN_TIME:
                        if (mRecorder != null) {
                            mNeedUpdateRemainingTime = true;
                            mHandler.post(mUpdateRemainingTime);
                        }
                        break;
                    case ACTION_DISABLE_MONITOR_REMAIN_TIME:
                        mNeedUpdateRemainingTime = false;
                        if (mRecorder != null) {
                            showRecordingNotification();
                        }
                        break;
                    default:
                        break;
                }
                return START_STICKY;
            }
            return super.onStartCommand(intent, flags, startId);
        }
    
        @Override
        public void onDestroy() {
            mTeleManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
            if (mWakeLock.isHeld()) {
                mWakeLock.release();
            }
            super.onDestroy();
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onLowMemory() {
            localStopRecording();
            super.onLowMemory();
        }
    
        private void localStartRecording(int outputfileformat, String path, boolean highQuality,
                long maxFileSize) {
            if (mRecorder == null) {
                mRemainingTimeCalculator.reset();
                if (maxFileSize != -1) {
                    mRemainingTimeCalculator.setFileSizeLimit(new File(path), maxFileSize);
                }
    
                mRecorder = new MediaRecorder();
                mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                if (outputfileformat == MediaRecorder.OutputFormat.THREE_GPP) {
                    mRemainingTimeCalculator.setBitRate(SoundRecorder.BITRATE_3GPP);
                    mRecorder.setAudioSamplingRate(highQuality ? 44100 : 22050);
                    mRecorder.setOutputFormat(outputfileformat);
                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                } else {
                    mRemainingTimeCalculator.setBitRate(SoundRecorder.BITRATE_AMR);
                    mRecorder.setAudioSamplingRate(highQuality ? 16000 : 8000);
                    mRecorder.setOutputFormat(outputfileformat);
                    mRecorder.setAudioEncoder(highQuality ? MediaRecorder.AudioEncoder.AMR_NB
                            : MediaRecorder.AudioEncoder.AMR_NB);
                }
                mRecorder.setOutputFile(path);
                mRecorder.setOnErrorListener(this);
    
                // Handle IOException
                try {
                    mRecorder.prepare();
                } catch (IOException exception) {
                    sendErrorBroadcast(Recorder.INTERNAL_ERROR);
                    mRecorder.reset();
                    mRecorder.release();
                    mRecorder = null;
                    return;
                }
                // Handle RuntimeException if the recording couldn't start
                try {
                    mRecorder.start();
                } catch (RuntimeException exception) {
                    AudioManager audioMngr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
                    boolean isInCall = (audioMngr.getMode() == AudioManager.MODE_IN_CALL);
                    if (isInCall) {
                        sendErrorBroadcast(Recorder.IN_CALL_RECORD_ERROR);
                    } else {
                        sendErrorBroadcast(Recorder.INTERNAL_ERROR);
                    }
                    mRecorder.reset();
                    mRecorder.release();
                    mRecorder = null;
                    return;
                }
                mFilePath = path;
                mStartTime = System.currentTimeMillis();
                mWakeLock.acquire();
                mNeedUpdateRemainingTime = false;
                sendStateBroadcast();
                showRecordingNotification();
            }
        }
    
        private void localStopRecording() {
            if (mRecorder != null) {
                mNeedUpdateRemainingTime = false;
                try {
                    mRecorder.stop();
                } catch (RuntimeException e) {
                }
                mRecorder.release();
                mRecorder = null;
    
                sendStateBroadcast();
                showStoppedNotification();
            }
            stopSelf();
        }
    
        private void showRecordingNotification() {
            Notification notification = new Notification(R.drawable.stat_sys_call_record,
                    getString(R.string.notification_recording), System.currentTimeMillis());
            notification.flags = Notification.FLAG_ONGOING_EVENT;
            PendingIntent pendingIntent;
            pendingIntent = PendingIntent
                    .getActivity(this, 0, new Intent(this, SoundRecorder.class), 0);
    
            notification.setLatestEventInfo(this, getString(R.string.app_name),
                    getString(R.string.notification_recording), pendingIntent);
    
            startForeground(NOTIFICATION_ID, notification);
        }
    
        private void showLowStorageNotification(int minutes) {
            if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
                // it's not necessary to show this notification in lock-screen
                return;
            }
    
            if (mLowStorageNotification == null) {
                mLowStorageNotification = new Notification(R.drawable.stat_sys_call_record_full,
                        getString(R.string.notification_recording), System.currentTimeMillis());
                mLowStorageNotification.flags = Notification.FLAG_ONGOING_EVENT;
            }
    
            PendingIntent pendingIntent;
            pendingIntent = PendingIntent
                    .getActivity(this, 0, new Intent(this, SoundRecorder.class), 0);
    
            mLowStorageNotification.setLatestEventInfo(this, getString(R.string.app_name),
                    getString(R.string.notification_warning, minutes), pendingIntent);
            startForeground(NOTIFICATION_ID, mLowStorageNotification);
        }
    
        private void showStoppedNotification() {
            stopForeground(true);
            mLowStorageNotification = null;
    
            Notification notification = new Notification(R.drawable.stat_sys_call_record,
                    getString(R.string.notification_stopped), System.currentTimeMillis());
            notification.flags = Notification.FLAG_AUTO_CANCEL;
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setType("audio/*");
            intent.setDataAndType(Uri.fromFile(new File(mFilePath)), "audio/*");
    
            PendingIntent pendingIntent;
            pendingIntent = PendingIntent.getActivity(this, 0, intent,
                    PendingIntent.FLAG_UPDATE_CURRENT);
    
            notification.setLatestEventInfo(this, getString(R.string.app_name),
                    getString(R.string.notification_stopped), pendingIntent);
            mNotifiManager.notify(NOTIFICATION_ID, notification);
        }
    
        private void sendStateBroadcast() {
            Intent intent = new Intent(RECORDER_SERVICE_BROADCAST_NAME);
            intent.putExtra(RECORDER_SERVICE_BROADCAST_STATE, mRecorder != null);
            sendBroadcast(intent);
        }
    
        private void sendErrorBroadcast(int error) {
            Intent intent = new Intent(RECORDER_SERVICE_BROADCAST_NAME);
            intent.putExtra(RECORDER_SERVICE_BROADCAST_ERROR, error);
            sendBroadcast(intent);
        }
    
        private void updateRemainingTime() {
            long t = mRemainingTimeCalculator.timeRemaining();
            if (t <= 0) {
                localStopRecording();
                return;
            } else if (t <= 1800
                    && mRemainingTimeCalculator.currentLowerLimit() != RemainingTimeCalculator.FILE_SIZE_LIMIT) {
                // less than half one hour
                showLowStorageNotification((int) Math.ceil(t / 60.0));
            }
    
            if (mRecorder != null && mNeedUpdateRemainingTime) {
                mHandler.postDelayed(mUpdateRemainingTime, 500);
            }
        }
    
        public static boolean isRecording() {
            return mRecorder != null;
        }
    
        public static String getFilePath() {
            return mFilePath;
        }
    
        public static long getStartTime() {
            return mStartTime;
        }
    
        public static void startRecording(Context context, int outputfileformat, String path,
                boolean highQuality, long maxFileSize) {
            Intent intent = new Intent(context, RecorderService.class);
            intent.putExtra(ACTION_NAME, ACTION_START_RECORDING);
            intent.putExtra(ACTION_PARAM_FORMAT, outputfileformat);
            intent.putExtra(ACTION_PARAM_PATH, path);
            intent.putExtra(ACTION_PARAM_HIGH_QUALITY, highQuality);
            intent.putExtra(ACTION_PARAM_MAX_FILE_SIZE, maxFileSize);
            context.startService(intent);
        }
    
        public static void stopRecording(Context context) {
            Intent intent = new Intent(context, RecorderService.class);
            intent.putExtra(ACTION_NAME, ACTION_STOP_RECORDING);
            context.startService(intent);
        }
    
        public static int getMaxAmplitude() {
            return mRecorder == null ? 0 : mRecorder.getMaxAmplitude();
        }
    
        @Override
        public void onError(MediaRecorder mr, int what, int extra) {
            sendErrorBroadcast(Recorder.INTERNAL_ERROR);
            localStopRecording();
        }
    }
    


    效果图:


  • 相关阅读:
    permission 文档 翻译 运行时权限
    TabLayout ViewPager Fragment 简介 案例 MD
    Log 日志工具类 保存到文件 MD
    OkHttp 官方wiki 翻译 MD
    Okhttp 简介 示例 MD
    OkHttp 官方Wiki之【使用案例】
    DialogPlus
    倒计时 总结 Timer Handler CountDownTimer RxJava MD
    RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
    CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3146822.html
Copyright © 2011-2022 走看看