Giter Site home page Giter Site logo

kunminx / jetpack-musicplayer Goto Github PK

View Code? Open in Web Editor NEW
821.0 14.0 106.0 9.06 MB

Json 数据驱动,音乐播放组件

Java 85.92% HTML 14.08%
android jetpack jetpack-android livedata music music-player musicplayer music-library music-composition androidx media controller

jetpack-musicplayer's Introduction

 

由来

Jetpack-MusicPlayer 是一款基于 Jetpack MVVM 架构音乐播放控制组件,它是因 “Jetpack-MVVM-Best-Practice” 这项目需求而存在。

最初寻遍 GitHub 也未找到合适开源库,于是另起炉灶,自己编写 高度解耦、轻松配置、可通过 Maven 仓库远程依赖 的真正第三方库。

Jetpack-MusicPlayer 使用十分简单,依托于 设计模式原则 及 Java 泛型特性,使用者无需知道内部实现细节,仅通过继承 Album、Music、Artist 基类 即可完成 “业务实体类” 定制和扩展

此外,在不设置自定义配置情况下,Jetpack-MusicPlayer 最少只需 一行代码即可运行起来

 

PureMusic Dispatcher PlayMode Switch

 

目标

Jetpack-MusicPlayer 目标是:一行代码即可接入 音乐播放控制组件

除一键接入省去 99% 繁杂重复工作外,你还可从该项目获得内容包括:

  • 整洁代码风格 和 标准资源命名规范。
  • 遵循 "响应式编程" 开发模式的 Dispatcher 使用,
  • 优秀代码分层和封装**,在不做任何个性化配置情况下,一行代码即可接入。
  • 主体工程基于前沿软件工程安全 JetPack MVVM 架构。
  • AndroidX 和 Material Design 2 全面使用。
  • ConstraintLayout 约束布局最佳实践。
  • 绝不使用 Dagger,绝不使用奇技淫巧、编写艰深晦涩代码。

 

如你正在思考 如何为项目挑选合适的架构,这项目值得你参考!

 

 

简单使用:

1.在 build.gradle 中添加依赖。

implementation 'com.kunminx.player:player:5.2.0'

提示:本库托管于 Maven Central,请自行在根目录 build.gradle 添加 mavenCentral()

2.依据默认专辑实体类 DefaultAlbum 结构准备一串数据。此处以 JSON 为例:

// DefaultAlbum 包含 DefaultMusic 和 DefaultArtist 两个子类:
// 三者的字段可详见 BaseAlbumItem、BaseMusicItem 和 BaseArtistItem。
{
  "albumId": "JAY_008",
  "title": "依然范特西",
  "summary": "Still Fantasy",
  "artist": {
    "name": "Jay"
  },
  "coverImg": "https://...57036-570ed96eb055ef17.png",
  "musics": [
    {
      "musicId": "JAY_008_001",
      "title": "本草纲目",
      "artist": {
        "name": "Jay"
      },
      "coverImg": "https://.../57036-570ed96eb055ef17.png",
      "url": "bencaogangmu.mp3"
    },
    ...
  ]
}

3.在 Application 中初始化 多媒体播放控制组件。

DefaultPlayerManager.getInstance().init(this);

4.在得到数据后,最少只需一行代码 即可完成数据的装载。

//一行代码完成数据的初始化。
DefaultPlayerManager.getInstance().loadAlbum(album);

 

温馨提示:

1.实际开发中,项目数据或与本库数据 “结构上存在差异”,故通常做法是,从后端拿到和解析项目 JSON 数据,并对该数据进行遍历。在遍历过程中,实例化并装载 “本库实体类对象” 到列表中,以获本库所能使用的列表数据。

2.注意:如后端直接使用本库实体类读写 JSON 数据,请在 ProGuard Rules 中为该实体类配置混淆白名单:

-keep class com.kunminx.player.bean.** {*;}

 

更多

"播放控制" 及 "个性化配置" 等,详见 Wiki

 

Thanks to

material-components-android

AndroidX

ExoPlayer

AndroidVideoCache

 

My Pages

Email:[email protected]

Juejin:KunMinX 在掘金

 

License

Copyright 2018-present KunMinX

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

jetpack-musicplayer's People

Contributors

kunminx avatar theoneee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jetpack-musicplayer's Issues

【建议】关于PlayerController里的几个事件分发将setValue更改为postValue

这里的几个事件:

  private final MutableLiveData<ChangeMusic> changeMusicLiveData = new MutableLiveData<>();
  private final MutableLiveData<PlayingMusic> playingMusicLiveData = new MutableLiveData<>();
  private final MutableLiveData<Boolean> pauseLiveData = new MutableLiveData<>();
  private final MutableLiveData<Enum> playModeLiveData = new MutableLiveData<>();

在分发时都是使用的setValue,但是我在项目里的音频资源来自网络,在进行PlayerManager.getInstance().loadAlbum(album, 0)时会耗一些时间造成界面会卡一下,网络不好时甚至更会出现ANR,所以我将此方法放入了子线程,把里面的事件分发更改为postValue(),这样是不是更好一点,这样无论在子线程还是主线程能能使用。

测试音频

https://ws.stream.qqmusic.qq.com/C400003nGa8A3ysktw.m4a?guid=3710892&vkey=D9C0E0E81420C49A1B5346C3F6BF0A832DBE61A32F6E990C4C95A0EB0F17D91B58550AE7D018DF8EEBA47DAAE11CCE398531632F3A77D8AD&uin=626567678&fromtag=143

将移动网络调为3G测试网络慢的情况。

MediaPlayerHelper里去掉对格式的判断

  public boolean play(final String localPathOrURL) {
   //if (!checkAvalable(localPathOrURL)) {
   //   return false;
   //}
   ...
  }

MainFragment对资源进行替换:

mState.musicRequest.getFreeMusicsLiveData().observe(getViewLifecycleOwner(), dataResult -> {
      if (!dataResult.getResponseStatus().isSuccess()) return;
      TestAlbum musicAlbum = dataResult.getResult();
      for(TestAlbum.TestMusic music:musicAlbum.getMusics()){
        music.setUrl(URL);
      }
      .....
    });

如果这样,那么是否需要对格式进行判断,或者向外曝露一个额外的判断接口,是不是更好呢。

一直点击列表卡顿之后崩溃切换音乐崩溃

java.lang.RuntimeException: Unable to start service com.kunminx.puremusic.player.notification.PlayerService@b6f7781 with Intent { cmp=com.kunminx.puremusic.debug/com.kunminx.puremusic.player.notification.PlayerService }: java.lang.IllegalStateException: Pid 2142 has exceeded the number of permissibleregistered listeners. Ignoring request to add.
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4186)
at android.app.ActivityThread.access$1900(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1933)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:226)
at android.app.ActivityThread.main(ActivityThread.java:7592)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.IllegalStateException: Pid 2142 has exceeded the number of permissibleregistered listeners. Ignoring request to add.
at android.os.Parcel.createException(Parcel.java:2082)
at android.os.Parcel.readException(Parcel.java:2042)
at android.os.Parcel.readException(Parcel.java:1990)
at com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy.listenForSubscriber(ITelephonyRegistry.java:1056)
at android.telephony.TelephonyManager.listen(TelephonyManager.java:5087)
at com.kunminx.puremusic.player.helper.PlayerCallHelper.bindCallListener(PlayerCallHelper.java:80)
at com.kunminx.puremusic.player.notification.PlayerService.onStartCommand(PlayerService.java:96)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4165)
at android.app.ActivityThread.access$1900(ActivityThread.java:229) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1933) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:226) 
at android.app.ActivityThread.main(ActivityThread.java:7592) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.TelephonyRegistry.add(TelephonyRegistry.java:957)
at com.android.server.TelephonyRegistry.listen(TelephonyRegistry.java:671)
at com.android.server.TelephonyRegistry.listenForSubscriber(TelephonyRegistry.java:640)
at com.android.internal.telephony.ITelephonyRegistry$Stub.onTransact(ITelephonyRegistry.java:428)
at android.os.Binder.execTransactInternal(Binder.java:1024)

【 提问须知 】

如有 bug,请另外 new 一个 issue ⚠️⚠️⚠️

本项目开 issue 规范:

  1. 有任何 bug 都欢迎及时开 issue,我看到后予以处理。
  2. 如有使用上的疑问,请先认真阅读 Readme 和源码 sample,在没有找到答案后,另外开 issue。
  3. 如开 issue 是为了发表个人见解,请务必 客观、具体、严谨;严禁草率、乱入、带节奏:

务必注明观点所对应的场景,并附上完整可复现的代码,

不然缺乏一致的前提依据来有效交流!

任何缺乏实证依据和因果逻辑的泛泛而谈,都可能对其他使用者造成困扰。

在发表个人见解前,请先确保自己认真阅读过源码。这是对自己、对作者、对其他读者最起码的尊重。

请问再重复 播放 再调用暂停的方法 会导致 程序会变得很卡的情况 logcat上一直报这个错误

MediaPlayerNative: error (-38, 0)
MediaPlayerNative: [notify] : [1170] callback app listenerNotNull=1, send=1
MediaPlayer: [HSM] stayAwake false uid: 10759, pid: 28843
MediaPlayerNative: stop called in state 0, mPlayer(0xc0cbf8e0)
MediaPlayerNative: Message: MEDIA_ERROR(100), ext1=Unknown MediaErrorType(-38), ext2=0x0
MediaPlayerNative: error (-38, 0)
MediaPlayerNative: [notify] : [1170] callback app listenerNotNull=1, send=1
。。。
一直重复的报这个 是什么原因额

代码中就写了获取当前播放音频getCurrentPlayingMusic() 的url 一致就调用pauseAudio() 方法

【优化】切换歌曲后第一时间的播放进度会被上一首数据污染

现在当前播放的数据是只有一个实例:

private PlayingMusic mCurrentPlay = new PlayingMusic("00:00", "00:00");

但是当切换歌曲时,只是更换了部分播放数据:

   public void setChangingPlayingMusic(boolean changingPlayingMusic) {
        mIsChangingPlayingMusic = changingPlayingMusic;
        if (mIsChangingPlayingMusic) {
            ...
            mCurrentPlay.setBaseInfo(mPlayingInfoManager.getMusicAlbum(), getCurrentPlayingMusic());
           ....
        }
    }

    public void setBaseInfo(B musicAlbum, M music) {
        //要用当前实际播放的列表,因为不同模式存在不同的播放列表
        this.title = music.getTitle();
        this.summary = musicAlbum.getSummary();
        this.albumId = musicAlbum.getAlbumId();
        this.musicId = music.getMusicId();
        this.img = music.getCoverImg();
        this.artist = (A) music.getArtist();
        this.music = music;
    }

这个时候的播放进度和时间是没有被重置的,分发当前播放音乐消息时会把上一首的播放数据也带过去,造成数据污染,
建议在更换歌曲时重置一下播放进度和时间:

   public void setChangingPlayingMusic(boolean changingPlayingMusic) {
        mIsChangingPlayingMusic = changingPlayingMusic;
        if (mIsChangingPlayingMusic) {
             // 重置播放时间和进度数据
            mCurrentPlay.setNowTime("00:00");
            mCurrentPlay.setAllTime("00:00");
            mCurrentPlay.setPlayerPosition(0);
            mCurrentPlay.setDuration(0);
            mCurrentPlay.setBaseInfo(mPlayingInfoManager.getMusicAlbum(), getCurrentPlayingMusic());
           ....
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.