赞
踩
基于MediaPlayer技术实现在线音乐播放器,播放在线音乐,后端使用SpringBoot将音乐存放在Tomcat服务器。app通过网络请求获取音乐,从而实现在线音乐播放。该项目分为用户端和管理员端
Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。
虽然服务是在后台运行的,但是Service和Activity都是运行在当前APP所在的main thread(UI主线程)中的,而耗时操作(如网络请求、拷贝数据、大文件)会阻塞主线程,给用户带来不好的体验。如果需要在服务中进行耗时操作,可以选择 IntentService,IntentService是Service的子类,用来处理异步请求。
创建Service直接在Android Studio中右键选择Service创建即可。默认我们所创建的Service是继承Service的。同时我们为了实现后台音乐播放的功能,所以我们还要实MediaPlayer.OnCompletionListener的接口。
同时还要在AndroidManifest.xml文件中对已经创建的Service进行注册,这一点Android Studio已经帮我们自动创建好了
(1)在Acitivity界面通过显式意图(或隐式意图)的方式来启动服务和关闭服务。
Intent intentService = new Intent(MainActivity.this, AudioService.class);
startService(intentService);
(2)bindService()绑定服务
当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
欢迎页
/** * 欢迎页 */ @SuppressLint("CustomSplashScreen") public class SplashActivity extends BaseActivity<ActivitySplashBinding> { @Override protected ActivitySplashBinding getViewBinding() { return ActivitySplashBinding.inflate(getLayoutInflater()); } @Override protected void setListener() { } @Override protected void initData() { new Handler(Looper.myLooper()).postDelayed(new Runnable() { @Override public void run() { startActivity(new Intent(mContext,LoginActivity.class)); finish(); } },800); } }
用户主页面
/** * 用户主页面 */ public class MainActivity extends BaseActivity<ActivityMainBinding> { private String[] titles = {"音乐推荐", "音乐分类"}; private List<Fragment> fragmentList = new ArrayList<>(); @Override protected ActivityMainBinding getViewBinding() { return ActivityMainBinding.inflate(getLayoutInflater()); } @Override protected void setListener() { mBinding.avatar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivityForResult(new Intent(MainActivity.this, MineActivity.class), 20002); } }); } @Override protected void initData() { if (ApiConstants.getUserInfo() != null) { mBinding.username.setText(ApiConstants.getUserInfo().getUsername()); } //造数据 fragmentList.add(new HomeFragment()); fragmentList.add(new TypeFragment()); // fragmentList.add(new RecordFragment()); //如果处理成懒加载的话,其实很简单,只要是这个方法setOffscreenPageLimit不去设置,就可以了。 // mBinding.viewPager.setOffscreenPageLimit(fragmentList.size()); mBinding.viewPager.setUserInputEnabled(false); mBinding.viewPager.setAdapter(new FragmentStateAdapter(this) { @NonNull @Override public Fragment createFragment(int position) { return fragmentList.get(position); } @Override public int getItemCount() { return fragmentList.size(); } }); mBinding.tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { mBinding.viewPager.setCurrentItem(tab.getPosition(), false); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(mBinding.tabs, mBinding.viewPager, new TabLayoutMediator.TabConfigurationStrategy() { @Override public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) { tab.setText(titles[position]); } }); //这句话很重要 tabLayoutMediator.attach(); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == 20002) { finish(); } } }
音乐播放界面
/** * 音乐播放界面 */ public class PlayMusicActivity extends BaseActivity<ActivityPlayMusicBinding> implements OnPlayerEventListener { private static final String TAG = "============"; private MusicInfo musicInfo; private int mLastProgress; @Override protected ActivityPlayMusicBinding getViewBinding() { return ActivityPlayMusicBinding.inflate(getLayoutInflater()); } @Override protected void setListener() { Aria.download(this).register(); mBinding.sbProgress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean b) { if (Math.abs(progress - mLastProgress) >= DateUtils.SECOND_IN_MILLIS) { mBinding.tvCurrentTime.setText(formatTime("mm:ss", progress)); mLastProgress = progress; } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (AudioPlayer.get().isPlaying() || AudioPlayer.get().isPausing()) { int progress = seekBar.getProgress(); AudioPlayer.get().seekTo(progress); } else { seekBar.setProgress(0); } } }); mBinding.ivMusicPlay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AudioPlayer.get().playPause(); } }); mBinding.ivMusicPrevious.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AudioPlayer.get().prev(); } }); mBinding.ivMusicNext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AudioPlayer.get().next(); } }); //下载 mBinding.download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (XXPermissions.isGranted(mContext, Permission.Group.STORAGE)) { download(); } else { checkPermission(); } } }); } @Override protected void initData() { 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); } } } /** * 沉浸式状态栏 */ private void initSystemBar() { ImmersionBar.with(this).init(); } public String formatTime(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") private void onChangeImpl(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(); } @Override public void onChange(MusicInfo music) { onChangeImpl(music); } @Override public void onPlayerStart(long duration) { //一定要设置最大值 mBinding.sbProgress.setMax((int) duration); mBinding.tvTotalTime.setText(formatTime("mm:ss", duration)); mBinding.ivMusicPlay.setSelected(true); startAnim(); } @Override public void onPlayerPause() { mBinding.ivMusicPlay.setSelected(false); stopAnim(); } @Override public void onPublish(int progress) { mBinding.sbProgress.setProgress(progress); } @Override public void onBufferingUpdate(int percent) { mBinding.sbProgress.setSecondaryProgress(mBinding.sbProgress.getMax() * 100 / percent); } private Animation animation; private void startAnim() { animation = AnimationUtils.loadAnimation(this, R.anim.rotation_animation); LinearInterpolator lin = new LinearInterpolator();//设置动画匀速运动 animation.setInterpolator(lin); mBinding.imgCd.startAnimation(animation); } private void stopAnim() { if (mBinding.imgCd.getAnimation() != null) { mBinding.imgCd.clearAnimation(); } } private void addRecord(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(new HttpStringCallback(null) { @Override protected void onSuccess(String msg, String response) { } @Override protected void onError(String response) { } }); } private void checkPermission() { XXPermissions.with(this) // 申请单个权限 // 申请多个权限 .permission(Permission.Group.STORAGE) // 设置权限请求拦截器(局部设置) //.interceptor(new PermissionInterceptor()) // 设置不触发错误检测机制(局部设置) //.unchecked() .request(new OnPermissionCallback() { @Override public void onGranted(List<String> permissions, boolean all) { if (!all) { showToast("获取部分权限成功,但部分权限未正常授予"); return; } //这里做操作 } @Override public void onDenied(List<String> permissions, boolean never) { if (never) { showToast("被永久拒绝授权,请手动授予录音和日历权限"); // 如果是被永久拒绝就跳转到应用权限系统设置页面 XXPermissions.startPermissionActivity(mContext, permissions); } else { showToast("获取录音和日历权限失败"); } } }); } @Download.onWait public void onWait(DownloadTask task) { Log.d(TAG, "onWait: "); } @Download.onPre public void onPre(DownloadTask task) { Log.d(TAG, "onPre: "); } @Download.onTaskStart public void onTaskStart(DownloadTask task) { Log.d(TAG, "onTaskStart: "); showToast("开始下载~~~~~"); } @Download.onTaskRunning public void onTaskRunning(DownloadTask task) { Log.d(TAG, "onTaskRunning: "); } @Download.onTaskResume public void onTaskResume(DownloadTask task) { Log.d(TAG, "onTaskResume: "); } @Download.onTaskStop public void onTaskStop(DownloadTask task) { Log.d(TAG, "onTaskStop: "); } @Download.onTaskCancel public void onTaskCancel(DownloadTask task) { Log.d(TAG, "onTaskCancel: "); } @Download.onTaskFail public void onTaskFail(DownloadTask task, Exception e) { Log.d(TAG, "onTaskFail: "); } @Download.onTaskComplete public void onTaskComplete(DownloadTask task) { Log.d(TAG, "onTaskComplete: "); mBinding.download.setClickable(false); mBinding.download.setImageResource(R.mipmap.ic_download_complete); showToast("下载完成~~~~~"); } private void download() { if (null != musicInfo) { Aria.download(PlayMusicActivity.this) .load(musicInfo.getMusic_url()) // 下载地址 .setFilePath(getExternalCacheDir().getPath() + musicInfo.getMusic_title() + ".mp3") // 设置文件保存路径 .setExtendField(GsonUtils.toJson(musicInfo)) .create(); } } }
详情可私信哦~~~~~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。