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();
        }
    }
    


    效果图:


  • 相关阅读:
    数据仓库 数据可视化 Hive导出到MySql
    数据仓库 品牌复购率
    数据仓库 转化率及漏斗分析
    数据仓库 GMV成交总额
    数据仓库 DWS层之用户行为宽表
    数据仓库 业务数仓 DWD层
    数据仓库 业务数仓 ODS层
    数据仓库 表的分类与同步策略
    数据仓库 最近七天内连续三天活跃用户数
    CF505E Mr. Kitayuta vs. Bamboos 二分+贪心
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3146822.html
Copyright © 2011-2022 走看看