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

这篇具有很好参考价值的文章主要介绍了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 = new Intent(MainActivity.this, AudioService.class);
 startService(intentService);

(2)bindService()绑定服务

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


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

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


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

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


3.部分核心代码实现

欢迎页

/**
 * 欢迎页
 */
@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();

        }
    }

}

详情可私信哦~~~~~~文章来源地址https://www.toymoban.com/news/detail-444330.html

到了这里,关于Android程序设计之音乐播放器实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于微信小程序的音乐播放器的设计与开发(源码+lw+部署文档+讲解等)

    💗 博主介绍 :✌新人博主,工作经验两年+、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码+数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人 随着移动互联网的快速发展,音

    2024年02月04日
    浏览(37)
  • 【计算机毕业设计】nodejs+vue音乐播放器系统 微信小程序83g3s

    本系统的设计与实现共包含12个表:分别是配置文件信息表,音乐列表评论表信息表,音乐论坛信息表,歌手介绍信息表,音乐资讯信息表,收藏表信息表,token表信息表,用户表信息表,音乐类型信息表,音乐列表信息表,音乐专辑信息表,用户信息表, 使用Spring作为项目管

    2024年02月04日
    浏览(41)
  • 82、基于stm32单片机音乐喷泉设计播放器频谱彩灯系统设计(程序+原理图+参考论文+开题报告+任务书+设计资料+元器件清单等)

    随着人们生活水平的提高和建立绿色城市的向往,音乐喷泉以其独特的魅力和特殊的功能,愈来愈成为休闲娱乐产业中的一项重要产品,音乐喷泉的兴建也越来越多。 根据目前音乐喷泉的发展现状,介绍了一个以STM32单片机为核心的小型音乐喷泉控制系统。给出了一个简洁的单

    2024年02月12日
    浏览(119)
  • 基于android音乐播放器的设计

    本科毕业论文(设计)诚信声明 本人郑重声明:所呈交的毕业论文(设计),题目《………基于android音乐播放器的设计……………………………》是本人在指导教师的指导下,进行研究工作所取得的成果。对本文的研究作出重要贡献的个人和集体,均已在文章以明确方式注

    2024年02月03日
    浏览(45)
  • Android课程设计大作业-音乐播放器

    1)使用Service播放音乐 Android SDK提供了Service。Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Remote Sercie):用于Android系统内部的应用程序之间前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单

    2024年02月10日
    浏览(40)
  • Android手机开发课程设计之音乐播放器

    一、音乐播放器概述与分析 目前手机的音乐播放功能已经是大家比较关注的一个部分,不少在人在购买手机的时候都会关心手机的音乐播放的能力,这也足以看出目前大家对音乐播放功能的重视,所以一款性能良好的手机音乐播放器软件一定会受到欢迎。和传统的音乐播放器

    2024年02月05日
    浏览(51)
  • Android 音乐播放器

    ◼ 音乐播放器 . ◼ 要求 : Activity 编程、 ListView 编程、 SeekBar 编程、 ExoPlayer 编程( 播放 、 暂停 、 停止 、 上一首 、 下一首 ),音乐文件放在 assets/music 目录下,界面自拟. ◼ 期望最终效果: ◼ 分别对应 activity_music_list.xml 、 activity_my_music_player.xml 的视图. ◼ 点击列表任

    2024年02月03日
    浏览(55)
  • Android开发之音乐播放器

    我们大家平时长时间打代码的时候肯定会感到疲惫和乏味,这个时候一边播放自己喜欢的音乐,一边继续打代码,心情自然也愉快很多。音乐带给人的听觉享受是无可比拟的,动听的音乐可以愉悦人的身心,让人更加积极地去热爱生活。接下来就教大家如何用Android Studio自己

    2024年02月08日
    浏览(49)
  • Android Studio 实现音乐播放器

    🍅 文章末尾有获取完整项目源码方式 🍅         Android初学者开发第一个完整的实例项目应该就属《音乐播放器》了,项目包含SQLlit数据库的使用、listview、Fragment、等。话不多说先上成品: Android Studio 音乐播放器 图片效果展示: 1.启动页效果 2.登录页效果 3.注册页效果

    2024年02月06日
    浏览(45)
  • 小项目开发——Android 音乐播放器

    ◼ 音乐播放器 . ◼ 要求 : Activity 编程、 ListView 编程、 SeekBar 编程、 ExoPlayer 编程( 播放 、 暂停 、 停止 、 上一首 、 下一首 ),音乐文件放在 assets/music 目录下,界面自拟. ◼ 期望最终效果: ◼ 分别对应 activity_music_list.xml 、 activity_my_music_player.xml 的视图. ◼ 点击列表任

    2024年01月21日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包