iOS后台持续播放音乐

摘要:
13日晚开奖的第15041期体彩大乐透开出1.77亿元巨奖。这不是重点,今天下午得主现真身领奖了,这也不是重点!重点是人家随手就捐了1000万,500万给华西医院,500万给华西第二医院!好人一生平安!
… … 幻灯播放查看原图 X您已经浏览完所有图片重新播放 下一图集

之前在App
Store上架了一个音乐播放器软件,用的是AVPlayer做的音乐播放器。很多用户反映没有后台播放,最近决定更新一下。注意,重点是持续后台播放,网络歌曲也可以,重点是持续播放,后台播放很简单,但是后台持续播放,则需要做一些处理,申请后台id,才能实现持续播放。

最近有小伙伴经常android的录音怎么实现,有没有相关的案例。今天给大家推荐一个android中实现录音和播放的小案例。

选中Targets–>Capabilities–>BackgroundModes–>ON,并勾选Audio
and AirPlay选项,如下图

效果图:

澳门新葡亰平台游戏 1设置后台模式

澳门新葡亰平台游戏 2

-applicationWillResignActive:(UIApplication *)application{ //开启后台处理多媒体事件 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; AVAudioSession *session=[AVAudioSession sharedInstance]; [session setActive:YES error:nil]; //后台播放 [session setCategory:AVAudioSessionCategoryPlayback error:nil]; //这样做,可以在按home键进入后台后 ,播放一段时间,几分钟吧。但是不能持续播放网络歌曲,若需要持续播放网络歌曲,还需要申请后台任务id,具体做法是:_bgTaskId=[AppDelegate backgroundPlayerID:_bgTaskId]; //其中的_bgTaskId是后台任务UIBackgroundTaskIdentifier _bgTaskId;}实现一下backgroundPlayerID:这个方法:+(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId{ //设置并激活音频会话类别 AVAudioSession *session=[AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; //允许应用程序接收远程控制 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; //设置后台任务ID UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid; newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:backTaskId]; } return newTaskId;}

image

原理是,在音乐播放被中断时,暂停播放,在中断完成后,开始播放。具体做法是:–>在通知中心注册一个事件中断的通知://处理中断事件的通知

一、实现录音的 Service
关键代码:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterreption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]];
 // 开始录音
    public void startRecording() {
        setFileNameAndPath();

        mRecorder = new MediaRecorder();
        mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); //录音文件保存的格式,这里保存为 mp4
        mRecorder.setOutputFile(mFilePath); // 设置录音文件的保存路径
        mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        mRecorder.setAudioChannels(1);
        // 设置录音文件的清晰度
        mRecorder.setAudioSamplingRate(44100);
        mRecorder.setAudioEncodingBitRate(192000);

        try {
            mRecorder.prepare();
            mRecorder.start();
            mStartingTimeMillis = System.currentTimeMillis();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
        }
    }

    // 设置录音文件的名字和保存路径
    public void setFileNameAndPath() {
        File f;

        do {
            count++;
            mFileName = getString(R.string.default_file_name)
                    + "_" + (System.currentTimeMillis()) + ".mp4";
            mFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
            mFilePath += "/SoundRecorder/" + mFileName;
            f = new File(mFilePath);
        } while (f.exists() && !f.isDirectory());
    }

    // 停止录音
    public void stopRecording() {
        mRecorder.stop();
        mElapsedMillis = (System.currentTimeMillis() - mStartingTimeMillis);
        mRecorder.release();

        getSharedPreferences("sp_name_audio", MODE_PRIVATE)
                .edit()
                .putString("audio_path", mFilePath)
                .putLong("elpased", mElapsedMillis)
                .apply();
        if (mIncrementTimerTask != null) {
            mIncrementTimerTask.cancel();
            mIncrementTimerTask = null;
        }

        mRecorder = null;
    }

//处理中断事件

二、显示录音界面的 RecordAudioDialogFragment

用户进行的时候,总不能让 App
跳转到另外一个界面吧,这样用户体验并不是很好,比较好的方法是显示一个对话框,让用户进行操作,既然要用对话框,必然离不开
DialogFragment

在 RecordAudioDialogFragment 有一个 newInstance(int maxTime)
的静态方法供外部调用,如果想设置录音的最大时长,直接传参数进去就行了。

好的,敲黑板,重点来了,其实这个对话框的重点部分就是在
onCreateDialog()中,我们先加载了我们自定义的对话框的布局,当点击录音的按钮的时候,先进行相关权限的申请,这里有个巨坑,录音权限
android.permission.RECORD_AUDIO
在不久前还是普通权限的,不知道什么时候突然变成了危险权限,需要我们进行申请,Google
真是会玩。

    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_record_audio, null);

        mFabRecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(getActivity()
                            , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, 1);
                }else {
                    onRecord(mStartRecording);
                    mStartRecording = !mStartRecording;
                }
            }
        });

        builder.setView(view);
        return builder.create();
    }
-handleInterreption:(NSNotification *)sender{ if { [self.playView.player pause]; _played=NO; } else { [self.playView.player play]; _played=YES; }}

三、播放录音的 PlaybackDialogFragment

其实,如果只是录音这一块的话,写个 MediaPlayer
就可以了,然而还要写播放的时间进度,以及显示一个稍微好看点的进度条,我能怎样,我也很烦啊。

外部调用这个对话框的时候,只需要传入一个包含录音文件信息的
RecordingItem,因为包含的信息比较多,所以最好将 RecordingItem
进行序列化。

    public static PlaybackDialogFragment newInstance(RecordingItem item) {
        PlaybackDialogFragment fragment = new PlaybackDialogFragment();
        Bundle bundle = new Bundle();
        bundle.putParcelable(ARG_ITEM, item);
        fragment.setArguments(b);
        return fragment;
    }

澳门新葡亰平台游戏,好,重点又来了,来看看 onCreateDialog() 方法,在加载了布局之后,给
mSeekBar 设置监听,mSeekBar
是一个显示进度条的控件,当开始播放录音时候,将录音文件的时长,设置进
mSeekBar 里面,播放录音的同时,运行 mSeekBar,通过监听 mSeekBar
的进度,刷新显示的播放进度。

    public Dialog onCreateDialog(Bundle savedInstanceState) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        View view = getActivity().getLayoutInflater().inflate(R.layout.fragment_media_playback, null);

        mFileLengthTextView.setText(String.valueOf(mFileLength));
        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if(mMediaPlayer != null && fromUser) {
                    mMediaPlayer.seekTo(progress);
                    mHandler.removeCallbacks(mRunnable);

                    long minutes = TimeUnit.MILLISECONDS.toMinutes(mMediaPlayer.getCurrentPosition());
                    long seconds = TimeUnit.MILLISECONDS.toSeconds(mMediaPlayer.getCurrentPosition())
                            - TimeUnit.MINUTES.toSeconds(minutes);
                    mCurrentProgressTextView.setText(String.format("%02d:%02d", minutes,seconds));

                    updateSeekBar();

                } else if (mMediaPlayer == null && fromUser) {
                    prepareMediaPlayerFromPoint(progress);
                    updateSeekBar();
                }
            }

        });

        mPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onPlay(isPlaying);
                isPlaying = !isPlaying;
            }
        });

        mFileLengthTextView.setText(String.format("%02d:%02d", minutes,seconds));
        builder.setView(view);
        return builder.create();
    }

当点击播放录音的按钮之后,会调用 onPlay() 方法,然后根据
isPlaying(标识当前是否播放录音)的值,来调用不同的方法

    private void onPlay(boolean isPlaying){
        if (!isPlaying) {
            //currently MediaPlayer is not playing audio
            if(mMediaPlayer == null) {
                startPlaying(); //start from beginning
            } 
        } else {
            pausePlaying();
        }
    }

我们最关心的,莫过于 startPlaying()
这个方法,这个方法便是来开启播放录音的,我们首先将外部传入的有关的录音信息,设置给
MediaPlayer,然后开始调用 mMediaPlayer.start() 进行录音的播放,然后调用
updateSeekbar() 实时更新进度条的内容。当 MediaPlayer
的内容播放完成后,调用 stopPlaying() 方法,关闭 mMediaPlayer

项目地址:

https://github.com/developerHaoz/SoundRecorderUtils

4.至此音乐后台持续播放搞定,大功告成!现在可以打开软件播放一首歌曲,然后按home键回到后台,音乐会继续播放~

发表评论

电子邮件地址不会被公开。 必填项已用*标注