Android简易音乐重构MVVM Java版-解决播放界面旋转动画卡顿及播放异常崩溃问题(二十一)

Posted 雪の星空朝酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android简易音乐重构MVVM Java版-解决播放界面旋转动画卡顿及播放异常崩溃问题(二十一)相关的知识,希望对你有一定的参考价值。

android简易音乐重构MVVM Java版-解决播放界面旋转动画卡顿及播放异常崩溃问题(二十一)

关于

  本篇主要解决播放界面歌曲封面旋转不平滑问题及、部分歌曲需要在失败后调用获取音乐来源重新播放并添加进播放队列中,以及解决部分歌曲封面加载导致背景过亮看不清其余东西。ps(最近工作上比较忙,简易音乐的功能开发及博客项目编写更新频率会降低。)
  简易音乐app仅作为学习用,禁止用于商业及非法用途,如产生法律纠纷与本人无关

效果图

修改ApiService

 @GET("song/url") //获取歌曲信息
    LiveData<ApiResponse<SongEntity>> getSongUrl(@Query("id") long songUrl);

歌曲实体类SongEntity

@NoArgsConstructor
@Data
public class SongEntity 

    private List<DataEntity> data;
    private int code;

    @NoArgsConstructor
    @Data
    public static class DataEntity 
        private int id;
        private String url;
        private int br;
        private int size;
        private String md5;
        private int code;
        private int expi;
        private String type;
        private double gain;
        private int fee;
        private Object uf;
        private int payed;
        private int flag;
        private boolean canExtend;
        private Object freeTrialInfo;
        private String level;
        private String encodeType;
        private FreeTrialPrivilegeEntity freeTrialPrivilege;
        private FreeTimeTrialPrivilegeEntity freeTimeTrialPrivilege;
        private int urlSource;
        private int rightSource;

        @NoArgsConstructor
        @Data
        public static class FreeTrialPrivilegeEntity 
            private boolean resConsumable;
            private boolean userConsumable;
            private Object listenType;
        

        @NoArgsConstructor
        @Data
        public static class FreeTimeTrialPrivilegeEntity 
            private boolean resConsumable;
            private boolean userConsumable;
            private int type;
            private int remainTime;
        
    


修改播放界面

  修改activity_current_song_play.xml

<!--添加背景灰色值,降低图片亮度-->
<View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/grays_0350" />

  修改CurrentSongPlayActivity

public class CurrentSongPlayActivity extends BaseActivity 

    private ActivityCurrentSongPlayBinding binding;
    private ObjectAnimator rotationAnim;
    private MusicInfo musicInfo;
    private SongPlayViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        binding = ActivityCurrentSongPlayBinding.inflate(getLayoutInflater());
        viewModel = new ViewModelProvider(this).get(SongPlayViewModel.class);
        binding.setVm(viewModel);
        binding.setLifecycleOwner(this);
        setContentView(binding.getRoot());
        initView();
        initAnim();
        initObserver();
    

    private void initObserver() 
        viewModel.getLyric()
                .observe(this, lyricEntityApiResponse -> 
                    ViewExtensionKt.printLog("当前"+lyricEntityApiResponse.getMessage());
                    if (lyricEntityApiResponse.getStatus() == Status.SUCCESS)
                        if (lyricEntityApiResponse.getData().getLrc() != null)
                            if (lyricEntityApiResponse.getData().getTlyric() != null)
                                binding.lrc.loadLrc(lyricEntityApiResponse.getData().getLrc().getLyric(),lyricEntityApiResponse.getData().getTlyric().getLyric());
                            else 
                                binding.lrc.loadLrc(lyricEntityApiResponse.getData().getLrc().getLyric(),"");
                            
                        else 
                            binding.lrc.loadLrc("","");
                        
                    
                );
    

    private void initView() 
        musicInfo = getIntent().getParcelableExtra(MUSIC_INFO);
        initImageBg(musicInfo);
        initListener();
        binding.viewBody.setOnClickListener(view -> 
            if (ClickUtil.enableClick())
                viewModel.isShowLrc = !viewModel.isShowLrc;
                showLyrics(viewModel.isShowLrc);
            
        );
        //进度
        binding.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() 
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) 

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) 

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) 
                MusicPlay.seekTo(seekBar.getProgress(),true);
                binding.lrc.updateTime(seekBar.getProgress());
            
        );
        binding.ivPlayMode.setOnClickListener(v -> 
            if (ClickUtil.enableClick())
                changeRepeatMode();
            
        );
        binding.lrc.setListener(time -> 
            MusicPlay.seekTo(time,true);
            return true;
        );
        binding.lrc.setCoverChangeListener(()->
            viewModel.isShowLrc = false;
            showLyrics(false);
        );
        binding.ivList.setOnClickListener(view -> 
            //MusicPlay.getPlayList()
        );
        binding.ivPlay.setOnClickListener(v -> 
            if (MusicPlay.isPlaying())
                MusicPlay.pauseMusic();
                rotationAnim.pause();
            else 
                MusicPlay.restoreMusic();
                rotationAnim.resume();
            
        );
    

    private void initImageBg(MusicInfo musicInfo) 
        viewModel.currentSongUrl.set(musicInfo.getSongCover());
        RequestOptions options = new RequestOptions()
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .bitmapTransform(new BlurTransformation(25, 30));
        viewModel.currentSongId.set(Long.parseLong(musicInfo.getSongId()));
        initObserver();
        Glide.with(this)
                .asBitmap()
                .load(musicInfo.getSongCover())
                //.placeholder()
                .transition(BitmapTransitionOptions.withCrossFade(1500))
                .apply(options)
                .into(new SimpleTarget<Bitmap>() 
                    @Override
                    public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) 
                        Drawable drawable = ImageUtils.createBlurredImageFromBitmap(resource, 15);
                        binding.imgBc.setImageDrawable(drawable);
                        Palette.from(resource)
                                .setRegion(0,0,getScreenWidth(),getStatusBarHeight())
                                .maximumColorCount(6)
                                .generate(palette -> 
                                    Palette.Swatch mostPopularSwatch = null;
                                    for (Palette.Swatch swatch: palette.getSwatches())
                                        if (mostPopularSwatch == null
                                        || swatch.getPopulation() > mostPopularSwatch.getPopulation())
                                            mostPopularSwatch = swatch;
                                        
                                    
                                    if (mostPopularSwatch!= null)
                                        double luminance =ColorUtils.calculateLuminance(mostPopularSwatch.getRgb());
                                        // 当luminance小于0.5时,我们认为这是一个深色值.
                                        if (luminance < 0.5)
                                             setDarkStatusBar();
                                        else 
                                            setLightStatusBar();
                                        
                                    
                                );
                        StatusBarUtil.setTranslucentForImageView(CurrentSongPlayActivity.this,0,binding.viewTitleBg);
                    
                );
        binding.tvTitle.setText(musicInfo.getSongName());
        binding.tvSinger.setText(musicInfo.getArtist());
    

    private int getScreenWidth()
        DisplayMetrics displayMetrics =new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.widthPixels;
    

    private int getStatusBarHeight()
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0)
            result = getResources().getDimensionPixelSize(resourceId);
        
        return result;
    

    private void initListener() 
        MusicPlay.onPlayStateListener(this, new OnMusicPlayStateListener() 
            @Override
            public void onPlayState(@NonNull PlayManger playManger) 
                switch (playManger.getStage())
                    case PlayManger.PAUSE:
                    case PlayManger.IDLE:
                        rotationAnim.pause();
                        binding.ivPlay.setImageResource(R.drawable.shape_play_white);
                        break;
                    case PlayManger.PLAYING:
                        resumeRotateAnimation();
                        binding.ivPlay.setImageResource(R.drawable.shape_pause_white);
                        break;
                    case PlayManger.BUFFERING:
                        ViewExtensionKt.printLog("缓冲");
                        break;
                    case PlayManger.SWITCH:
                        if (playManger.getSongInfo() != null)
                            initImageBg(playManger.getSongInfo());
                        
                        break;
                    case PlayManger.ERROR:
                        //获取当前歌曲播放失败的歌曲信息 
                        MusicInfo musicInfo = playManger.getSongInfo();
                        int index = MusicPlay.getNowPlayingIndex();             
                        viewModel.getSongInfo(Long.parseLong(playManger.getSongInfo().getSongId()))
                                .observe(CurrentSongPlayActivity.this, songEntityApiResponse -> 
                                    if (songEntityApiResponse.getStatus() == Status.SUCCESS)
                                        if (songEntityApiResponse.getData().getData()!= null && songEntityApiResponse.getData().getData().get(0).getUrl() != null)
                                            musicInfo.setSongUrl(songEntityApiResponse.getData().getData().get(0).getUrl());
                                            MusicPlay.addSongInfo(musicInfo,index);
                                            MusicPlay.playMusicByInfo(musicInfo);
                                        else 
                                            //歌曲无版权
                                            ToastUtils.show(getString(R.string.no_copyright));
                                            MusicPlay.removeSongInfoById(playManger.getSongInfo().getSongId());
                                        
                                    
                                );
                        break;

                
            
        );
        MusicPlay.onPlayProgressListener(new OnMusicPlayProgressListener() 
            @Override
            public void onPlayProgress(long curP, long duration) 
                if (binding.seekBar.getMax() != duration)
                    binding.seekBar.setMax((int) duration);
                    binding.tvTotalTime.setText(TimeUtil.getTimeNoYMDH(duration));
                
                binding.tvPastTime.setText(TimeUtil.getTimeNoYMDH(curP));
                binding.lrc.updateTime(curP);
                binding.seekBar.setProgress((int) curP);
            
        );
    

    //

以上是关于Android简易音乐重构MVVM Java版-解决播放界面旋转动画卡顿及播放异常崩溃问题(二十一)的主要内容,如果未能解决你的问题,请参考以下文章

Android简易音乐重构MVVM Java版-新增启动动画

Android简易音乐重构MVVM Java版-新增推荐菜单及侧边栏展示

Android简易音乐重构MVVM Java版-BottomNavigationView+viewpager主界面结构

Android简易音乐重构MVVM Java版-新增推荐雷达歌单详情列表界面(十八)

Android简易音乐重构MVVM Java版-新增推荐雷达歌单详情列表界面(十八)

Android简易音乐重构MVVM Java版-新增歌曲播放界面+状态栏黑科技(十七)