0


Android程序设计之音乐播放器实现

Android毕设音乐播放器实现

基于MediaPlayer技术实现在线音乐播放器,播放在线音乐,后端使用SpringBoot将音乐存放在Tomcat服务器。app通过网络请求获取音乐,从而实现在线音乐播放。该项目分为用户端和管理员端


一、核心技术Service组件介绍

Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。

虽然服务是在后台运行的,但是Service和Activity都是运行在当前APP所在的main thread(UI主线程)中的,而耗时操作(如网络请求、拷贝数据、大文件)会阻塞主线程,给用户带来不好的体验。如果需要在服务中进行耗时操作,可以选择 IntentService,IntentService是Service的子类,用来处理异步请求。

二、如何使用SerVice

创建Service直接在Android Studio中右键选择Service创建即可。默认我们所创建的Service是继承Service的。同时我们为了实现后台音乐播放的功能,所以我们还要实MediaPlayer.OnCompletionListener的接口。

同时还要在AndroidManifest.xml文件中对已经创建的Service进行注册,这一点Android Studio已经帮我们自动创建好了

三、Service启动的两种方式

(1)在Acitivity界面通过显式意图(或隐式意图)的方式来启动服务和关闭服务。

Intent intentService =newIntent(MainActivity.this,AudioService.class);startService(intentService);

(2)bindService()绑定服务

当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。


1. 用户端功能模块:登录,注册,音乐推荐,音乐分类,个人中心,音乐浏览记录,我的下载,上一曲,下一曲,音乐下载

在这里插入图片描述
在这里插入图片描述


2.管理员模块:登录,注册,用户管理,音乐分类管理(添加分类,删除分类,编辑分类),音乐管理(修改歌名,移动音乐分类,删除音乐)

在这里插入图片描述
在这里插入图片描述


3.部分核心代码实现

欢迎页

/**
 * 欢迎页
 */@SuppressLint("CustomSplashScreen")publicclassSplashActivityextendsBaseActivity<ActivitySplashBinding>{@OverrideprotectedActivitySplashBindinggetViewBinding(){returnActivitySplashBinding.inflate(getLayoutInflater());}@OverrideprotectedvoidsetListener(){}@OverrideprotectedvoidinitData(){newHandler(Looper.myLooper()).postDelayed(newRunnable(){@Overridepublicvoidrun(){startActivity(newIntent(mContext,LoginActivity.class));finish();}},800);}}

用户主页面

/**
 * 用户主页面
 */publicclassMainActivityextendsBaseActivity<ActivityMainBinding>{privateString[] titles ={"音乐推荐","音乐分类"};privateList<Fragment> fragmentList =newArrayList<>();@OverrideprotectedActivityMainBindinggetViewBinding(){returnActivityMainBinding.inflate(getLayoutInflater());}@OverrideprotectedvoidsetListener(){

        mBinding.avatar.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){startActivityForResult(newIntent(MainActivity.this,MineActivity.class),20002);}});}@OverrideprotectedvoidinitData(){if(ApiConstants.getUserInfo()!=null){
            mBinding.username.setText(ApiConstants.getUserInfo().getUsername());}//造数据
        fragmentList.add(newHomeFragment());
        fragmentList.add(newTypeFragment());//        fragmentList.add(new RecordFragment());//如果处理成懒加载的话,其实很简单,只要是这个方法setOffscreenPageLimit不去设置,就可以了。//        mBinding.viewPager.setOffscreenPageLimit(fragmentList.size());
        mBinding.viewPager.setUserInputEnabled(false);
        mBinding.viewPager.setAdapter(newFragmentStateAdapter(this){@NonNull@OverridepublicFragmentcreateFragment(int position){return fragmentList.get(position);}@OverridepublicintgetItemCount(){return fragmentList.size();}});
        mBinding.tabs.addOnTabSelectedListener(newTabLayout.OnTabSelectedListener(){@OverridepublicvoidonTabSelected(TabLayout.Tab tab){
                mBinding.viewPager.setCurrentItem(tab.getPosition(),false);}@OverridepublicvoidonTabUnselected(TabLayout.Tab tab){}@OverridepublicvoidonTabReselected(TabLayout.Tab tab){}});TabLayoutMediator tabLayoutMediator =newTabLayoutMediator(mBinding.tabs, mBinding.viewPager,newTabLayoutMediator.TabConfigurationStrategy(){@OverridepublicvoidonConfigureTab(@NonNullTabLayout.Tab tab,int position){
                tab.setText(titles[position]);}});//这句话很重要
        tabLayoutMediator.attach();}@OverrideprotectedvoidonActivityResult(int requestCode,int resultCode,@NullableIntent data){super.onActivityResult(requestCode, resultCode, data);if(resultCode ==20002){finish();}}}

音乐播放界面

/**
 * 音乐播放界面
 */publicclassPlayMusicActivityextendsBaseActivity<ActivityPlayMusicBinding>implementsOnPlayerEventListener{privatestaticfinalStringTAG="============";privateMusicInfo musicInfo;privateint mLastProgress;@OverrideprotectedActivityPlayMusicBindinggetViewBinding(){returnActivityPlayMusicBinding.inflate(getLayoutInflater());}@OverrideprotectedvoidsetListener(){Aria.download(this).register();

        mBinding.sbProgress.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener(){@OverridepublicvoidonProgressChanged(SeekBar seekBar,int progress,boolean b){if(Math.abs(progress - mLastProgress)>=DateUtils.SECOND_IN_MILLIS){
                    mBinding.tvCurrentTime.setText(formatTime("mm:ss", progress));
                    mLastProgress = progress;}}@OverridepublicvoidonStartTrackingTouch(SeekBar seekBar){}@OverridepublicvoidonStopTrackingTouch(SeekBar seekBar){if(AudioPlayer.get().isPlaying()||AudioPlayer.get().isPausing()){int progress = seekBar.getProgress();AudioPlayer.get().seekTo(progress);}else{
                    seekBar.setProgress(0);}}});

        mBinding.ivMusicPlay.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){AudioPlayer.get().playPause();}});

        mBinding.ivMusicPrevious.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){AudioPlayer.get().prev();}});

        mBinding.ivMusicNext.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){AudioPlayer.get().next();}});//下载
        mBinding.download.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(View view){if(XXPermissions.isGranted(mContext,Permission.Group.STORAGE)){download();}else{checkPermission();}}});}@OverrideprotectedvoidinitData(){initSystemBar();
        musicInfo =(MusicInfo)getIntent().getSerializableExtra("musicInfo");//监听AudioPlayer.get().addOnPlayEventListener(this);if(null!= musicInfo){AudioPlayer.get().addAndPlay(musicInfo);//添加到浏览记录addRecord(musicInfo);//获取单个任务实体DownloadEntity entity =Aria.download(this).getFirstDownloadEntity(musicInfo.getMusic_url());if(null!= entity){
                mBinding.download.setClickable(false);
                mBinding.download.setImageResource(R.mipmap.ic_download_complete);}else{
                mBinding.download.setClickable(true);
                mBinding.download.setImageResource(R.mipmap.iv_download);}}}/**
     * 沉浸式状态栏
     */privatevoidinitSystemBar(){ImmersionBar.with(this).init();}publicStringformatTime(String pattern,long milli){int m =(int)(milli /DateUtils.MINUTE_IN_MILLIS);int s =(int)((milli /DateUtils.SECOND_IN_MILLIS)%60);String mm =String.format(Locale.getDefault(),"%02d", m);String ss =String.format(Locale.getDefault(),"%02d", s);return pattern.replace("mm", mm).replace("ss", ss);}@SuppressLint("SetTextI18n")privatevoidonChangeImpl(MusicInfo music){if(music ==null){return;}
        mBinding.sbProgress.setProgress((int)AudioPlayer.get().getAudioPosition());
        mBinding.sbProgress.setSecondaryProgress(0);
        mLastProgress =0;
        mBinding.tvCurrentTime.setText("00:00");if(AudioPlayer.get().isPlaying()||AudioPlayer.get().isPreparing()){
            mBinding.ivMusicPlay.setSelected(true);}else{
            mBinding.ivMusicPlay.setSelected(false);}
        mBinding.toolbar.setTitle(music.getMusic_title());
        mBinding.tvMusicTitle.setText(music.getMusic_title());
        mBinding.tvMusicSongType.setText(music.getMusic_type());startAnim();}@OverridepublicvoidonChange(MusicInfo music){onChangeImpl(music);}@OverridepublicvoidonPlayerStart(long duration){//一定要设置最大值
        mBinding.sbProgress.setMax((int) duration);
        mBinding.tvTotalTime.setText(formatTime("mm:ss", duration));
        mBinding.ivMusicPlay.setSelected(true);startAnim();}@OverridepublicvoidonPlayerPause(){
        mBinding.ivMusicPlay.setSelected(false);stopAnim();}@OverridepublicvoidonPublish(int progress){
        mBinding.sbProgress.setProgress(progress);}@OverridepublicvoidonBufferingUpdate(int percent){
        mBinding.sbProgress.setSecondaryProgress(mBinding.sbProgress.getMax()*100/ percent);}privateAnimation animation;privatevoidstartAnim(){
        animation =AnimationUtils.loadAnimation(this,R.anim.rotation_animation);LinearInterpolator lin =newLinearInterpolator();//设置动画匀速运动
        animation.setInterpolator(lin);
        mBinding.imgCd.startAnimation(animation);}privatevoidstopAnim(){if(mBinding.imgCd.getAnimation()!=null){
            mBinding.imgCd.clearAnimation();}}privatevoidaddRecord(MusicInfo musicInfo){OkGo.<String>get(ApiConstants.ADD_RECORD_MUSIC_URL).params("username",ApiConstants.getUserInfo().getUsername()).params("music_title", musicInfo.getMusic_title()).params("music_url", musicInfo.getMusic_url()).params("music_type", musicInfo.getMusic_type()).execute(newHttpStringCallback(null){@OverrideprotectedvoidonSuccess(String msg,String response){}@OverrideprotectedvoidonError(String response){}});}privatevoidcheckPermission(){XXPermissions.with(this)// 申请单个权限// 申请多个权限.permission(Permission.Group.STORAGE)// 设置权限请求拦截器(局部设置)//.interceptor(new PermissionInterceptor())// 设置不触发错误检测机制(局部设置)//.unchecked().request(newOnPermissionCallback(){@OverridepublicvoidonGranted(List<String> permissions,boolean all){if(!all){showToast("获取部分权限成功,但部分权限未正常授予");return;}//这里做操作}@OverridepublicvoidonDenied(List<String> permissions,boolean never){if(never){showToast("被永久拒绝授权,请手动授予录音和日历权限");// 如果是被永久拒绝就跳转到应用权限系统设置页面XXPermissions.startPermissionActivity(mContext, permissions);}else{showToast("获取录音和日历权限失败");}}});}@Download.onWaitpublicvoidonWait(DownloadTask task){Log.d(TAG,"onWait: ");}@Download.onPrepublicvoidonPre(DownloadTask task){Log.d(TAG,"onPre: ");}@Download.onTaskStartpublicvoidonTaskStart(DownloadTask task){Log.d(TAG,"onTaskStart: ");showToast("开始下载~~~~~");}@Download.onTaskRunningpublicvoidonTaskRunning(DownloadTask task){Log.d(TAG,"onTaskRunning: ");}@Download.onTaskResumepublicvoidonTaskResume(DownloadTask task){Log.d(TAG,"onTaskResume: ");}@Download.onTaskStoppublicvoidonTaskStop(DownloadTask task){Log.d(TAG,"onTaskStop: ");}@Download.onTaskCancelpublicvoidonTaskCancel(DownloadTask task){Log.d(TAG,"onTaskCancel: ");}@Download.onTaskFailpublicvoidonTaskFail(DownloadTask task,Exception e){Log.d(TAG,"onTaskFail: ");}@Download.onTaskCompletepublicvoidonTaskComplete(DownloadTask task){Log.d(TAG,"onTaskComplete: ");
        mBinding.download.setClickable(false);
        mBinding.download.setImageResource(R.mipmap.ic_download_complete);showToast("下载完成~~~~~");}privatevoiddownload(){if(null!= musicInfo){Aria.download(PlayMusicActivity.this).load(musicInfo.getMusic_url())// 下载地址.setFilePath(getExternalCacheDir().getPath()+ musicInfo.getMusic_title()+".mp3")// 设置文件保存路径.setExtendField(GsonUtils.toJson(musicInfo)).create();}}}

详情可私信哦~~~~~~


本文转载自: https://blog.csdn.net/jky_yihuangxing/article/details/127898359
版权归原作者 东晋谨慎的冬瓜 所有, 如有侵权,请联系我们删除。

“Android程序设计之音乐播放器实现”的评论:

还没有评论