├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ ├── card.json │ ├── dynamic.json │ ├── hglo1.ogg │ ├── hglo2.ogg │ ├── hglo3.ogg │ ├── hglo4.ogg │ ├── hglo5.ogg │ ├── hglo6.ogg │ ├── hglo7.ogg │ ├── hglo8.ogg │ ├── home.json │ └── user.json │ ├── java │ └── com │ │ └── lzx │ │ └── musiclib │ │ ├── Ext.kt │ │ ├── HomeActivity.kt │ │ ├── LifecycleUtils.kt │ │ ├── NotificationReceiver.kt │ │ ├── SpConstant.kt │ │ ├── TestApplication.kt │ │ ├── adapter │ │ ├── EfficientAdapter.kt │ │ ├── EfficientAdapterExt.kt │ │ └── ViewHolderCreator.kt │ │ ├── base │ │ └── BaseFragment.kt │ │ ├── card │ │ ├── CardActivity.kt │ │ ├── CardAdapter.kt │ │ └── CardFragment.kt │ │ ├── dynamic │ │ ├── DynamicActivity.kt │ │ ├── DynamicAdapter.kt │ │ ├── DynamicDetailActivity.kt │ │ └── DynamicFragment.kt │ │ ├── effect │ │ ├── EffectActivity.kt │ │ ├── EqualizerBandView.kt │ │ ├── VerticalSeekBar.java │ │ └── VerticalSeekBarWrapper.java │ │ ├── home │ │ ├── MainActivity.kt │ │ ├── PlayDetailActivity.kt │ │ └── TestActivity.kt │ │ ├── http │ │ ├── QQMusicApi.kt │ │ └── RetrofitClient.kt │ │ ├── user │ │ ├── UserAdapter.kt │ │ └── UserInfoActivity.kt │ │ ├── viewmodel │ │ └── MusicViewModel.kt │ │ └── weight │ │ ├── CustomTabEntity.java │ │ ├── CustomTabLayout.kt │ │ ├── DonutProgress.kt │ │ ├── GalleryItemDecoration.kt │ │ ├── MomentAudioView.kt │ │ ├── MsgView.java │ │ ├── OnTabSelectListener.java │ │ ├── Spanny.java │ │ ├── SpectrumDrawView.kt │ │ ├── SquareImageView.kt │ │ ├── SquareView.kt │ │ └── ViewPagerLayoutManager.kt │ └── res │ ├── anim │ ├── popup_bottom_enter.xml │ └── popup_bottom_exit.xml │ ├── drawable-xxhdpi │ ├── afb.png │ ├── b0c.png │ ├── b6e.png │ ├── ba1.png │ ├── bt_playpage_button_clock_normal_new.png │ ├── bt_playpage_loop_press.png │ ├── dy_bg.png │ ├── gdt_ic_express_pause.png │ ├── gdt_ic_express_play.png │ ├── gdt_ic_pause.png │ ├── gdt_ic_play.png │ ├── ic_accompaniment.png │ ├── ic_arrow_drop_down.png │ ├── ic_close.png │ ├── ic_danqu.png │ ├── ic_live_red_playing1.png │ ├── ic_live_red_playing2.png │ ├── ic_live_red_playing3.png │ ├── ic_live_red_playing4.png │ ├── ic_live_red_playing5.png │ ├── ic_next_song.png │ ├── ic_pre_song.png │ ├── ic_shunji.png │ ├── ic_shunxu.png │ ├── ic_songlist.png │ ├── ic_speed.png │ ├── ic_user.png │ ├── ic_variable_speed.png │ ├── ic_volume.png │ ├── icon_bar_close.png │ ├── icon_dynamic_top_next.png │ ├── icon_dynamic_top_play.png │ ├── icon_dynamic_top_stop.png │ ├── icon_dynamic_voice_loading.png │ ├── moment_audio_view_pause.png │ ├── moment_audio_view_play.png │ ├── note_btn_close.png │ ├── notify_btn_dark_favorite_normal.png │ ├── notify_btn_dark_lyrics_normal.png │ ├── notify_btn_dark_next_pressed.png │ ├── notify_btn_dark_pause_normal.png │ ├── notify_btn_dark_play_normal.png │ ├── notify_btn_dark_prev_pressed.png │ ├── notify_btn_favorite_checked.png │ ├── notify_btn_light_favorite_normal.png │ ├── notify_btn_light_lyrics_normal.png │ ├── notify_btn_light_next_pressed.png │ ├── notify_btn_light_pause_normal.png │ ├── notify_btn_light_play_normal.png │ ├── notify_btn_light_prev_pressed.png │ ├── notify_btn_lyrics_checked.png │ ├── recordfinish.png │ └── rerecord.png │ ├── drawable │ ├── anim_playing.xml │ ├── anim_round_rotate.xml │ ├── bg_button_36dp.xml │ ├── bg_equalizer_band_item.xml │ ├── bg_play_detail.xml │ ├── bg_spinner.xml │ ├── ic_singer_more.xml │ ├── notify_btn_dark_next_selector.xml │ ├── notify_btn_dark_pause_selector.xml │ ├── notify_btn_dark_play_selector.xml │ ├── notify_btn_dark_prev_selector.xml │ ├── notify_btn_light_next_selector.xml │ ├── notify_btn_light_pause_selector.xml │ ├── notify_btn_light_play_selector.xml │ ├── notify_btn_light_prev_selector.xml │ ├── progress_equalizer_band.xml │ ├── seek_bar_pro.xml │ ├── seek_bar_thumb.xml │ ├── shape_bg_dialog.xml │ └── shape_round_black.xml │ ├── layout │ ├── activiity_dynamic_detail.xml │ ├── activity_card.xml │ ├── activity_dynamic.xml │ ├── activity_effect.xml │ ├── activity_home.xml │ ├── activity_main.xml │ ├── activity_play_detail.xml │ ├── activity_test.xml │ ├── activity_user.xml │ ├── dialog_song_list.xml │ ├── fragment_card.xml │ ├── fragment_dynamic.xml │ ├── item_card.xml │ ├── item_dialog_song_list.xml │ ├── item_dynamic.xml │ ├── item_equalizer_band.xml │ ├── item_home_music.xml │ ├── item_preset.xml │ ├── item_user.xml │ ├── layout_moment_audio_view.xml │ ├── slide_layout_tab.xml │ ├── view_notify_big_play.xml │ └── view_notify_play.xml │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-v19 │ └── style.xml │ ├── values-v21 │ └── style.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── sliding_tab_attrs.xml │ ├── strings.xml │ └── styles.xml ├── art ├── StarrySky流程图.png ├── WechatIMG1.jpeg ├── a4074094959_10.jpg ├── biaoqing.gif ├── logo.jpg ├── notification1.png ├── notification2.png ├── notification3.png ├── notification4.png ├── qq_qun.jpg ├── 成功案例.png └── 成功案例副本.png ├── build.gradle ├── docs ├── .nojekyll ├── README.md ├── Service相关配置.md ├── SoundPool.md ├── _sidebar.md ├── index.html ├── 介绍.md ├── 全局拦截器.md ├── 其他配置.md ├── 多实例播放器.md ├── 播放相关api介绍.md ├── 缓存.md ├── 通知栏.md └── 音效相关.md ├── extension-flac2120 ├── .gitignore ├── README.md ├── build.gradle ├── consumer-rules.pro ├── libs │ ├── arm64-v8a │ │ └── libflacJNI.so │ ├── armeabi-v7a │ │ └── libflacJNI.so │ ├── x86 │ │ └── libflacJNI.so │ └── x86_64 │ │ └── libflacJNI.so ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── lzx │ └── extension_flac2120 │ ├── FlacBinarySearchSeeker.java │ ├── FlacDecoder.java │ ├── FlacDecoderException.java │ ├── FlacDecoderJni.java │ ├── FlacExtractor.java │ ├── FlacLibrary.java │ └── LibflacAudioRenderer.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── starrysky ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── com │ └── lzx │ └── starrysky │ ├── AppLifecycleCallback.kt │ ├── OnPlayerEventListener.kt │ ├── SongInfo.kt │ ├── StarrySky.kt │ ├── StarrySkyInstall.kt │ ├── StarrySkyPlayer.kt │ ├── cache │ ├── ExoCache.kt │ └── ICache.kt │ ├── control │ ├── PlayerControl.kt │ ├── RepeatMode.kt │ └── VoiceEffect.kt │ ├── intercept │ ├── InterceptorService.kt │ └── StarrySkyInterceptor.kt │ ├── manager │ ├── MediaSessionManager.kt │ ├── PlaybackManager.kt │ └── PlaybackStage.kt │ ├── notification │ ├── CustomNotification.kt │ ├── INotification.kt │ ├── NotificationConfig.kt │ ├── NotificationManager.kt │ ├── SystemNotification.kt │ ├── imageloader │ │ ├── DefaultImageLoader.kt │ │ └── ImageLoader.kt │ └── utils │ │ ├── NotificationColorUtils.kt │ │ └── NotificationUtils.kt │ ├── playback │ ├── ExoPlayback.kt │ ├── FocusManager.kt │ ├── Playback.kt │ └── SoundPoolPlayback.kt │ ├── queue │ ├── MediaQueueManager.kt │ └── MediaSourceProvider.kt │ ├── service │ ├── MusicService.kt │ ├── MusicServiceBinder.kt │ └── WifiLockHelper.kt │ └── utils │ ├── CommExt.kt │ ├── KtPreferences.kt │ ├── MD5.java │ ├── MainLooper.kt │ ├── StarrySkyConstant.kt │ └── TimerTaskManager.kt └── res ├── drawable-nodpi └── default_art.png ├── drawable-xxhdpi ├── ic_notification.png ├── ic_pause_white_24dp.png ├── ic_play_arrow_white_24dp.png ├── ic_skip_next_white_24dp.png └── ic_skip_previous_white_24dp.png ├── values └── strings.xml └── xml ├── allowed_media_browser_callers.xml ├── automotive_app_desc.xml └── network_security_config.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 lizixian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A Powerful and Streamline MusicLibrary 2 | 3 | [ ![](https://img.shields.io/badge/platform-android-green.svg) ](http://developer.android.com/index.html) 4 | [![](https://jitpack.io/v/EspoirX/StarrySky.svg)](https://jitpack.io/#EspoirX/StarrySky) 5 | [ ![](https://img.shields.io/badge/license-MIT-green.svg) ](http://choosealicense.com/licenses/mit/) 6 | 7 | 8 | 9 | 10 | 打包有问题,先用着v2.6.7或者用源码,暂时没心情维护,大家可自己修改,很简单的。 11 | 12 | # StarrySky 13 | 14 | `StarrySky` `MusicLibrary` `Music` `音频集成` 15 | 16 | 17 | 一个丰富,舒服的音乐播放封装库,针对快速集成音频播放功能,减少大家搬砖的时间,你值得拥有。 18 | 19 | [项目文档](https://espoirx.github.io/StarrySky/#/) 20 | 21 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdkVersion 31 8 | defaultConfig { 9 | applicationId "com.lzx.starrysky" 10 | minSdkVersion 16 11 | targetSdkVersion 31 12 | versionCode 1 13 | versionName "1.0" 14 | multiDexEnabled true 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | 23 | lintOptions { 24 | abortOnError false 25 | } 26 | 27 | compileOptions { 28 | sourceCompatibility 1.8 29 | targetCompatibility 1.8 30 | } 31 | 32 | dependencies { 33 | implementation fileTree(dir: 'libs', include: ['*.jar']) 34 | //noinspection GradleCompatible 35 | implementation 'com.android.support:appcompat-v7:28.0.0' 36 | implementation "com.android.support:design:28.0.0" 37 | implementation 'androidx.constraintlayout:constraintlayout:2.0.3' 38 | implementation 'com.github.bumptech.glide:glide:4.11.0' 39 | implementation "com.squareup.okhttp3:okhttp:4.1.0" 40 | 41 | implementation "com.squareup.retrofit2:retrofit:2.9.0" 42 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0' 43 | implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0' 44 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9" 45 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" 46 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0-beta01" 47 | 48 | implementation project(':starrysky') 49 | // implementation 'com.github.EspoirX:StarrySky:v2.6.3' 50 | 51 | implementation 'com.google.android.exoplayer:exoplayer-hls:2.14.1' 52 | implementation 'com.google.android.exoplayer:extension-rtmp:2.14.1' 53 | implementation 'com.google.android.exoplayer:exoplayer-dash:2.14.1' 54 | implementation 'com.google.android.exoplayer:exoplayer-smoothstreaming:2.14.1' 55 | 56 | implementation 'com.qw:soulpermission:1.3.0' 57 | implementation 'com.danikula:videocache:2.7.1' 58 | implementation 'com.bigkoo:convenientbanner:2.1.5' 59 | implementation 'com.gcssloop.widget:rclayout:1.8.1' 60 | implementation 'com.mikhaellopez:circularimageview:4.2.0' 61 | implementation 'com.noober.background:core:1.6.5' 62 | implementation 'com.afollestad.material-dialogs:core:3.3.0' 63 | implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0' 64 | 65 | implementation 'com.tencent.bugly:crashreport:3.1.0' 66 | implementation 'com.tencent.bugly:nativecrashreport:3.7.1' 67 | 68 | implementation "com.github.ssseasonnn.RxDownload:rxdownload4:1.0.9" 69 | implementation 'com.github.Lundez:Croller:1.0.3' 70 | } 71 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | # ServiceLoader support 23 | -keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {} 24 | -keepnames class kotlinx.coroutines.CoroutineExceptionHandler {} 25 | -keepnames class kotlinx.coroutines.android.AndroidExceptionPreHandler {} 26 | -keepnames class kotlinx.coroutines.android.AndroidDispatcherFactory {} 27 | 28 | # Most of volatile fields are updated with AFU and should not be mangled 29 | -keepclassmembernames class kotlinx.** { 30 | volatile ; 31 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/assets/hglo1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo1.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo2.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo3.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo3.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo4.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo4.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo5.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo5.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo6.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo6.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo7.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo7.ogg -------------------------------------------------------------------------------- /app/src/main/assets/hglo8.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/assets/hglo8.ogg -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/HomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import com.lzx.musiclib.home.MainActivity 6 | import com.lzx.musiclib.home.TestActivity 7 | import com.lzx.starrysky.StarrySky 8 | import kotlinx.android.synthetic.main.activity_home.btn1 9 | import kotlinx.android.synthetic.main.activity_home.btn2 10 | 11 | class HomeActivity : AppCompatActivity() { 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | setContentView(R.layout.activity_home) 15 | btn1.setOnClickListener { navigationTo() } 16 | btn2.setOnClickListener { navigationTo() } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/LifecycleUtils.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib 2 | 3 | import android.content.Context 4 | import androidx.lifecycle.LifecycleObserver 5 | import androidx.lifecycle.LifecycleOwner 6 | 7 | object LifecycleUtils { 8 | /** 9 | * 添加观察 10 | */ 11 | fun addObserver(context: Context?, observer: LifecycleObserver?) { 12 | if (context is LifecycleOwner) { 13 | val owner = context as LifecycleOwner? 14 | owner?.lifecycle?.addObserver(observer!!) 15 | } 16 | } 17 | 18 | /** 19 | * 移除订阅 20 | */ 21 | fun removeObserver(context: Context?, observer: LifecycleObserver?) { 22 | if (context is LifecycleOwner) { 23 | val owner = context as LifecycleOwner? 24 | owner?.lifecycle?.removeObserver(observer!!) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/NotificationReceiver.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import com.lzx.starrysky.SongInfo 7 | import com.lzx.starrysky.StarrySky 8 | import com.lzx.starrysky.utils.getTargetClass 9 | 10 | 11 | /** 12 | * 处理通知栏点击的广播 13 | */ 14 | class NotificationReceiver : BroadcastReceiver() { 15 | override fun onReceive(context: Context?, intent: Intent?) { 16 | 17 | //songInfo是当前播放的音频信息 18 | val songInfo = intent?.getParcelableExtra("songInfo") 19 | 20 | //bundleInfo是你在配置通知栏的那个bundle,里面可以拿到你自定义的参数 21 | val bundleInfo = intent?.getBundleExtra("bundleInfo") 22 | val targetClass = bundleInfo?.getString("targetClass")?.getTargetClass() 23 | 24 | if (StarrySky.getActivityStack().isNullOrEmpty()) { 25 | val mainIntent = Intent(context, HomeActivity::class.java) 26 | mainIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 27 | 28 | val targetIntent = Intent(context, targetClass) 29 | targetIntent.putExtra("songId", songInfo?.songId) 30 | 31 | val intents = arrayOf(mainIntent, targetIntent) 32 | context?.startActivities(intents) 33 | } else { 34 | val targetIntent = Intent(context, targetClass) 35 | targetIntent.putExtra("songId", songInfo?.songId) 36 | targetIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK 37 | context?.startActivity(targetIntent) 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/SpConstant.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib 2 | 3 | import com.lzx.starrysky.utils.KtPreferences 4 | 5 | object SpConstant : KtPreferences() { 6 | var HAS_PERMISSION by booleanPref() 7 | var KEY_TOKEN by stringPref() 8 | var KEY_EXPIRES by stringPref() 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/base/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.base 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.os.Bundle 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import androidx.annotation.IdRes 10 | import androidx.fragment.app.Fragment 11 | 12 | abstract class BaseFragment : Fragment() { 13 | 14 | var mContext: Context? = null 15 | var mActivity: Activity? = null 16 | 17 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 18 | val view = inflater.inflate(getResourceId(), container, false) 19 | mActivity = activity 20 | mContext = mActivity 21 | return view 22 | } 23 | 24 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 25 | super.onViewCreated(view, savedInstanceState) 26 | initView(view) 27 | } 28 | 29 | 30 | open fun findViewById(@IdRes id: Int): View? { 31 | return view?.findViewById(id) 32 | } 33 | 34 | override fun onAttach(context: Context) { 35 | super.onAttach(context) 36 | mActivity = context as Activity 37 | mContext = context 38 | } 39 | 40 | override fun onDetach() { 41 | mActivity = null 42 | super.onDetach() 43 | } 44 | 45 | override fun onDestroyView() { 46 | unInitView() 47 | super.onDestroyView() 48 | } 49 | 50 | abstract fun getResourceId(): Int 51 | 52 | abstract fun initView(view: View?) 53 | 54 | abstract fun unInitView() 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/card/CardActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.card 2 | 3 | import android.os.Bundle 4 | import android.view.ViewGroup 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.fragment.app.Fragment 7 | import androidx.fragment.app.FragmentManager 8 | import androidx.fragment.app.FragmentStatePagerAdapter 9 | import com.lzx.musiclib.R 10 | import com.lzx.starrysky.StarrySky 11 | import com.lzx.starrysky.utils.orDef 12 | import kotlinx.android.synthetic.main.activity_card.tabLayout 13 | import kotlinx.android.synthetic.main.activity_card.viewpager 14 | 15 | class CardActivity : AppCompatActivity() { 16 | 17 | private var categoryList = mutableListOf() 18 | private var isStopByOnPause = false 19 | private var adapter: CardCategoryAdapter? = null 20 | 21 | override fun onCreate(savedInstanceState: Bundle?) { 22 | super.onCreate(savedInstanceState) 23 | setContentView(R.layout.activity_card) 24 | 25 | StarrySky.closeNotification() 26 | StarrySky.setIsOpenNotification(false) 27 | 28 | categoryList.add(CardCategory("card1", "推荐")) 29 | categoryList.add(CardCategory("card2", "流行电音")) 30 | categoryList.add(CardCategory("card3", "情感陪伴")) 31 | categoryList.add(CardCategory("card4", "动感地带")) 32 | categoryList.add(CardCategory("card5", "劲歌金曲")) 33 | 34 | adapter = CardCategoryAdapter(supportFragmentManager, categoryList) 35 | viewpager.removeAllViews() 36 | viewpager.removeAllViewsInLayout() 37 | viewpager.adapter = adapter 38 | tabLayout.setViewPager(viewpager) 39 | } 40 | 41 | override fun onResume() { 42 | super.onResume() 43 | if (isStopByOnPause) { 44 | val pos = adapter?.currFragment?.curPlayPos.orDef() 45 | adapter?.currFragment?.playCurVoice(pos) 46 | isStopByOnPause = false 47 | } 48 | } 49 | 50 | override fun onPause() { 51 | super.onPause() 52 | isStopByOnPause = true 53 | } 54 | } 55 | 56 | class CardCategoryAdapter( 57 | fm: FragmentManager?, 58 | private var categoryList: MutableList 59 | ) : FragmentStatePagerAdapter(fm!!) { 60 | 61 | private val fragmentMap = hashMapOf() 62 | 63 | override fun getItem(position: Int): Fragment { 64 | val category = categoryList[position] 65 | if (fragmentMap[category.cardType] != null) { 66 | return fragmentMap[category.cardType]!! 67 | } 68 | val fragment = CardFragment.newInstance(category.cardType, category.cardTitle) 69 | fragmentMap[category.cardType] = fragment 70 | return fragment 71 | } 72 | 73 | override fun getCount(): Int = categoryList.size 74 | 75 | override fun getPageTitle(position: Int): CharSequence? { 76 | return categoryList[position].cardTitle 77 | } 78 | 79 | override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { 80 | super.destroyItem(container, position, `object`) 81 | val category = categoryList[position] 82 | if (fragmentMap[category.cardType] != null) { 83 | fragmentMap.remove(category.cardType) 84 | } 85 | } 86 | 87 | var currFragment: CardFragment? = null 88 | 89 | override fun setPrimaryItem(container: ViewGroup, position: Int, obj: Any) { 90 | if (obj is CardFragment) { 91 | currFragment = obj 92 | } 93 | super.setPrimaryItem(container, position, obj) 94 | } 95 | } 96 | 97 | 98 | data class CardCategory(var cardType: String, var cardTitle: String) -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/card/CardAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.card 2 | 3 | import android.app.Activity 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.gcssloop.widget.RCImageView 10 | import com.lzx.musiclib.R 11 | import com.lzx.musiclib.dynamic.DynamicDetailActivity 12 | import com.lzx.musiclib.loadImage 13 | import com.lzx.musiclib.navigationTo 14 | import com.lzx.musiclib.user.UserInfoActivity 15 | import com.lzx.starrysky.SongInfo 16 | import com.lzx.starrysky.StarrySky 17 | 18 | class CardAdapter(private val context: Activity?) : 19 | RecyclerView.Adapter() { 20 | 21 | private val list = mutableListOf() 22 | 23 | fun submitList(list: MutableList, isRefresh: Boolean) { 24 | if (isRefresh) { 25 | this.list.clear() 26 | } 27 | this.list.addAll(list) 28 | notifyDataSetChanged() 29 | } 30 | 31 | fun getList() = list 32 | 33 | fun getItem(position: Int): SongInfo? = list.getOrNull(position) 34 | 35 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { 36 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card, parent, false) 37 | return CardHolder(view) 38 | } 39 | 40 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { 41 | val info = list.getOrNull(position) 42 | val cardHolder = holder as CardHolder 43 | cardHolder.cover.loadImage(info?.songCover) 44 | cardHolder.headerImg.loadImage("https://i2.gqxz.com/uploads/202009/14/200914110924764.jpg") 45 | cardHolder.songName.text = info?.songName 46 | cardHolder.singer.text = info?.artist 47 | cardHolder.itemView.setOnClickListener { 48 | context?.navigationTo("songInfo" to info, "from" to "card") 49 | } 50 | cardHolder.headerImg.setOnClickListener { 51 | StarrySky.with().stopMusic() 52 | context?.navigationTo() 53 | } 54 | } 55 | 56 | class CardHolder(holder: View) : RecyclerView.ViewHolder(holder) { 57 | val cover: RCImageView = holder.findViewById(R.id.cover) 58 | val headerImg: RCImageView = holder.findViewById(R.id.headerImg) 59 | val songName: TextView = holder.findViewById(R.id.songName) 60 | val singer: TextView = holder.findViewById(R.id.singer) 61 | 62 | } 63 | 64 | override fun getItemCount(): Int = list.size 65 | } 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/card/CardFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.card 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import com.lzx.musiclib.R 6 | import com.lzx.musiclib.base.BaseFragment 7 | import com.lzx.musiclib.getSelfViewModel 8 | import com.lzx.musiclib.showToast 9 | import com.lzx.musiclib.viewmodel.MusicViewModel 10 | import com.lzx.musiclib.weight.GalleryItemDecoration 11 | import com.lzx.musiclib.weight.OnViewPagerListener 12 | import com.lzx.musiclib.weight.ViewPagerLayoutManager 13 | import com.lzx.starrysky.StarrySky 14 | import com.lzx.starrysky.manager.PlaybackStage 15 | import com.lzx.starrysky.utils.orDef 16 | import kotlinx.android.synthetic.main.fragment_card.recycleView 17 | 18 | class CardFragment : BaseFragment() { 19 | override fun getResourceId(): Int = R.layout.fragment_card 20 | private var viewModel: MusicViewModel? = null 21 | 22 | companion object { 23 | fun newInstance(cardType: String, cardName: String) = CardFragment().apply { 24 | arguments = Bundle().apply { 25 | putString("cardType", cardType) 26 | putString("cardName", cardName) 27 | } 28 | } 29 | } 30 | 31 | private var cardType: String? = null 32 | private var cardName: String? = null 33 | private var linearLayoutManager: ViewPagerLayoutManager? = null 34 | private var cardAdapter: CardAdapter? = null 35 | var curPlayPos = 0 36 | private var isVisibleToUser: Boolean = false 37 | 38 | override fun initView(view: View?) { 39 | cardType = arguments?.getString("cardType") 40 | cardName = arguments?.getString("cardName") 41 | viewModel = getSelfViewModel { 42 | cardLiveData.observe(this@CardFragment, { 43 | cardAdapter?.submitList(it, true) 44 | }) 45 | } 46 | initRecycleView() 47 | viewModel?.getCardMusicList(cardType) 48 | StarrySky.with().playbackState().observe(this, { 49 | if (it.stage == PlaybackStage.IDLE && !it.isStop) { 50 | //重播 51 | playCurVoice(curPlayPos) 52 | } 53 | }) 54 | } 55 | 56 | override fun setUserVisibleHint(isVisibleToUser: Boolean) { 57 | super.setUserVisibleHint(isVisibleToUser) 58 | this.isVisibleToUser = isVisibleToUser 59 | if (isVisibleToUser) { 60 | val position = linearLayoutManager?.getCurrPosition().orDef() 61 | if (position >= 0 && position <= cardAdapter?.getList()?.lastIndex ?: 0) { 62 | curPlayPos = position 63 | } 64 | playCurVoice(curPlayPos) 65 | } 66 | } 67 | 68 | private fun initRecycleView() { 69 | linearLayoutManager = ViewPagerLayoutManager(activity) 70 | linearLayoutManager?.recycleChildrenOnDetach = true 71 | recycleView.layoutManager = linearLayoutManager 72 | recycleView.addItemDecoration(GalleryItemDecoration()) 73 | recycleView.adapter = CardAdapter(activity).also { cardAdapter = it } 74 | linearLayoutManager?.setOnViewPagerListener(object : OnViewPagerListener { 75 | override fun onInitComplete() { 76 | val position = linearLayoutManager?.getCurrPosition().orDef() 77 | if (position >= 0 && position <= cardAdapter?.getList()?.lastIndex ?: 0) { 78 | curPlayPos = position 79 | } 80 | playCurVoice(curPlayPos) 81 | } 82 | 83 | override fun onPageRelease(isNext: Boolean, position: Int) { 84 | 85 | } 86 | 87 | override fun onPageSelected(position: Int, isBottom: Boolean) { 88 | if (curPlayPos == position) return 89 | playCurVoice(position) 90 | } 91 | }) 92 | } 93 | 94 | fun playCurVoice(position: Int) { 95 | if (!isVisibleToUser) return 96 | curPlayPos = position 97 | val songInfo = cardAdapter?.getItem(position) ?: return 98 | activity?.showToast("当前播放:" + songInfo.songName) 99 | StarrySky.with() 100 | .skipMediaQueue(true) 101 | .playMusicByInfo(songInfo) 102 | } 103 | 104 | override fun unInitView() { 105 | } 106 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/dynamic/DynamicAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.dynamic 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.gcssloop.widget.RCImageView 10 | import com.lzx.musiclib.R 11 | import com.lzx.musiclib.loadImage 12 | import com.lzx.musiclib.navigationTo 13 | import com.lzx.musiclib.user.UserInfoActivity 14 | import com.lzx.musiclib.weight.MomentAudioView 15 | import com.lzx.starrysky.SongInfo 16 | import com.lzx.starrysky.StarrySky 17 | 18 | class DynamicAdapter(val context: Context?) : RecyclerView.Adapter() { 19 | 20 | private val list = mutableListOf() 21 | var listener: OnItemClickListener? = null 22 | 23 | fun submitList(list: MutableList, isRefresh: Boolean) { 24 | if (isRefresh) { 25 | this.list.clear() 26 | } 27 | this.list.addAll(list) 28 | notifyDataSetChanged() 29 | } 30 | 31 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DynamicHolder { 32 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_dynamic, parent, false) 33 | return DynamicHolder(view) 34 | } 35 | 36 | override fun onBindViewHolder(holder: DynamicHolder, position: Int) { 37 | val info = list[position] 38 | holder.userHeader.loadImage(info.songCover) 39 | holder.nickname.text = info.artist 40 | holder.audioView.setVoiceInfo(info) 41 | 42 | val isPlaying = StarrySky.with().isCurrMusicIsPlaying(info.songId) 43 | holder.audioView.setUIState(isPlaying) 44 | holder.audioView.setOnClickListener { 45 | listener?.itemClick(list, position) 46 | } 47 | holder.desc.setOnClickListener { 48 | StarrySky.with().playMusic(list, position) 49 | context?.navigationTo("songInfo" to info, "from" to "dynamic") 50 | } 51 | holder.userHeader.setOnClickListener { 52 | StarrySky.with().stopMusic() 53 | context?.navigationTo() 54 | } 55 | } 56 | 57 | override fun getItemCount(): Int = list.size 58 | 59 | class DynamicHolder(holder: View) : RecyclerView.ViewHolder(holder) { 60 | val userHeader: RCImageView = holder.findViewById(R.id.userHeader) 61 | val nickname: TextView = holder.findViewById(R.id.nickname) 62 | val desc: TextView = holder.findViewById(R.id.desc) 63 | val audioView: MomentAudioView = holder.findViewById(R.id.audioView) 64 | } 65 | 66 | interface OnItemClickListener { 67 | fun itemClick(list: MutableList, position: Int) 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/dynamic/DynamicDetailActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.dynamic 2 | 3 | import android.animation.Animator 4 | import android.animation.AnimatorListenerAdapter 5 | import android.animation.ObjectAnimator 6 | import android.annotation.SuppressLint 7 | import android.os.Bundle 8 | import android.view.animation.LinearInterpolator 9 | import android.widget.SeekBar 10 | import androidx.appcompat.app.AppCompatActivity 11 | import com.lzx.musiclib.R 12 | import com.lzx.musiclib.loadImage 13 | import com.lzx.starrysky.OnPlayProgressListener 14 | import com.lzx.starrysky.SongInfo 15 | import com.lzx.starrysky.StarrySky 16 | import com.lzx.starrysky.manager.PlaybackStage 17 | import com.lzx.starrysky.utils.formatTime 18 | import kotlinx.android.synthetic.main.activiity_dynamic_detail.cover 19 | import kotlinx.android.synthetic.main.activiity_dynamic_detail.progressText 20 | import kotlinx.android.synthetic.main.activiity_dynamic_detail.seekBar 21 | import kotlinx.android.synthetic.main.activiity_dynamic_detail.songName 22 | import kotlinx.android.synthetic.main.activiity_dynamic_detail.timeText 23 | 24 | class DynamicDetailActivity : AppCompatActivity() { 25 | 26 | private var from: String? = null 27 | private var songInfo: SongInfo? = null 28 | private var rotationAnim: ObjectAnimator? = null 29 | 30 | override fun onCreate(savedInstanceState: Bundle?) { 31 | super.onCreate(savedInstanceState) 32 | setContentView(R.layout.activiity_dynamic_detail) 33 | 34 | from = intent.getStringExtra("from") 35 | songInfo = intent.getParcelableExtra("songInfo") 36 | 37 | if (from == "dynamic") { 38 | StarrySky.closeNotification() 39 | } 40 | 41 | cover.loadImage(songInfo?.songCover) 42 | songName.text = songInfo?.songName 43 | 44 | rotationAnim = ObjectAnimator.ofFloat(cover, "rotation", 0f, 359f) 45 | rotationAnim?.interpolator = LinearInterpolator() 46 | rotationAnim?.duration = 20000 47 | rotationAnim?.addListener(object : AnimatorListenerAdapter() { 48 | override fun onAnimationEnd(animation: Animator?) { 49 | super.onAnimationEnd(animation) 50 | rotationAnim?.start() 51 | } 52 | }) 53 | rotationAnim?.start() 54 | 55 | StarrySky.with().playbackState().observe(this, { 56 | if (it.stage == PlaybackStage.IDLE && !it.isStop) { 57 | //重播 58 | StarrySky.with() 59 | .skipMediaQueue(true) 60 | .playMusicByInfo(songInfo) 61 | } 62 | }) 63 | StarrySky.with().setOnPlayProgressListener(object : OnPlayProgressListener { 64 | @SuppressLint("SetTextI18n") 65 | override fun onPlayProgress(currPos: Long, duration: Long) { 66 | if (seekBar.max.toLong() != duration) { 67 | seekBar.max = duration.toInt() 68 | } 69 | seekBar.progress = currPos.toInt() 70 | progressText.text = currPos.formatTime() 71 | timeText.text = " / " + duration.formatTime() 72 | } 73 | }) 74 | //进度SeekBar 75 | seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { 76 | override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {} 77 | override fun onStartTrackingTouch(seekBar: SeekBar) {} 78 | override fun onStopTrackingTouch(seekBar: SeekBar) { 79 | StarrySky.with().seekTo(seekBar.progress.toLong(), true) 80 | } 81 | }) 82 | } 83 | 84 | override fun onDestroy() { 85 | super.onDestroy() 86 | rotationAnim?.cancel() 87 | rotationAnim?.removeAllListeners() 88 | rotationAnim = null 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/dynamic/DynamicFragment.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.dynamic 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import com.lzx.musiclib.R 7 | import com.lzx.musiclib.base.BaseFragment 8 | import com.lzx.musiclib.getSelfViewModel 9 | import com.lzx.musiclib.viewmodel.MusicViewModel 10 | import com.lzx.starrysky.SongInfo 11 | import com.lzx.starrysky.StarrySky 12 | import kotlinx.android.synthetic.main.fragment_card.recycleView 13 | 14 | class DynamicFragment : BaseFragment() { 15 | companion object { 16 | fun newInstance(type: String) = DynamicFragment().apply { 17 | arguments = Bundle().apply { 18 | putString("type", type) 19 | } 20 | } 21 | } 22 | 23 | override fun getResourceId(): Int = R.layout.fragment_card 24 | 25 | private var dynamicAdapter: DynamicAdapter? = null 26 | private var viewModel: MusicViewModel? = null 27 | private var type: String? = null 28 | 29 | override fun initView(view: View?) { 30 | type = arguments?.getString("type") 31 | recycleView.layoutManager = LinearLayoutManager(activity) 32 | recycleView.adapter = DynamicAdapter(context).also { dynamicAdapter = it } 33 | 34 | viewModel = getSelfViewModel { 35 | dynamicLiveData.observe(this@DynamicFragment, { 36 | dynamicAdapter?.submitList(it, true) 37 | }) 38 | } 39 | 40 | viewModel?.getDynamicMusicList(type) 41 | 42 | StarrySky.with().playbackState().observe(this, { 43 | dynamicAdapter?.notifyDataSetChanged() 44 | }) 45 | 46 | dynamicAdapter?.listener = object : DynamicAdapter.OnItemClickListener { 47 | override fun itemClick(list: MutableList, position: Int) { 48 | (activity as DynamicActivity).showVoiceBar() 49 | val info = list[position] 50 | if (StarrySky.with().isCurrMusicIsPlaying(info.songId)) { 51 | StarrySky.with().pauseMusic() 52 | } else { 53 | StarrySky.with().playMusic(list, position) 54 | } 55 | } 56 | 57 | } 58 | } 59 | 60 | override fun unInitView() { 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/http/QQMusicApi.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.http 2 | 3 | import okhttp3.ResponseBody 4 | import retrofit2.http.GET 5 | import retrofit2.http.Headers 6 | import retrofit2.http.Query 7 | 8 | interface QQMusicApi { 9 | companion object { 10 | const val BASE_URL = "https://api.qq.jsososo.com/" 11 | // https://api.qq.jsososo.com/songlist?id=2429907335 12 | } 13 | 14 | @Headers("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows 7)") 15 | @GET("song/urls") 16 | suspend fun getMusicUrl(@Query("id") id: String): ResponseBody 17 | 18 | @Headers("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows 7)") 19 | @GET("songlist") 20 | suspend fun getQQMusicSongList(@Query("id") id: String): ResponseBody 21 | 22 | 23 | @Headers("User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows 7)") 24 | @GET("lzxTreasureBox") 25 | suspend fun getGithubHtml(): ResponseBody 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/http/RetrofitClient.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.http 2 | 3 | import okhttp3.OkHttpClient 4 | import okhttp3.logging.HttpLoggingInterceptor 5 | import retrofit2.Retrofit 6 | import retrofit2.converter.gson.GsonConverterFactory 7 | import java.util.concurrent.TimeUnit 8 | 9 | object RetrofitClient { 10 | private val client: OkHttpClient 11 | get() { 12 | val builder = OkHttpClient.Builder() 13 | builder.connectTimeout(5L, TimeUnit.SECONDS) 14 | val interceptor = HttpLoggingInterceptor() 15 | interceptor.level = HttpLoggingInterceptor.Level.BODY 16 | builder.addInterceptor(interceptor) 17 | return builder.build() 18 | } 19 | 20 | fun getService(serviceClass: Class, baseUrl: String = QQMusicApi.BASE_URL): S { 21 | return Retrofit.Builder() 22 | .client(client) 23 | .baseUrl(baseUrl) 24 | .addConverterFactory(GsonConverterFactory.create()) 25 | .build() 26 | .create(serviceClass) 27 | } 28 | 29 | fun getQQMusic(): QQMusicApi { 30 | return getService(QQMusicApi::class.java, QQMusicApi.BASE_URL) 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/user/UserAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.user 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.lzx.musiclib.R 10 | import com.lzx.starrysky.SongInfo 11 | import com.lzx.starrysky.StarrySky 12 | import com.lzx.starrysky.utils.formatTime 13 | 14 | class UserAdapter : RecyclerView.Adapter() { 15 | 16 | private val list = mutableListOf() 17 | 18 | var currPlayingIndex = 0 19 | 20 | fun submitList(list: MutableList, isRefresh: Boolean) { 21 | if (isRefresh) { 22 | this.list.clear() 23 | } 24 | this.list.addAll(list) 25 | notifyDataSetChanged() 26 | } 27 | 28 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserHolder { 29 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_user, parent, false) 30 | return UserHolder(view) 31 | } 32 | 33 | override fun onBindViewHolder(holder: UserHolder, position: Int) { 34 | val info = list[position] 35 | holder.musicName.text = info.songName 36 | holder.musicSinger.text = info.artist 37 | 38 | holder.itemView.setOnClickListener { 39 | currPlayingIndex = position 40 | StarrySky.with().playMusic(list, position) 41 | } 42 | } 43 | 44 | @SuppressLint("SetTextI18n") 45 | override fun onBindViewHolder(holder: UserHolder, position: Int, payloads: MutableList) { 46 | super.onBindViewHolder(holder, position, payloads) 47 | val any = payloads.getOrNull(0) ?: return 48 | val info = list[position] 49 | val playingId = StarrySky.with().getNowPlayingSongId() 50 | if (info.songId != playingId) return 51 | val pair = any as Pair<*, *> 52 | val currPos = pair.first as Long 53 | val duration = pair.second as Long 54 | holder.time.text = currPos.formatTime() + " / " + duration.formatTime() 55 | } 56 | 57 | override fun getItemCount(): Int = list.size 58 | 59 | class UserHolder(holder: View) : RecyclerView.ViewHolder(holder) { 60 | val musicName: TextView = holder.findViewById(R.id.musicName) 61 | val musicSinger: TextView = holder.findViewById(R.id.musicSinger) 62 | val time: TextView = holder.findViewById(R.id.time) 63 | } 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/user/UserInfoActivity.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.user 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import androidx.recyclerview.widget.LinearLayoutManager 6 | import com.lzx.musiclib.R 7 | import com.lzx.musiclib.getSelfViewModel 8 | import com.lzx.musiclib.loadImage 9 | import com.lzx.musiclib.viewmodel.MusicViewModel 10 | import com.lzx.starrysky.OnPlayProgressListener 11 | import com.lzx.starrysky.StarrySky 12 | import com.lzx.starrysky.manager.PlaybackStage 13 | import com.lzx.starrysky.utils.orDef 14 | import kotlinx.android.synthetic.main.activity_user.bgImage 15 | import kotlinx.android.synthetic.main.activity_user.recycleView 16 | 17 | class UserInfoActivity : AppCompatActivity() { 18 | 19 | private var userAdapter: UserAdapter? = null 20 | private var viewModel: MusicViewModel? = null 21 | 22 | override fun onCreate(savedInstanceState: Bundle?) { 23 | super.onCreate(savedInstanceState) 24 | setContentView(R.layout.activity_user) 25 | 26 | bgImage.loadImage("https://up.zhuoku.org/pic/ba/5b/a0/ba5ba00c78aafbd57ba5021615b46d8a.jpg") 27 | 28 | recycleView.layoutManager = LinearLayoutManager(this) 29 | recycleView.adapter = UserAdapter().also { userAdapter = it } 30 | 31 | viewModel = getSelfViewModel { 32 | val list = getUserMusicList() 33 | userAdapter?.submitList(list, true) 34 | } 35 | 36 | StarrySky.with().playbackState().observe(this, { 37 | when (it.stage) { 38 | PlaybackStage.PLAYING -> { 39 | userAdapter?.currPlayingIndex = StarrySky.with().getNowPlayingIndex() 40 | userAdapter?.notifyDataSetChanged() 41 | } 42 | } 43 | }) 44 | 45 | StarrySky.with().setOnPlayProgressListener(object : OnPlayProgressListener { 46 | override fun onPlayProgress(currPos: Long, duration: Long) { 47 | userAdapter?.notifyItemChanged(userAdapter?.currPlayingIndex.orDef(), Pair(currPos, duration)) 48 | } 49 | }) 50 | } 51 | 52 | override fun onDestroy() { 53 | super.onDestroy() 54 | StarrySky.with().stopMusic() 55 | } 56 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/CustomTabEntity.java: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight; 2 | 3 | import androidx.annotation.DrawableRes; 4 | 5 | public interface CustomTabEntity { 6 | String getTabTitle(); 7 | 8 | @DrawableRes 9 | int getTabSelectedIcon(); 10 | 11 | @DrawableRes 12 | int getTabUnselectedIcon(); 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/GalleryItemDecoration.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight 2 | 3 | import android.graphics.Rect 4 | import android.view.View 5 | import androidx.recyclerview.widget.RecyclerView 6 | import com.lzx.musiclib.dp 7 | import com.lzx.starrysky.utils.orDef 8 | 9 | 10 | class GalleryItemDecoration() : RecyclerView.ItemDecoration() { 11 | 12 | 13 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) { 14 | val position = parent.getChildAdapterPosition(view) 15 | val itemCount = parent.adapter?.itemCount.orDef() 16 | 17 | val isLastPosition = position == itemCount - 1 18 | 19 | val itemHeight: Int = parent.height - 97.dp 20 | 21 | val lp = view.layoutParams as RecyclerView.LayoutParams 22 | lp.height = itemHeight 23 | 24 | var bottomMargin = 15.dp 25 | if (isLastPosition) { 26 | bottomMargin = 97.dp 27 | } 28 | lp.setMargins(15.dp, lp.topMargin, 15.dp, bottomMargin) 29 | view.layoutParams = lp 30 | super.getItemOffsets(outRect, view, parent, state) 31 | } 32 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/MomentAudioView.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.LayoutInflater 6 | import android.view.View.OnClickListener 7 | import android.widget.ImageView 8 | import android.widget.TextView 9 | import androidx.lifecycle.Lifecycle 10 | import androidx.lifecycle.LifecycleObserver 11 | import androidx.lifecycle.OnLifecycleEvent 12 | import com.gcssloop.widget.RCRelativeLayout 13 | import com.lzx.musiclib.LifecycleUtils 14 | import com.lzx.musiclib.R 15 | import com.lzx.starrysky.SongInfo 16 | import com.lzx.starrysky.StarrySky 17 | 18 | class MomentAudioView : RCRelativeLayout, LifecycleObserver { 19 | 20 | private lateinit var ivPlay: ImageView 21 | private lateinit var title: TextView 22 | private lateinit var desc: TextView 23 | 24 | // private var isPlaying: Boolean = false 25 | private var songInfo: SongInfo? = null 26 | private var dynamicId: String = "" 27 | 28 | constructor(context: Context, ivPlay: ImageView) : super(context) { 29 | initView(context) 30 | } 31 | 32 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { 33 | initView(context) 34 | } 35 | 36 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, 37 | attrs, defStyleAttr) { 38 | initView(context) 39 | } 40 | 41 | private fun initView(context: Context) { 42 | LifecycleUtils.addObserver(context, this) 43 | LayoutInflater.from(context).inflate(R.layout.layout_moment_audio_view, this, true) 44 | ivPlay = findViewById(R.id.img_play) 45 | title = findViewById(R.id.title) 46 | desc = findViewById(R.id.desc) 47 | } 48 | 49 | fun setVoiceInfo(info: SongInfo?) { 50 | this.songInfo = info 51 | this.dynamicId = info?.songId.orEmpty() 52 | if (!StarrySky.with().isCurrMusicIsPlaying(info?.songId)) { 53 | ivPlay.setImageResource(R.drawable.moment_audio_view_pause) 54 | } else { 55 | ivPlay.setImageResource(R.drawable.moment_audio_view_play) 56 | } 57 | title.text = songInfo?.songName 58 | desc.text = songInfo?.artist 59 | } 60 | 61 | fun setUIState(isPlaying: Boolean) { 62 | if (isPlaying) { 63 | ivPlay.setImageResource(R.drawable.moment_audio_view_pause) 64 | } else { 65 | ivPlay.setImageResource(R.drawable.moment_audio_view_play) 66 | } 67 | } 68 | 69 | @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) 70 | fun onDestroy() { 71 | LifecycleUtils.removeObserver(context, this) 72 | StarrySky.with().stopMusic() 73 | } 74 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/OnTabSelectListener.java: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight; 2 | 3 | public interface OnTabSelectListener { 4 | void onTabSelect(int position); 5 | 6 | void onTabReselect(int position); 7 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/SquareImageView.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | 6 | class SquareImageView 7 | @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : 8 | androidx.appcompat.widget.AppCompatImageView(context, attrs, defStyleAttr) { 9 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 10 | super.onMeasure(widthMeasureSpec, widthMeasureSpec) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lzx/musiclib/weight/SquareView.kt: -------------------------------------------------------------------------------- 1 | package com.lzx.musiclib.weight 2 | 3 | import android.content.Context 4 | import android.util.AttributeSet 5 | import android.view.View 6 | 7 | class SquareView 8 | @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : 9 | View(context, attrs, defStyleAttr) { 10 | override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 11 | super.onMeasure(widthMeasureSpec, widthMeasureSpec) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/popup_bottom_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/anim/popup_bottom_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/afb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/afb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/b0c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/b0c.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/b6e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/b6e.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ba1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ba1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bt_playpage_button_clock_normal_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/bt_playpage_button_clock_normal_new.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/bt_playpage_loop_press.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/bt_playpage_loop_press.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/dy_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/dy_bg.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gdt_ic_express_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/gdt_ic_express_pause.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gdt_ic_express_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/gdt_ic_express_play.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gdt_ic_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/gdt_ic_pause.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/gdt_ic_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/gdt_ic_play.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_accompaniment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_accompaniment.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_arrow_drop_down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_danqu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_danqu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_live_red_playing1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_live_red_playing1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_live_red_playing2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_live_red_playing2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_live_red_playing3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_live_red_playing3.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_live_red_playing4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_live_red_playing4.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_live_red_playing5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_live_red_playing5.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_next_song.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_next_song.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_pre_song.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_pre_song.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_shunji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_shunji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_shunxu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_shunxu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_songlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_songlist.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_speed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_user.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_variable_speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_variable_speed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/ic_volume.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_bar_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/icon_bar_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_dynamic_top_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/icon_dynamic_top_next.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_dynamic_top_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/icon_dynamic_top_play.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_dynamic_top_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/icon_dynamic_top_stop.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/icon_dynamic_voice_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/icon_dynamic_voice_loading.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/moment_audio_view_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/moment_audio_view_pause.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/moment_audio_view_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/moment_audio_view_play.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/note_btn_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/note_btn_close.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_favorite_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_favorite_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_lyrics_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_lyrics_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_next_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_next_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_pause_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_pause_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_play_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_play_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_dark_prev_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_dark_prev_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_favorite_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_favorite_checked.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_favorite_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_favorite_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_lyrics_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_lyrics_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_next_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_next_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_pause_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_pause_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_play_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_play_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_light_prev_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_light_prev_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/notify_btn_lyrics_checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/notify_btn_lyrics_checked.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/recordfinish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/recordfinish.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/rerecord.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EspoirX/StarrySky/8c6ace6df35a5f2ec4841099a5a021fa85ac9e01/app/src/main/res/drawable-xxhdpi/rerecord.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/anim_playing.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 13 | 16 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/anim_round_rotate.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button_36dp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_equalizer_band_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_play_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_spinner.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_singer_more.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_dark_next_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_dark_pause_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_dark_play_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_dark_prev_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_light_next_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_light_pause_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_light_play_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/notify_btn_light_prev_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/progress_equalizer_band.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/seek_bar_pro.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/seek_bar_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_bg_dialog.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_round_black.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activiity_dynamic_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 19 | 29 | 30 | 41 | 42 | 51 | 52 | 67 | 68 | 79 | 80 | 89 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_card.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 28 | 29 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_dynamic.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 31 | 32 | 41 | 42 | 50 | 51 | 58 | 59 | 72 | 73 | 81 | 82 | 89 | 90 | 101 | 102 | 110 | 111 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_effect.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 15 | 16 | 24 | 25 | 31 | 32 | 33 | 43 | 44 | 52 | 53 | 54 | 62 | 63 | 69 | 70 | 76 | 77 | 81 | 82 | 83 | 84 | 90 | 91 | 97 | 98 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 |