├── .gitignore
├── .idea
├── .gitignore
├── .name
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── compiler.xml
├── deploymentTargetDropDown.xml
├── encodings.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jarRepositories.xml
├── kotlinc.xml
├── misc.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ ├── ftplet-api-1.1.1.jar
│ ├── ftpserver-core-1.1.1.jar
│ ├── log4j-1.2.17.jar
│ ├── mina-core-2.0.16.jar
│ └── slf4j-api-1.6.2.jar
├── proguard-rules.pro
├── release
│ └── output-metadata.json
└── src
│ ├── androidTest
│ └── java
│ │ └── cn
│ │ └── wearbbs
│ │ └── music
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── cn
│ │ │ ├── jackuxl
│ │ │ ├── api
│ │ │ │ ├── CloudSongApi.java
│ │ │ │ ├── MVApi.java
│ │ │ │ ├── MusicListApi.java
│ │ │ │ ├── SongApi.kt
│ │ │ │ └── UserApi.java
│ │ │ ├── model
│ │ │ │ ├── Album.kt
│ │ │ │ ├── Artist.kt
│ │ │ │ ├── CloudSong.kt
│ │ │ │ ├── CommentThread.kt
│ │ │ │ ├── Song.kt
│ │ │ │ ├── SongUrl.kt
│ │ │ │ ├── info
│ │ │ │ │ ├── ChargeInfo.kt
│ │ │ │ │ ├── Info.kt
│ │ │ │ │ └── ResourceInfo.kt
│ │ │ │ ├── privilege
│ │ │ │ │ ├── FreeTimeTrialPrivilege.kt
│ │ │ │ │ ├── FreeTrialPrivilege.kt
│ │ │ │ │ └── Privilege.kt
│ │ │ │ └── result
│ │ │ │ │ ├── AlbumResult.kt
│ │ │ │ │ ├── PersonalFMResult.kt
│ │ │ │ │ ├── Result.kt
│ │ │ │ │ ├── SearchHot.kt
│ │ │ │ │ ├── SearchHotResult.kt
│ │ │ │ │ ├── SearchResult.kt
│ │ │ │ │ ├── SongDetailResult.kt
│ │ │ │ │ ├── SongResult.kt
│ │ │ │ │ ├── SongUrlResult.kt
│ │ │ │ │ └── UserCloudResult.kt
│ │ │ └── util
│ │ │ │ └── NetWorkUtil.java
│ │ │ └── wearbbs
│ │ │ └── music
│ │ │ ├── adapter
│ │ │ ├── CommentAdapter.java
│ │ │ ├── LocalMusicAdapter.java
│ │ │ ├── MusicAdapter.java
│ │ │ ├── MusicLibraryAdapter.java
│ │ │ ├── SongAdapter.kt
│ │ │ └── ViewPagerAdapter.java
│ │ │ ├── api
│ │ │ └── AppServiceApi.java
│ │ │ ├── application
│ │ │ └── MainApplication.java
│ │ │ ├── event
│ │ │ └── MessageEvent.java
│ │ │ ├── fragment
│ │ │ ├── ConsoleFragment.java
│ │ │ ├── LyricsFragment.java
│ │ │ └── PlayerFragment.java
│ │ │ ├── service
│ │ │ └── MusicPlayerService.java
│ │ │ ├── ui
│ │ │ ├── AboutActivity.java
│ │ │ ├── CommentActivity.java
│ │ │ ├── FeedbackActivity.java
│ │ │ ├── FtpActivity.java
│ │ │ ├── LocalMusicActivity.java
│ │ │ ├── LoginActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MenuActivity.java
│ │ │ ├── MusicLibraryActivity.java
│ │ │ ├── MusicListActivity.java
│ │ │ ├── MusicPanActivity.java
│ │ │ ├── OpenSourceActivity.java
│ │ │ ├── PlayListActivity.java
│ │ │ ├── QRCodeActivity.java
│ │ │ ├── ReplyActivity.java
│ │ │ ├── SearchActivity.java
│ │ │ ├── SettingsActivity.java
│ │ │ ├── SlideBackActivity.java
│ │ │ ├── UpdateActivity.java
│ │ │ ├── UserProfileActivity.java
│ │ │ └── ViewPictureActivity.java
│ │ │ ├── util
│ │ │ ├── DownloadUtil.java
│ │ │ ├── QRCodeUtil.java
│ │ │ ├── SharedPreferencesUtil.java
│ │ │ └── ToastUtil.java
│ │ │ └── view
│ │ │ ├── LoadingView.java
│ │ │ └── MessageView.java
│ └── res
│ │ ├── drawable-night
│ │ ├── icon_play_order.png
│ │ └── icon_play_repeat_one.png
│ │ ├── drawable
│ │ ├── btn_blue.xml
│ │ ├── et_blue.xml
│ │ ├── ic_baseline_android_24.xml
│ │ ├── ic_baseline_arrow_back_24.xml
│ │ ├── ic_baseline_arrow_back_ios_24.xml
│ │ ├── ic_baseline_arrow_forward_ios_24.xml
│ │ ├── ic_baseline_assignment_24.xml
│ │ ├── ic_baseline_assignment_turned_in_24.xml
│ │ ├── ic_baseline_brightness_24.xml
│ │ ├── ic_baseline_brightness_24_black.xml
│ │ ├── ic_baseline_build_24.xml
│ │ ├── ic_baseline_check_24.xml
│ │ ├── ic_baseline_cloud_24.xml
│ │ ├── ic_baseline_cloud_download_24.xml
│ │ ├── ic_baseline_desktop_windows_24.xml
│ │ ├── ic_baseline_family_restroom_24.xml
│ │ ├── ic_baseline_favorite_24.xml
│ │ ├── ic_baseline_favorite_border_24.xml
│ │ ├── ic_baseline_file_copy_24.xml
│ │ ├── ic_baseline_library_music_24.xml
│ │ ├── ic_baseline_lock_24.xml
│ │ ├── ic_baseline_login_24.xml
│ │ ├── ic_baseline_menu_24.xml
│ │ ├── ic_baseline_message_24.xml
│ │ ├── ic_baseline_music_video_24.xml
│ │ ├── ic_baseline_pause_circle_filled_24.xml
│ │ ├── ic_baseline_person_24.xml
│ │ ├── ic_baseline_phone_android_24.xml
│ │ ├── ic_baseline_photo_size_select_actual_24.xml
│ │ ├── ic_baseline_play_circle_filled_24.xml
│ │ ├── ic_baseline_playlist_play_24.xml
│ │ ├── ic_baseline_radio_24.xml
│ │ ├── ic_baseline_refresh_24.xml
│ │ ├── ic_baseline_save_24.xml
│ │ ├── ic_baseline_sd_storage_24.xml
│ │ ├── ic_baseline_search_24.xml
│ │ ├── ic_baseline_settings_24.xml
│ │ ├── ic_baseline_share_24.xml
│ │ ├── ic_baseline_star_24.xml
│ │ ├── ic_baseline_supervised_user_circle_24.xml
│ │ ├── ic_baseline_supervised_user_circle_primary_24.xml
│ │ ├── ic_baseline_thumb_up_24.xml
│ │ ├── ic_baseline_visibility_24.xml
│ │ ├── ic_baseline_visibility_off_24.xml
│ │ ├── ic_baseline_volume_down_24.xml
│ │ ├── ic_baseline_volume_up_24.xml
│ │ ├── ic_baseline_warning_24.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_outline_thumb_up_24.xml
│ │ ├── icon_extra.png
│ │ ├── icon_play_order.png
│ │ ├── icon_play_repeat_one.png
│ │ ├── icon_tip.png
│ │ ├── middle_ss.xml
│ │ ├── qrcode_group.png
│ │ ├── qrcode_update.png
│ │ ├── qrcode_update_dev.png
│ │ ├── ripple_item_normal.xml
│ │ ├── shape_progressbar_azure.xml
│ │ └── shape_progressbar_loading.xml
│ │ ├── layout
│ │ ├── activity_about.xml
│ │ ├── activity_comment.xml
│ │ ├── activity_feedback.xml
│ │ ├── activity_ftp.xml
│ │ ├── activity_localmusic.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ ├── activity_menu.xml
│ │ ├── activity_music.xml
│ │ ├── activity_opensource.xml
│ │ ├── activity_qrcode.xml
│ │ ├── activity_reply.xml
│ │ ├── activity_search.xml
│ │ ├── activity_settings.xml
│ │ ├── activity_update.xml
│ │ ├── activity_userprofile.xml
│ │ ├── activity_viewpicture.xml
│ │ ├── fragment_console.xml
│ │ ├── fragment_lyrics.xml
│ │ ├── fragment_player.xml
│ │ ├── item_comment.xml
│ │ ├── item_hot.xml
│ │ ├── item_music.xml
│ │ ├── view_loading.xml
│ │ ├── view_message.xml
│ │ ├── widget_musiclist_info.xml
│ │ └── widget_reply.xml
│ │ ├── mipmap
│ │ └── ic_launcher_round.png
│ │ ├── values-night
│ │ └── themes.xml
│ │ ├── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── themes.xml
│ │ └── xml
│ │ └── root_preferences.xml
│ └── test
│ └── java
│ └── cn
│ └── wearbbs
│ └── music
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | *.apk
17 | *.jks
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | WearMusicPro
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | xmlns:android
18 |
19 | ^$
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | xmlns:.*
29 |
30 | ^$
31 |
32 |
33 | BY_NAME
34 |
35 |
36 |
37 |
38 |
39 |
40 | .*:id
41 |
42 | http://schemas.android.com/apk/res/android
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | .*:name
52 |
53 | http://schemas.android.com/apk/res/android
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | name
63 |
64 | ^$
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | style
74 |
75 | ^$
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | .*
85 |
86 | ^$
87 |
88 |
89 | BY_NAME
90 |
91 |
92 |
93 |
94 |
95 |
96 | .*
97 |
98 | http://schemas.android.com/apk/res/android
99 |
100 |
101 | ANDROID_ATTRIBUTE_ORDER
102 |
103 |
104 |
105 |
106 |
107 |
108 | .*
109 |
110 | .*
111 |
112 |
113 | BY_NAME
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetDropDown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.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 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.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 |
--------------------------------------------------------------------------------
/.idea/kotlinc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 | WearMusic
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 | - [官方网站](https://wmusic.wearbbs.cn)
32 | - [Github Release](https://github.com/JackuXL/WearMusic/releases)
33 |
34 | > 下载后,请前往 [WearBBS](https://wearbbs.cn) 查看 [ADB 教程](https://wearbbs.cn/threads/adb.110/),以将其安装至手表。
35 |
36 |
37 | ### 了解更多
38 |
39 | > 请前往 [WearBBS 资源中心](https://wearbbs.cn/resources/wearmusic.260/) 。
40 |
41 |
42 |
43 | ## 预览视频
44 |
45 | [手表网易云第三方客户端 WearMusic v3.0 - 从零重置 稳定护航每一首音乐!](https://www.bilibili.com/video/BV1Nv411T7PW/)
46 |
47 |
48 |
49 | ## 关于
50 |
51 | - 哔哩哔哩:@JackuXL
52 | - 软件交流群:133636679
53 |
54 | WearMusic 是完全开源且免费的。同时,维护后台的[API服务器](https://music.wearbbs.cn)和[更新服务器](https://wmu.wearbbs.cn)需要投入大量的资金,您可以自愿捐助我们,保证WearMusic 的正常更新、运行。
55 |
56 |
57 |
58 |
59 | ## Licence
60 |
61 | 本项目在 AGPL-3.0 许可证下开源,详情参阅 [LICENSE 文件](https://github.com/JackuXL/WearMusic/blob/master/LICENSE)。
62 |
63 | **但请注意,您必须同时遵守下面的额外限制:**
64 | **However, please note that you must also observe the following additional restrictions:**
65 |
66 | - 基于(修改)本项目所开发的新项目,必须保留本项目对包括但不限于特定设备、地域、人群的限制,包括源代码和二进制都必须遵守此限制。
67 | - Based on (modifying) the new project developed by this project must retain the limitations of this project including but not limited to specific devices, regions, and crowds, including source code and binary must comply with this restriction.
68 | - 基于(修改)本项目所开发的新项目,其许可证必须包含所有这里列出的额外限制条件。
69 | - Based on (modifying) the new project developed by this project, the license must include all additional restrictions listed here.
70 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 | android {
6 | compileSdkVersion 31
7 | buildToolsVersion "30.0.3"
8 | buildFeatures {
9 | viewBinding true
10 | }
11 | defaultConfig {
12 | applicationId "cn.wearbbs.music"
13 | minSdkVersion 21
14 | targetSdkVersion 31
15 | versionCode 13
16 | versionName "3.5.2"
17 |
18 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
19 |
20 | }
21 | packagingOptions {
22 | resources {
23 | excludes += ['META-INF/DEPENDENCIES']
24 | }
25 | }
26 | buildTypes {
27 | release {
28 | minifyEnabled false
29 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
30 | }
31 | }
32 | compileOptions {
33 | sourceCompatibility JavaVersion.VERSION_1_8
34 | targetCompatibility JavaVersion.VERSION_1_8
35 | }
36 | kotlinOptions {
37 | jvmTarget = '1.8'
38 | }
39 | namespace 'cn.wearbbs.music'
40 | }
41 |
42 |
43 |
44 | dependencies {
45 | implementation fileTree(dir: "libs", include: ["*.aar","*.jar"])
46 | implementation 'androidx.core:core-ktx:1.7.0'
47 | implementation 'androidx.appcompat:appcompat:1.4.0'
48 | implementation 'com.google.android.material:material:1.4.0'
49 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
50 | implementation "androidx.viewpager2:viewpager2:1.0.0"
51 | implementation 'androidx.preference:preference-ktx:1.1.1'
52 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
53 | testImplementation 'junit:junit:4.13.2'
54 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
55 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
56 | implementation 'com.github.bumptech.glide:glide:4.12.0'
57 | implementation 'androidx.viewpager2:viewpager2:1.0.0'
58 | implementation 'androidx.recyclerview:recyclerview:1.2.1'
59 | implementation 'com.hyman:flowlayout-lib:1.1.2'
60 | implementation 'me.wcy:lrcview:2.2'
61 | implementation 'cn.carbs.android:ExpandableTextView:1.0.3'
62 | implementation 'me.panpf:sketch:2.7.1'
63 | implementation 'com.google.zxing:core:3.4.1'
64 | implementation 'com.alibaba:fastjson:1.2.79'
65 |
66 | def appCenterSdkVersion = '4.4.2'
67 | implementation "com.microsoft.appcenter:appcenter-analytics:${appCenterSdkVersion}"
68 | implementation "com.microsoft.appcenter:appcenter-crashes:${appCenterSdkVersion}"
69 |
70 | implementation 'org.greenrobot:eventbus:3.3.1'
71 | implementation 'com.android.support:percent:28.0.0'
72 | implementation 'com.github.youlookwhat:ByRecyclerView:1.1.6'
73 | implementation 'com.squareup.okhttp3:okhttp:4.9.3'
74 | implementation 'com.google.code.gson:gson:2.8.9'
75 | }
--------------------------------------------------------------------------------
/app/libs/ftplet-api-1.1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/libs/ftplet-api-1.1.1.jar
--------------------------------------------------------------------------------
/app/libs/ftpserver-core-1.1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/libs/ftpserver-core-1.1.1.jar
--------------------------------------------------------------------------------
/app/libs/log4j-1.2.17.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/libs/log4j-1.2.17.jar
--------------------------------------------------------------------------------
/app/libs/mina-core-2.0.16.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/libs/mina-core-2.0.16.jar
--------------------------------------------------------------------------------
/app/libs/slf4j-api-1.6.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/libs/slf4j-api-1.6.2.jar
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "cn.wearbbs.music",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 13,
15 | "versionName": "3.5.1",
16 | "outputFile": "app-release.apk"
17 | }
18 | ],
19 | "elementType": "File"
20 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/cn/wearbbs/music/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("cn.wearbbs.music", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
11 |
12 |
21 |
24 |
27 |
30 |
33 |
36 |
39 |
42 |
45 |
48 |
51 |
54 |
57 |
60 |
63 |
64 |
65 |
66 |
69 |
70 |
71 |
74 |
75 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/api/CloudSongApi.java:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.api;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONArray;
5 | import com.alibaba.fastjson.JSONObject;
6 | import com.google.gson.Gson;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.concurrent.LinkedTransferQueue;
11 |
12 | import cn.jackuxl.model.CloudSong;
13 | import cn.jackuxl.model.Song;
14 | import cn.jackuxl.model.SongUrl;
15 | import cn.jackuxl.model.result.PersonalFMResult;
16 | import cn.jackuxl.model.result.SongUrlResult;
17 | import cn.jackuxl.model.result.UserCloudResult;
18 | import cn.jackuxl.util.NetWorkUtil;
19 |
20 | public class CloudSongApi {
21 | private final String cookie;
22 | private final Gson gson = new Gson();
23 |
24 | public CloudSongApi(String cookie) {
25 | this.cookie = cookie;
26 | }
27 |
28 | public List getSongList() {
29 | UserCloudResult result = gson.fromJson(NetWorkUtil.sendByGetUrl("/user/cloud", cookie), UserCloudResult.class);
30 | if(result.getCode()!=200){
31 | return null;
32 | }
33 | List res = new ArrayList<>();
34 | for(int i = 0;i data = gson.fromJson(NetWorkUtil.sendByGetUrl("/song/url?id=" + stringBuilder, cookie),SongUrlResult.class).getData();
104 | String[] result = new String[data.size()];
105 | for (int i = 0; i < data.size(); i++) {
106 | result[searchArrayForIndex(ids, String.valueOf(data.get(i).getId()))] = data.get(i).getUrl();
107 | }
108 | return result;
109 | }
110 |
111 | private int searchArrayForIndex(String[] array, String str) {
112 | for (int i = 0; i < array.length; i++) {
113 | if (array[i].equals(str)) {
114 | return i;
115 | }
116 | }
117 | return -1;
118 | }
119 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/api/MVApi.java:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.api;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import cn.jackuxl.util.NetWorkUtil;
5 |
6 | public class MVApi {
7 | private final String cookie;
8 |
9 | public MVApi(String cookie) {
10 | this.cookie = cookie;
11 | }
12 |
13 | public String getMVUrl(String mvId) {
14 | String obj = NetWorkUtil.sendByGetUrl("/mv/url?id=" + mvId, cookie);
15 | return JSON.parseObject(obj).getJSONObject("data").getString("url");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/api/MusicListApi.java:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.api;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONArray;
5 | import cn.jackuxl.util.NetWorkUtil;
6 |
7 | public class MusicListApi {
8 | private final String uid;
9 | private final String cookie;
10 |
11 | public MusicListApi(String uid, String cookie) {
12 | this.uid = uid;
13 | this.cookie = cookie;
14 | }
15 |
16 | /**
17 | * 获取喜欢音乐列表
18 | *
19 | * @return ids
20 | */
21 | @Deprecated
22 | public String[] getLikeList() {
23 | JSONArray ids = JSON.parseObject(NetWorkUtil.sendByGetUrl("/likelist?uid=" + uid, cookie)).getJSONArray("ids");
24 | String[] result = new String[ids.size()];
25 | for (int i = 0; i < ids.size(); i++) {
26 | result[i] = ids.getString(i);
27 | }
28 | return result;
29 | }
30 |
31 | /**
32 | * 获取歌单列表
33 | *
34 | * @return data
35 | */
36 | public JSONArray getMusicList() {
37 | return JSON.parseObject(NetWorkUtil.sendByGetUrl("/user/playlist?uid=" + uid, cookie)).getJSONArray("playlist");
38 | }
39 |
40 | /**
41 | * 获取歌单详情
42 | *
43 | * @param id 歌单id
44 | * @return detail(ids)
45 | */
46 | public String[] getMusicListDetail(String id) {
47 | JSONArray trackIds = JSON.parseObject(NetWorkUtil.sendByGetUrl("/playlist/detail?id=" + id, cookie)).getJSONObject("playlist").getJSONArray("trackIds");
48 | String[] result = new String[trackIds.size()];
49 | for (int i = 0; i < trackIds.size(); i++) {
50 | result[i] = trackIds.getJSONObject(i).getString("id");
51 | }
52 | return result;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/Album.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import cn.jackuxl.model.info.Info
5 | import com.google.gson.annotations.SerializedName
6 |
7 |
8 | data class Album(
9 | @SerializedName("alias")
10 | val alias: List,
11 | @SerializedName("artist")
12 | val artist: Artist,
13 | @SerializedName("artists")
14 | val artists: List,
15 | @SerializedName("blurPicUrl")
16 | val blurPicUrl: String,
17 | @SerializedName("briefDesc")
18 | val briefDesc: String,
19 | @SerializedName("commentThreadId")
20 | val commentThreadId: String,
21 | @SerializedName("company")
22 | val company: Any,
23 | @SerializedName("companyId")
24 | val companyId: Int,
25 | @SerializedName("copyrightId")
26 | val copyrightId: Int,
27 | @SerializedName("description")
28 | val description: String,
29 | @SerializedName("id")
30 | val id: Int,
31 | @SerializedName("info")
32 | val info: Info,
33 | @SerializedName("mark")
34 | val mark: Int,
35 | @SerializedName("name")
36 | val name: String,
37 | @SerializedName("onSale")
38 | val onSale: Boolean,
39 | @SerializedName("paid")
40 | val paid: Boolean,
41 | @SerializedName("pic")
42 | val pic: Long,
43 | @SerializedName("picId")
44 | val picId: Long,
45 | @SerializedName("picId_str")
46 | val picIdStr: String,
47 | @SerializedName("picUrl")
48 | val picUrl: String,
49 | @SerializedName("publishTime")
50 | val publishTime: Long,
51 | @SerializedName("size")
52 | val size: Int,
53 | @SerializedName("songs")
54 | val songs: List,
55 | @SerializedName("status")
56 | val status: Int,
57 | @SerializedName("subType")
58 | val subType: String,
59 | @SerializedName("tags")
60 | val tags: String,
61 | @SerializedName("type")
62 | val type: String
63 | )
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/Artist.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Artist(
7 | @SerializedName("albumSize")
8 | val albumSize: Int,
9 | @SerializedName("alias")
10 | val alias: List,
11 | @SerializedName("id")
12 | val id: Int,
13 | @SerializedName("img1v1")
14 | val img1v1: Int,
15 | @SerializedName("img1v1Url")
16 | val img1v1Url: String,
17 | @SerializedName("name")
18 | var name: String? = "未知",
19 | @SerializedName("picId")
20 | val picId: Long,
21 | @SerializedName("picUrl")
22 | val picUrl: Any,
23 | @SerializedName("trans")
24 | val trans: Any
25 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/CloudSong.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class CloudSong(
7 | @SerializedName("addTime")
8 | val addTime: Long,
9 | @SerializedName("album")
10 | val album: String,
11 | @SerializedName("artist")
12 | val artist: String,
13 | @SerializedName("bitrate")
14 | val bitrate: Int,
15 | @SerializedName("cover")
16 | val cover: Int,
17 | @SerializedName("coverId")
18 | val coverId: String,
19 | @SerializedName("fileName")
20 | val fileName: String,
21 | @SerializedName("fileSize")
22 | val fileSize: Int,
23 | @SerializedName("lyricId")
24 | val lyricId: String,
25 | @SerializedName("simpleSong")
26 | val simpleSong: Song,
27 | @SerializedName("songId")
28 | val songId: Int,
29 | @SerializedName("songName")
30 | val songName: String,
31 | @SerializedName("version")
32 | val version: Int
33 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/CommentThread.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import cn.jackuxl.model.info.ResourceInfo
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class CommentThread(
8 | @SerializedName("commentCount")
9 | val commentCount: Int,
10 | @SerializedName("hotCount")
11 | val hotCount: Int,
12 | @SerializedName("id")
13 | val id: String,
14 | @SerializedName("latestLikedUsers")
15 | val latestLikedUsers: Any,
16 | @SerializedName("likedCount")
17 | val likedCount: Int,
18 | @SerializedName("resourceId")
19 | val resourceId: Int,
20 | @SerializedName("resourceInfo")
21 | val resourceInfo: ResourceInfo,
22 | @SerializedName("resourceOwnerId")
23 | val resourceOwnerId: Int,
24 | @SerializedName("resourceTitle")
25 | val resourceTitle: String,
26 | @SerializedName("resourceType")
27 | val resourceType: Int,
28 | @SerializedName("shareCount")
29 | val shareCount: Int
30 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/Song.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Song(
7 | @SerializedName("album",alternate = ["al"])
8 | val album: Album,
9 | @SerializedName("alias")
10 | val alias: List,
11 | @SerializedName("artists", alternate = ["ar"])
12 | val artists: List,
13 | @SerializedName("copyrightId")
14 | val copyrightId: Int,
15 | @SerializedName("duration")
16 | val duration: Int,
17 | @SerializedName("fee")
18 | val fee: Int,
19 | @SerializedName("ftype")
20 | val ftype: Int,
21 | @SerializedName("id")
22 | val id: Int,
23 | @SerializedName("mark")
24 | val mark: Long,
25 | @SerializedName("mvid")
26 | val mvid: Int,
27 | @SerializedName("name")
28 | val name: String,
29 | @SerializedName("rUrl")
30 | val rUrl: Any,
31 | @SerializedName("rtype")
32 | val rtype: Int,
33 | @SerializedName("status")
34 | val status: Int
35 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/SongUrl.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model
2 |
3 |
4 | import cn.jackuxl.model.privilege.FreeTimeTrialPrivilege
5 | import cn.jackuxl.model.privilege.FreeTrialPrivilege
6 | import com.google.gson.annotations.SerializedName
7 |
8 | data class SongUrl(
9 | @SerializedName("br")
10 | val br: Int,
11 | @SerializedName("canExtend")
12 | val canExtend: Boolean,
13 | @SerializedName("code")
14 | val code: Int,
15 | @SerializedName("encodeType")
16 | val encodeType: String,
17 | @SerializedName("expi")
18 | val expi: Int,
19 | @SerializedName("fee")
20 | val fee: Int,
21 | @SerializedName("flag")
22 | val flag: Int,
23 | @SerializedName("freeTimeTrialPrivilege")
24 | val freeTimeTrialPrivilege: FreeTimeTrialPrivilege,
25 | @SerializedName("freeTrialInfo")
26 | val freeTrialInfo: Any,
27 | @SerializedName("freeTrialPrivilege")
28 | val freeTrialPrivilege: FreeTrialPrivilege,
29 | @SerializedName("gain")
30 | val gain: Float,
31 | @SerializedName("id")
32 | val id: Int,
33 | @SerializedName("level")
34 | val level: String,
35 | @SerializedName("md5")
36 | val md5: String,
37 | @SerializedName("payed")
38 | val payed: Int,
39 | @SerializedName("size")
40 | val size: Int,
41 | @SerializedName("type")
42 | val type: String,
43 | @SerializedName("uf")
44 | val uf: Any,
45 | @SerializedName("url")
46 | val url: String,
47 | @SerializedName("urlSource")
48 | val urlSource: Int
49 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/info/ChargeInfo.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.info
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class ChargeInfo(
7 | @SerializedName("chargeMessage")
8 | val chargeMessage: Any,
9 | @SerializedName("chargeType")
10 | val chargeType: Int,
11 | @SerializedName("chargeUrl")
12 | val chargeUrl: Any,
13 | @SerializedName("rate")
14 | val rate: Int
15 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/info/Info.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.info
2 |
3 |
4 | import cn.jackuxl.model.CommentThread
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class Info(
8 | @SerializedName("commentCount")
9 | val commentCount: Int,
10 | @SerializedName("commentThread")
11 | val commentThread: CommentThread,
12 | @SerializedName("comments")
13 | val comments: Any,
14 | @SerializedName("latestLikedUsers")
15 | val latestLikedUsers: Any,
16 | @SerializedName("liked")
17 | val liked: Boolean,
18 | @SerializedName("likedCount")
19 | val likedCount: Int,
20 | @SerializedName("resourceId")
21 | val resourceId: Int,
22 | @SerializedName("resourceType")
23 | val resourceType: Int,
24 | @SerializedName("shareCount")
25 | val shareCount: Int,
26 | @SerializedName("threadId")
27 | val threadId: String
28 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/info/ResourceInfo.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.info
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class ResourceInfo(
7 | @SerializedName("creator")
8 | val creator: Any,
9 | @SerializedName("encodedId")
10 | val encodedId: Any,
11 | @SerializedName("id")
12 | val id: Int,
13 | @SerializedName("imgUrl")
14 | val imgUrl: String,
15 | @SerializedName("name")
16 | val name: String,
17 | @SerializedName("subTitle")
18 | val subTitle: Any,
19 | @SerializedName("userId")
20 | val userId: Int,
21 | @SerializedName("webUrl")
22 | val webUrl: Any
23 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/privilege/FreeTimeTrialPrivilege.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.privilege
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class FreeTimeTrialPrivilege(
7 | @SerializedName("remainTime")
8 | val remainTime: Int,
9 | @SerializedName("resConsumable")
10 | val resConsumable: Boolean,
11 | @SerializedName("type")
12 | val type: Int,
13 | @SerializedName("userConsumable")
14 | val userConsumable: Boolean
15 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/privilege/FreeTrialPrivilege.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.privilege
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class FreeTrialPrivilege(
7 | @SerializedName("listenType")
8 | val listenType: Any,
9 | @SerializedName("resConsumable")
10 | val resConsumable: Boolean,
11 | @SerializedName("userConsumable")
12 | val userConsumable: Boolean
13 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/privilege/Privilege.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.privilege
2 |
3 |
4 | import cn.jackuxl.model.info.ChargeInfo
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class Privilege(
8 | @SerializedName("chargeInfoList")
9 | val chargeInfoList: List,
10 | @SerializedName("cp")
11 | val cp: Long,
12 | @SerializedName("cs")
13 | val cs: Boolean,
14 | @SerializedName("dl")
15 | val dl: Long,
16 | @SerializedName("downloadMaxbr")
17 | val downloadMaxbr: Long,
18 | @SerializedName("fee")
19 | val fee: Long,
20 | @SerializedName("fl")
21 | val fl: Long,
22 | @SerializedName("flag")
23 | val flag: Long,
24 | @SerializedName("freeTrialPrivilege")
25 | val freeTrialPrivilege: FreeTrialPrivilege,
26 | @SerializedName("id")
27 | val id: Long,
28 | @SerializedName("maxbr")
29 | val maxbr: Long,
30 | @SerializedName("payed")
31 | val payed: Long,
32 | @SerializedName("pl")
33 | val pl: Long,
34 | @SerializedName("playMaxbr")
35 | val playMaxbr: Long,
36 | @SerializedName("preSell")
37 | val preSell: Boolean,
38 | @SerializedName("rscl")
39 | val rscl: Long,
40 | @SerializedName("sp")
41 | val sp: Long,
42 | @SerializedName("st")
43 | val st: Long,
44 | @SerializedName("subp")
45 | val subp: Long,
46 | @SerializedName("toast")
47 | val toast: Boolean
48 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/AlbumResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.model.Album
5 | import cn.jackuxl.model.Song
6 | import com.google.gson.annotations.SerializedName
7 |
8 | data class AlbumResult(
9 | @SerializedName("album")
10 | val album: Album,
11 | @SerializedName("code")
12 | val code: Int,
13 | @SerializedName("resourceState")
14 | val resourceState: Boolean,
15 | @SerializedName("songs")
16 | val songs: List
17 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/PersonalFMResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.model.Song
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class PersonalFMResult(
8 | @SerializedName("code")
9 | val code: Int,
10 | @SerializedName("data")
11 | val data: List,
12 | @SerializedName("popAdjust")
13 | val popAdjust: Boolean
14 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/Result.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class Result(
7 | @SerializedName("hots")
8 | val hots: List
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SearchHot.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class SearchHot(
7 | @SerializedName("first")
8 | val first: String,
9 | @SerializedName("iconType")
10 | val iconType: Int,
11 | @SerializedName("second")
12 | val second: Int,
13 | @SerializedName("third")
14 | val third: Any
15 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SearchHotResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class SearchHotResult(
7 | @SerializedName("code")
8 | val code: Int,
9 | @SerializedName("result")
10 | val result: Result
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SearchResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import com.google.gson.annotations.SerializedName
5 |
6 | data class SearchResult(
7 | @SerializedName("code")
8 | val code: Int,
9 | @SerializedName("result")
10 | val result: SongResult
11 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SongDetailResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.model.Song
5 | import cn.jackuxl.model.privilege.Privilege
6 | import com.google.gson.annotations.SerializedName
7 |
8 | data class SongDetailResult(
9 | @SerializedName("code")
10 | val code: Int,
11 | @SerializedName("privileges")
12 | val privileges: List,
13 | @SerializedName("songs")
14 | val songs: List
15 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SongResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.model.Song
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class SongResult(
8 | @SerializedName("hasMore")
9 | val hasMore: Boolean,
10 | @SerializedName("songCount")
11 | val songCount: Int,
12 | @SerializedName("songs")
13 | val songs: List
14 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/SongUrlResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.model.SongUrl
5 | import com.google.gson.annotations.SerializedName
6 |
7 | data class SongUrlResult(
8 | @SerializedName("code")
9 | val code: Int,
10 | @SerializedName("data")
11 | val data: List
12 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/model/result/UserCloudResult.kt:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.model.result
2 |
3 |
4 | import cn.jackuxl.api.CloudSongApi
5 | import cn.jackuxl.model.CloudSong
6 | import com.google.gson.annotations.SerializedName
7 |
8 | data class UserCloudResult(
9 | @SerializedName("code")
10 | val code: Int,
11 | @SerializedName("count")
12 | val count: Int,
13 | @SerializedName("data")
14 | val data: List,
15 | @SerializedName("hasMore")
16 | val hasMore: Boolean,
17 | @SerializedName("maxSize")
18 | val maxSize: String,
19 | @SerializedName("size")
20 | val size: String,
21 | @SerializedName("upgradeSign")
22 | val upgradeSign: Int
23 | )
--------------------------------------------------------------------------------
/app/src/main/java/cn/jackuxl/util/NetWorkUtil.java:
--------------------------------------------------------------------------------
1 | package cn.jackuxl.util;
2 |
3 | import okhttp3.OkHttpClient;
4 | import okhttp3.Request;
5 | import okhttp3.Response;
6 |
7 | import java.io.IOException;
8 | import java.io.UnsupportedEncodingException;
9 | import java.net.URLEncoder;
10 | import java.util.Objects;
11 |
12 | /**
13 | * @author JackuXL
14 | */
15 | public class NetWorkUtil {
16 | public static String domain;
17 |
18 | /**
19 | * 设置主域名
20 | * 添加在请求地址前
21 | *
22 | * @param domain 主域名(格式:http(s)://example.com)
23 | */
24 | public static void setDomain(String domain) {
25 | NetWorkUtil.domain = domain;
26 | }
27 |
28 | /**
29 | * GET请求
30 | *
31 | * @param url 地址(删除主域名)
32 | * @param cookie Cookie(可为Null)
33 | * @return 请求结果
34 | */
35 | public static String sendByGetUrl(String url, String cookie) {
36 | if (cookie == null) {
37 | cookie = "";
38 | }
39 | String result;
40 | OkHttpClient client = new OkHttpClient().newBuilder().build();
41 | Request request;
42 | request = new Request.Builder()
43 | .url(appendUrl(NetWorkUtil.domain + url,"cookie",cookie))
44 | .build();
45 | Response response;
46 | try {
47 | response = client.newCall(request).execute();
48 | result = Objects.requireNonNull(response.body()).string();
49 | return result;
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | }
53 | return null;
54 | }
55 | /**
56 | * 在指定url后追加参数
57 | * @param url 地址
58 | * @return 处理后 Url
59 | */
60 | private static String appendUrl(String url, String key,String value) {
61 | String newUrl = url;
62 | try {
63 | value = URLEncoder.encode(value,"utf-8");
64 | } catch (UnsupportedEncodingException e) {
65 | e.printStackTrace();
66 | }
67 | String paramStr = key + "=" + value;
68 | if (newUrl.contains("?")) {
69 | newUrl += "&" + paramStr;
70 | } else {
71 | newUrl += "?" + paramStr;
72 | }
73 | return newUrl;
74 | }
75 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/adapter/MusicLibraryAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.adapter;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ImageView;
9 | import android.widget.LinearLayout;
10 | import android.widget.TextView;
11 |
12 | import androidx.annotation.NonNull;
13 | import androidx.recyclerview.widget.RecyclerView;
14 |
15 | import com.alibaba.fastjson.JSONArray;
16 | import com.alibaba.fastjson.JSONObject;
17 | import com.bumptech.glide.Glide;
18 | import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
19 | import com.bumptech.glide.request.RequestOptions;
20 |
21 | import org.jetbrains.annotations.NotNull;
22 |
23 | import cn.wearbbs.music.R;
24 | import cn.wearbbs.music.ui.MusicListActivity;
25 |
26 | public class MusicLibraryAdapter extends RecyclerView.Adapter {
27 | private final JSONArray data;
28 | private final Activity activity;
29 |
30 | public MusicLibraryAdapter(JSONArray data, Activity activity) {
31 | this.data = data;
32 | this.activity = activity;
33 | }
34 |
35 | @NotNull
36 | @Override
37 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
38 | View view = LayoutInflater.from(activity).inflate(R.layout.item_music, parent, false);
39 | return new ViewHolder(view);
40 | }
41 |
42 | @Override
43 | public void onBindViewHolder(@NonNull final ViewHolder viewHolder, int position) {
44 | JSONObject playListDetail = data.getJSONObject(position);
45 | viewHolder.tv_title.setText(playListDetail.getString("name"));
46 | viewHolder.tv_artists.setText(String.format("by %s", playListDetail.getJSONObject("creator").getString("nickname")));
47 | RequestOptions options = RequestOptions.bitmapTransform(new RoundedCorners(10)).placeholder(R.drawable.ic_baseline_photo_size_select_actual_24).error(R.drawable.ic_baseline_photo_size_select_actual_24);
48 | viewHolder.iv_cover.setImageResource(R.drawable.ic_baseline_photo_size_select_actual_24);
49 | try{
50 | Glide.with(activity).load(playListDetail.getString("coverImgUrl").replace("http://", "https://")).apply(options).into(viewHolder.iv_cover);
51 | }
52 | catch (Exception ignored){
53 | ignored.printStackTrace();
54 | }
55 | viewHolder.ll_main.setOnClickListener(v -> {
56 | Intent intent = new Intent(activity, MusicListActivity.class);
57 | intent.putExtra("detail", playListDetail.toJSONString());
58 | activity.startActivity(intent);
59 | });
60 |
61 | }
62 |
63 | @Override
64 | public int getItemCount() {
65 | return data.size();
66 | }
67 |
68 | static class ViewHolder extends RecyclerView.ViewHolder {
69 | ImageView iv_cover;
70 | TextView tv_title;
71 | TextView tv_artists;
72 | LinearLayout ll_main;
73 |
74 | public ViewHolder(@NonNull View itemView) {
75 | super(itemView);
76 | iv_cover = itemView.findViewById(R.id.iv_cover);
77 | tv_title = itemView.findViewById(R.id.tv_title);
78 | tv_artists = itemView.findViewById(R.id.tv_artists);
79 | ll_main = itemView.findViewById(R.id.ll_main);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/adapter/ViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.adapter;
2 |
3 | import android.content.Intent;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.fragment.app.Fragment;
7 | import androidx.fragment.app.FragmentActivity;
8 | import androidx.viewpager2.adapter.FragmentStateAdapter;
9 |
10 | import cn.wearbbs.music.fragment.ConsoleFragment;
11 | import cn.wearbbs.music.fragment.LyricsFragment;
12 | import cn.wearbbs.music.fragment.PlayerFragment;
13 |
14 | public class ViewPagerAdapter extends FragmentStateAdapter {
15 | private final Intent intent;
16 |
17 | public ViewPagerAdapter(@NonNull FragmentActivity fragmentActivity, Intent intent) {
18 | super(fragmentActivity);
19 | this.intent = intent;
20 | }
21 |
22 | @NonNull
23 | @Override
24 | public Fragment createFragment(int position) {
25 | if (position == 0) {
26 | return PlayerFragment.newInstance(intent);
27 | } else if(position==1){
28 | return LyricsFragment.newInstance(intent);
29 | }
30 | else{
31 | return ConsoleFragment.newInstance(intent);
32 | }
33 | }
34 |
35 | @Override
36 | public int getItemCount() {
37 | return 3;
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/api/AppServiceApi.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.api;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 |
6 | import java.net.URLEncoder;
7 |
8 | import cn.wearbbs.music.application.MainApplication;
9 | import cn.wearbbs.music.util.SharedPreferencesUtil;
10 | import cn.jackuxl.util.NetWorkUtil;
11 |
12 | public class AppServiceApi {
13 | public static JSONObject getLatestVersionInfo() {
14 | NetWorkUtil.setDomain("");
15 | JSONObject result = JSON.parseObject(NetWorkUtil.sendByGetUrl("https://wmusic.wearbbs.cn/AppService/update.json", null));
16 | resetServer();
17 | return result;
18 | }
19 |
20 | public static boolean feedback(String content) {
21 | NetWorkUtil.setDomain("");
22 | String token = "C6ZdL45yZgBjHCmk";
23 | int code = 400;
24 | try{
25 | code = JSON.parseObject(NetWorkUtil.sendByGetUrl(String.format("https://wmusic.wearbbs.cn/AppService/feedback/?token=%s&content=%s", token, URLEncoder.encode(content, "utf-8")), null)).getInteger("code");
26 | }
27 | catch (Exception ignored){ }
28 | resetServer();
29 | return code == 200;
30 | }
31 |
32 | public static void resetServer(){
33 | NetWorkUtil.setDomain("https://api.wmusic.pro");
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/application/MainApplication.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.application;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Application;
5 | import android.content.Context;
6 | import android.content.pm.PackageInfo;
7 | import android.content.pm.PackageManager;
8 |
9 | import com.microsoft.appcenter.AppCenter;
10 | import com.microsoft.appcenter.analytics.Analytics;
11 | import com.microsoft.appcenter.crashes.Crashes;
12 |
13 | /**
14 | * @author JackuXL
15 | */
16 | public class MainApplication extends Application {
17 |
18 | @SuppressLint("StaticFieldLeak")
19 | private static Context context;
20 | @Override
21 | public void onCreate() {
22 | super.onCreate();
23 | AppCenter.start(this, "2d48333f-2592-446d-a227-7102be9ab4dd", Analytics.class, Crashes.class);
24 | context = getApplicationContext();
25 | }
26 | public static Context getContext(){
27 | return context;
28 | }
29 | // 获取应用版本号
30 | public static String getApplicationVersion() {
31 | try {
32 | PackageManager packageManager = context.getPackageManager();
33 | PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
34 | return packageInfo.versionName;
35 | } catch (Exception e) {
36 | e.printStackTrace();
37 | return "0.0.0";
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/event/MessageEvent.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.event;
2 |
3 | public class MessageEvent {
4 | public final String msg;
5 |
6 | public MessageEvent(String msg) {
7 | this.msg = msg;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.TextView;
8 |
9 | import java.util.Locale;
10 |
11 | import cn.wearbbs.music.R;
12 | import cn.wearbbs.music.application.MainApplication;
13 |
14 | /**
15 | * 关于
16 | */
17 | public class AboutActivity extends SlideBackActivity {
18 |
19 | @SuppressLint("StringFormatMatches")
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_about);
24 | TextView tv_content = findViewById(R.id.tv_content);
25 | tv_content.setText(String.format(getString(R.string.aboutContent),MainApplication.getApplicationVersion()));
26 | }
27 |
28 | @SuppressLint("NonConstantResourceId")
29 | public void onClick(View view) {
30 | switch (view.getId()) {
31 | case R.id.main_title:
32 | finish();
33 | break;
34 | case R.id.ll_checkUpdate:
35 | startActivity(new Intent(AboutActivity.this, UpdateActivity.class));
36 | break;
37 | case R.id.ll_feedback:
38 | startActivity(new Intent(AboutActivity.this, FeedbackActivity.class));
39 | break;
40 | }
41 |
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/CommentActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.recyclerview.widget.LinearLayoutManager;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import com.alibaba.fastjson.JSONArray;
13 |
14 | import cn.jackuxl.api.SongApi;
15 | import cn.wearbbs.music.R;
16 | import cn.wearbbs.music.adapter.CommentAdapter;
17 | import cn.wearbbs.music.util.SharedPreferencesUtil;
18 | import cn.wearbbs.music.view.MessageView;
19 |
20 | public class CommentActivity extends AppCompatActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_comment);
26 | init();
27 | }
28 |
29 | public void init(){
30 | SongApi api = new SongApi(SharedPreferencesUtil.getString("cookie",""));
31 | RecyclerView rv_main = findViewById(R.id.rv_main);
32 | rv_main.setLayoutManager(new LinearLayoutManager(this));
33 | new Thread(()->{
34 | try{
35 | JSONArray data = api.getHotComment(getIntent().getStringExtra("id"));
36 | runOnUiThread(()->{
37 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
38 | if(SharedPreferencesUtil.getString("cookie","").isEmpty()){
39 | rv_main.setAdapter(new CommentAdapter(data,getIntent().getStringExtra("id"),this));
40 | }
41 | else{
42 | rv_main.setAdapter(new CommentAdapter(data,getIntent().getStringExtra("id"),this,getHeader()));
43 | }
44 | rv_main.setVisibility(View.VISIBLE);
45 | });
46 | }
47 | catch (Exception e){
48 | runOnUiThread(this::showErrorMessage);
49 | }
50 | }).start();
51 |
52 | }
53 | public View getHeader(){
54 | RecyclerView rv_main = findViewById(R.id.rv_main);
55 | View header = LayoutInflater.from(this).inflate(R.layout.widget_reply, rv_main, false);
56 | header.findViewById(R.id.tv_sendreply).setOnClickListener(v -> {
57 | startActivity(new Intent(CommentActivity.this,ReplyActivity.class).putExtra("id", getIntent().getStringExtra("id")));
58 | });
59 | return header;
60 | }
61 |
62 | public void onClick(View view){
63 | finish();
64 | }
65 |
66 | public void showErrorMessage(){
67 | RecyclerView rv_main = findViewById(R.id.rv_main);
68 | rv_main.setVisibility(View.GONE);
69 |
70 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
71 |
72 | MessageView mv_message = findViewById(R.id.mv_message);
73 | mv_message.setVisibility(View.VISIBLE);
74 | mv_message.setContent(MessageView.LOAD_FAILED, v -> {
75 | mv_message.setVisibility(View.GONE);
76 | init();
77 | });
78 | }
79 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/FeedbackActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.os.Looper;
7 | import android.view.View;
8 | import android.widget.EditText;
9 | import android.widget.Toast;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 |
13 | import com.alibaba.fastjson.JSONObject;
14 |
15 | import cn.wearbbs.music.R;
16 | import cn.wearbbs.music.api.AppServiceApi;
17 | import cn.wearbbs.music.util.ToastUtil;
18 | import cn.wearbbs.music.view.MessageView;
19 |
20 | public class FeedbackActivity extends AppCompatActivity {
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_feedback);
26 | init();
27 | }
28 |
29 | @SuppressLint("NonConstantResourceId")
30 | public void onClick(View view) {
31 | switch (view.getId()) {
32 | case R.id.main_title:
33 | case R.id.main_title_info:
34 | finish();
35 | break;
36 | case R.id.btn_submit:
37 | EditText et_content = findViewById(R.id.et_content);
38 | new Thread(()->{
39 | if(AppServiceApi.feedback(et_content.getText().toString())){
40 | ToastUtil.show(FeedbackActivity.this,"提交成功");
41 | }
42 | else{
43 | ToastUtil.show(FeedbackActivity.this,"提交失败");
44 | }
45 | finish();
46 | }).start();
47 | break;
48 | }
49 | }
50 |
51 | public void init(){
52 | findViewById(R.id.ll_info).setVisibility(View.VISIBLE);
53 | new Thread(()->{
54 | JSONObject data = UpdateActivity.checkUpdate();
55 | if(data==null){
56 | runOnUiThread(this::showErrorMessage);
57 | }
58 | else if(data.getBoolean("needUpdate")){
59 | ToastUtil.show(FeedbackActivity.this,"请先更新");
60 | Intent intent = new Intent(FeedbackActivity.this, UpdateActivity.class);
61 | startActivity(intent);
62 | finish();
63 |
64 |
65 | }
66 | else{
67 | runOnUiThread(()->{
68 | findViewById(R.id.ll_info).setVisibility(View.GONE);
69 | findViewById(R.id.ll_feedback).setVisibility(View.VISIBLE);
70 | });
71 | }
72 | }).start();
73 | }
74 |
75 | public void showErrorMessage(){
76 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
77 |
78 | MessageView mv_message = findViewById(R.id.mv_message);
79 | mv_message.setVisibility(View.VISIBLE);
80 | mv_message.setContent(MessageView.LOAD_FAILED, v -> {
81 | mv_message.setVisibility(View.GONE);
82 | init();
83 | });
84 | }
85 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/MenuActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 |
10 | import androidx.appcompat.app.AlertDialog;
11 |
12 | import com.alibaba.fastjson.JSON;
13 | import com.alibaba.fastjson.JSONObject;
14 | import com.bumptech.glide.Glide;
15 | import com.bumptech.glide.request.RequestOptions;
16 |
17 | import cn.jackuxl.api.UserApi;
18 | import cn.wearbbs.music.R;
19 | import cn.wearbbs.music.util.SharedPreferencesUtil;
20 | import cn.jackuxl.util.NetWorkUtil;
21 |
22 | /**
23 | * 菜单
24 | */
25 | public class MenuActivity extends SlideBackActivity {
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_menu);
31 | JSONObject profile = SharedPreferencesUtil.getJSONObject("profile");
32 | if (SharedPreferencesUtil.getJSONObject("profile").size() >= 5) {
33 | initUserItem(profile);
34 | }
35 | }
36 |
37 | @Override
38 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
39 | super.onActivityResult(requestCode, resultCode, data);
40 | if(resultCode == RESULT_OK){
41 | switch (requestCode){
42 | case 0:
43 | JSONObject profile = JSON.parseObject(data.getStringExtra("profile"));
44 | initUserItem(profile);
45 | startActivity(new Intent(MenuActivity.this,MenuActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
46 | finish();
47 | break;
48 | case 1:
49 | startActivity(new Intent(MenuActivity.this,MenuActivity.class).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP).addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
50 | finish();
51 | break;
52 | }
53 | }
54 | }
55 |
56 | public void initUserItem(JSONObject profile) {
57 | TextView tv_name = findViewById(R.id.tv_name);
58 | tv_name.setText(profile.getString("nickname"));
59 | TextView tv_id = findViewById(R.id.tv_id);
60 | tv_id.setText(String.format("ID:%s",profile.getString("userId")));
61 | ImageView iv_avatar = findViewById(R.id.iv_avatar);
62 | RequestOptions options = RequestOptions.circleCropTransform().placeholder(R.drawable.ic_baseline_supervised_user_circle_24).error(R.drawable.ic_baseline_supervised_user_circle_24);
63 | Glide.with(MenuActivity.this).load(profile.getString("avatarUrl").replace("http://", "https://")).apply(options).into(iv_avatar);
64 | }
65 |
66 | @SuppressLint("NonConstantResourceId")
67 | public void onClick(View view) {
68 | switch (view.getId()) {
69 | case R.id.item_fm:
70 | startActivity(new Intent(MenuActivity.this, MainActivity.class)
71 | .putExtra("fm",true)
72 | .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
73 | .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
74 | break;
75 | case R.id.item_setting:
76 | startActivity(new Intent(MenuActivity.this, SettingsActivity.class));
77 | break;
78 | case R.id.item_user:
79 | if (SharedPreferencesUtil.getJSONObject("profile").size() <= 5) {
80 | startActivityForResult(new Intent(MenuActivity.this, LoginActivity.class), 0);
81 | } else {
82 | startActivityForResult(new Intent(MenuActivity.this, UserProfileActivity.class), 1);
83 | }
84 | break;
85 | case R.id.item_search:
86 | startActivity(new Intent(MenuActivity.this, SearchActivity.class));
87 | break;
88 | case R.id.item_musicPan:
89 | startActivity(new Intent(MenuActivity.this, MusicPanActivity.class));
90 | break;
91 | case R.id.item_likeList:
92 | startActivity(new Intent(MenuActivity.this, MusicListActivity.class));
93 | break;
94 | case R.id.item_musicLibrary:
95 | startActivity(new Intent(MenuActivity.this, MusicLibraryActivity.class));
96 | break;
97 | case R.id.item_localmusic:
98 | startActivity(new Intent(MenuActivity.this, LocalMusicActivity.class));
99 | break;
100 | }
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/MusicLibraryActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.recyclerview.widget.LinearLayoutManager;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | import com.alibaba.fastjson.JSONArray;
13 |
14 | import cn.jackuxl.api.MusicListApi;
15 | import cn.wearbbs.music.R;
16 | import cn.wearbbs.music.adapter.MusicLibraryAdapter;
17 | import cn.wearbbs.music.util.SharedPreferencesUtil;
18 | import cn.wearbbs.music.view.LoadingView;
19 | import cn.wearbbs.music.view.MessageView;
20 |
21 | /**
22 | * 歌单列表
23 | */
24 | public class MusicLibraryActivity extends AppCompatActivity {
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_music);
30 | TextView tv_title = findViewById(R.id.tv_title);
31 | tv_title.setText(getString(R.string.musicLibrary));
32 | init();
33 | }
34 |
35 | public void init(){
36 | MusicListApi api = new MusicListApi(SharedPreferencesUtil.getJSONObject("profile").getString("userId"), SharedPreferencesUtil.getString("cookie", ""));
37 | LoadingView lv_loading = findViewById(R.id.lv_loading);
38 | RecyclerView rv_main = findViewById(R.id.rv_main);
39 | MessageView mv_message = findViewById(R.id.mv_message);
40 | if(SharedPreferencesUtil.getString("cookie", "").isEmpty()){
41 | showNoLoginMessage();
42 | }
43 | else{
44 | new Thread(() -> {
45 | try{
46 | lv_loading.setVisibility(View.VISIBLE);
47 | rv_main.setVisibility(View.GONE);
48 | JSONArray data = api.getMusicList();
49 | runOnUiThread(() -> {
50 | if(data==null){
51 | showErrorMessage();
52 | }
53 | else if (data.size() == 0) {
54 | rv_main.setVisibility(View.GONE);
55 | mv_message.setVisibility(View.VISIBLE);
56 | mv_message.setContent(MessageView.NO_LOGIN,null);
57 | } else {
58 | rv_main.setLayoutManager(new LinearLayoutManager(this));
59 | rv_main.setAdapter(new MusicLibraryAdapter(data, this));
60 | lv_loading.setVisibility(View.GONE);
61 | rv_main.setVisibility(View.VISIBLE);
62 | }
63 | });
64 | }
65 | catch (Exception e){
66 | runOnUiThread(this::showErrorMessage);
67 | }
68 | }).start();
69 | }
70 | }
71 |
72 | public void onClick(View view) {
73 | Intent intent = new Intent(MusicLibraryActivity.this, MenuActivity.class);
74 | intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
75 | startActivity(intent);
76 | finish();
77 | }
78 |
79 | public void showNoLoginMessage() {
80 | RecyclerView rv_main = findViewById(R.id.rv_main);
81 | rv_main.setVisibility(View.GONE);
82 | MessageView mv_message = findViewById(R.id.mv_message);
83 | mv_message.setVisibility(View.VISIBLE);
84 | mv_message.setContent(MessageView.NO_LOGIN,null);
85 | }
86 |
87 | public void showErrorMessage(){
88 | RecyclerView rv_main = findViewById(R.id.rv_main);
89 | MessageView mv_message = findViewById(R.id.mv_message);
90 | rv_main.setVisibility(View.GONE);
91 | mv_message.setVisibility(View.VISIBLE);
92 | mv_message.setContent(MessageView.LOAD_FAILED, v -> {
93 | mv_message.setVisibility(View.GONE);
94 | init();
95 | });
96 | }
97 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/MusicPanActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 | import androidx.recyclerview.widget.LinearLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.alibaba.fastjson.JSONArray;
12 |
13 | import java.util.List;
14 |
15 | import cn.jackuxl.api.CloudSongApi;
16 | import cn.jackuxl.model.Song;
17 | import cn.wearbbs.music.R;
18 | import cn.wearbbs.music.adapter.MusicAdapter;
19 | import cn.wearbbs.music.adapter.SongAdapter;
20 | import cn.wearbbs.music.util.SharedPreferencesUtil;
21 | import cn.wearbbs.music.view.LoadingView;
22 | import cn.wearbbs.music.view.MessageView;
23 | import me.jingbin.library.ByRecyclerView;
24 |
25 | /**
26 | * 音乐云盘
27 | */
28 | public class MusicPanActivity extends SlideBackActivity {
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_music);
34 | TextView tv_title = findViewById(R.id.tv_title);
35 | tv_title.setText(getString(R.string.musicPan));
36 | init();
37 | }
38 |
39 | public void init() {
40 | if(SharedPreferencesUtil.getString("cookie", "").isEmpty()){
41 | showNoLoginMessage();
42 | }
43 | else{
44 | CloudSongApi api = new CloudSongApi(SharedPreferencesUtil.getString("cookie", ""));
45 | LoadingView lv_loading = findViewById(R.id.lv_loading);
46 | ByRecyclerView rv_main = findViewById(R.id.rv_main);
47 | MessageView mv_message = findViewById(R.id.mv_message);
48 | new Thread(() -> {
49 | try{
50 | lv_loading.setVisibility(View.VISIBLE);
51 | rv_main.setVisibility(View.GONE);
52 | List data = api.getSongList();
53 | runOnUiThread(() -> {
54 | System.out.println(data);
55 | if (data.size() == 0) {
56 | rv_main.setVisibility(View.GONE);
57 | mv_message.setVisibility(View.VISIBLE);
58 | mv_message.setContent(MessageView.NO_MUSIC,null);
59 | } else {
60 | rv_main.setLayoutManager(new LinearLayoutManager(this));
61 | rv_main.setAdapter(new SongAdapter(data, this));
62 | rv_main.setOnRefreshListener(() -> {
63 | // 刷新完成
64 | //rv_main.setRefreshing(false);
65 | });
66 | lv_loading.setVisibility(View.GONE);
67 | rv_main.setVisibility(View.VISIBLE);
68 | }
69 | });
70 | }
71 | catch (Exception e){
72 | runOnUiThread(()->{
73 | mv_message.setVisibility(View.VISIBLE);
74 | mv_message.setContent(MessageView.LOAD_FAILED, v -> {
75 | mv_message.setVisibility(View.GONE);
76 | init();
77 | });
78 | });
79 | }
80 | }).start();
81 | }
82 | }
83 |
84 | public void showNoLoginMessage() {
85 | RecyclerView rv_main = findViewById(R.id.rv_main);
86 | rv_main.setVisibility(View.GONE);
87 | MessageView mv_message = findViewById(R.id.mv_message);
88 | mv_message.setVisibility(View.VISIBLE);
89 | mv_message.setContent(MessageView.NO_LOGIN,null);
90 | }
91 |
92 | public void onClick(View view) {
93 | Intent intent = new Intent(MusicPanActivity.this, MenuActivity.class);
94 | intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
95 | startActivity(intent);
96 | finish();
97 | }
98 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/OpenSourceActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 |
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | import cn.wearbbs.music.R;
9 |
10 | public class OpenSourceActivity extends AppCompatActivity {
11 |
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | setContentView(R.layout.activity_opensource);
16 | }
17 |
18 | public void onClick(View view){
19 | finish();
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/PlayListActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.TextView;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 | import androidx.recyclerview.widget.LinearLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.alibaba.fastjson.JSON;
12 | import com.alibaba.fastjson.JSONArray;
13 |
14 | import org.greenrobot.eventbus.EventBus;
15 | import org.greenrobot.eventbus.Subscribe;
16 | import org.greenrobot.eventbus.ThreadMode;
17 |
18 | import cn.wearbbs.music.R;
19 | import cn.wearbbs.music.adapter.LocalMusicAdapter;
20 | import cn.wearbbs.music.adapter.MusicAdapter;
21 | import cn.wearbbs.music.event.MessageEvent;
22 | import cn.wearbbs.music.view.LoadingView;
23 |
24 | public class PlayListActivity extends AppCompatActivity {
25 | private JSONArray data;
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_music);
30 | EventBus.getDefault().register(this);
31 | TextView tv_title = findViewById(R.id.tv_title);
32 | tv_title.setText(R.string.playList);
33 | }
34 | public void init(){
35 | LoadingView lv_loading = findViewById(R.id.lv_loading);
36 | RecyclerView rv_main = findViewById(R.id.rv_main);
37 | rv_main.setLayoutManager(new LinearLayoutManager(this));
38 | if(getIntent().getBooleanExtra("local",false)){
39 | rv_main.setAdapter(new LocalMusicAdapter(data, this));
40 | }
41 | else{
42 | rv_main.setAdapter(new MusicAdapter(data, this));
43 | }
44 | lv_loading.setVisibility(View.GONE);
45 | rv_main.setVisibility(View.VISIBLE);
46 | }
47 |
48 | public void onClick(View view){
49 | finish();
50 | }
51 |
52 | @Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
53 | public void onMessageEvent(MessageEvent event){
54 | data = JSON.parseArray(event.msg);
55 | init();
56 | }
57 |
58 | @Override
59 | protected void onDestroy() {
60 | super.onDestroy();
61 | //移除所有的黏性事件
62 | EventBus.getDefault().removeAllStickyEvents();
63 | //避免内存泄漏,防止OOM,优化内存
64 | EventBus.getDefault().unregister(this);
65 | }
66 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/QRCodeActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 |
9 | import cn.wearbbs.music.R;
10 | import cn.wearbbs.music.util.QRCodeUtil;
11 |
12 | public class QRCodeActivity extends AppCompatActivity {
13 |
14 | @Override
15 | protected void onCreate(Bundle savedInstanceState) {
16 | super.onCreate(savedInstanceState);
17 | setContentView(R.layout.activity_qrcode);
18 | ImageView iv_qrcode = findViewById(R.id.iv_qrcode);
19 | iv_qrcode.setImageBitmap(QRCodeUtil.createQRCodeBitmap(getIntent().getStringExtra("url"), 512, 512));
20 | }
21 |
22 | public void onClick(View view) {
23 | finish();
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/ReplyActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.os.Looper;
6 | import android.view.View;
7 | import android.widget.EditText;
8 | import android.widget.Toast;
9 |
10 | import androidx.appcompat.app.AppCompatActivity;
11 |
12 | import cn.jackuxl.api.SongApi;
13 | import cn.wearbbs.music.R;
14 | import cn.wearbbs.music.util.SharedPreferencesUtil;
15 |
16 | public class ReplyActivity extends AppCompatActivity {
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_reply);
22 | }
23 |
24 | @SuppressLint("NonConstantResourceId")
25 | public void onClick(View view){
26 | switch (view.getId()){
27 | case R.id.main_title:
28 | finish();
29 | break;
30 | case R.id.btn_send:
31 | EditText et_content = findViewById(R.id.et_content);
32 | new Thread(()->{
33 | Looper.prepare();
34 | if(new SongApi(SharedPreferencesUtil.getString("cookie","")).sendComment(getIntent().getStringExtra("id"),et_content.getText().toString())){
35 | Toast.makeText(this,"发送成功",Toast.LENGTH_SHORT).show();
36 | finish();
37 | }
38 | else{
39 | Toast.makeText(this,"发送失败",Toast.LENGTH_SHORT).show();
40 | }
41 | Looper.loop();
42 | }).start();
43 | break;
44 |
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 |
7 | import androidx.appcompat.app.ActionBar;
8 | import androidx.appcompat.app.AppCompatDelegate;
9 | import androidx.preference.Preference;
10 | import androidx.preference.PreferenceFragmentCompat;
11 |
12 | import cn.wearbbs.music.R;
13 | import cn.jackuxl.util.NetWorkUtil;
14 |
15 | /**
16 | * 设置
17 | */
18 | public class SettingsActivity extends SlideBackActivity {
19 |
20 | @Override
21 | protected void onCreate(Bundle savedInstanceState) {
22 | super.onCreate(savedInstanceState);
23 | setContentView(R.layout.activity_settings);
24 | if (savedInstanceState == null) {
25 | getSupportFragmentManager()
26 | .beginTransaction()
27 | .replace(R.id.settings, new SettingsFragment())
28 | .commit();
29 | }
30 | ActionBar actionBar = getSupportActionBar();
31 | if (actionBar != null) {
32 | actionBar.setDisplayHomeAsUpEnabled(true);
33 | }
34 | }
35 |
36 | public void onClick(View view) {
37 | Intent intent = new Intent(SettingsActivity.this, MenuActivity.class);
38 | intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
39 | startActivity(intent);
40 | finish();
41 | }
42 |
43 | public static class SettingsFragment extends PreferenceFragmentCompat {
44 | @Override
45 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
46 | setPreferencesFromResource(R.xml.root_preferences, rootKey);
47 | findPreference("about").setOnPreferenceClickListener(preference -> {
48 | startActivity(new Intent(getActivity(), AboutActivity.class));
49 | return true;
50 | });
51 |
52 | findPreference("dark").setOnPreferenceChangeListener((preference, newValue) -> {
53 | if ((Boolean) newValue) {
54 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
55 | } else {
56 | AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
57 | }
58 | return true;
59 | });
60 |
61 | findPreference("opensource").setOnPreferenceClickListener(preference -> {
62 | startActivity(new Intent(getActivity(), OpenSourceActivity.class));
63 | return true;
64 | });
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/SlideBackActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.view.MotionEvent;
4 | import android.view.VelocityTracker;
5 |
6 | import androidx.appcompat.app.AppCompatActivity;
7 |
8 | /**
9 | * 支持滑动返回
10 | * 继承该Activity则支持滑动返回
11 | */
12 | public class SlideBackActivity extends AppCompatActivity {
13 |
14 | //手指上下滑动时的最小速度
15 | private static final int YSPEED_MIN = 1000;
16 |
17 | //手指向右滑动时的最小距离
18 | private static final int XDISTANCE_MIN = 50;
19 |
20 | //手指向上滑或下滑时的最小距离
21 | private static final int YDISTANCE_MIN = 100;
22 |
23 | //记录手指按下时的横坐标。
24 | private float xDown;
25 |
26 | //记录手指按下时的纵坐标。
27 | private float yDown;
28 |
29 | //用于计算手指滑动的速度。
30 | private VelocityTracker mVelocityTracker;
31 |
32 | @Override
33 | public boolean dispatchTouchEvent(MotionEvent event) {
34 | createVelocityTracker(event);
35 | switch (event.getAction()) {
36 | case MotionEvent.ACTION_DOWN:
37 | xDown = event.getRawX();
38 | yDown = event.getRawY();
39 | break;
40 | case MotionEvent.ACTION_MOVE:
41 | //记录手指移动时的横坐标。
42 | float xMove = event.getRawX();
43 | //记录手指移动时的纵坐标。
44 | float yMove = event.getRawY();
45 | //滑动的距离
46 | int distanceX = (int) (xMove - xDown);
47 | int distanceY = (int) (yMove - yDown);
48 | //获取顺时速度
49 | int ySpeed = getScrollVelocity();
50 | //关闭Activity需满足以下条件:
51 | //1.x轴滑动的距离>XDISTANCE_MIN
52 | //2.y轴滑动的距离在YDISTANCE_MIN范围内
53 | //3.y轴上(即上下滑动的速度) XDISTANCE_MIN && (distanceY < YDISTANCE_MIN && distanceY > -YDISTANCE_MIN) && ySpeed < YSPEED_MIN) {
55 | finish();
56 | overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
57 | }
58 | break;
59 | case MotionEvent.ACTION_UP:
60 | recycleVelocityTracker();
61 | break;
62 | default:
63 | break;
64 | }
65 | return super.dispatchTouchEvent(event);
66 | }
67 |
68 | @Override
69 | public void finish() {
70 | super.finish();
71 |
72 | }
73 |
74 | /**
75 | * 创建VelocityTracker对象,并将触摸界面的滑动事件加入到VelocityTracker当中。
76 | *
77 | * @param event 事件
78 | */
79 | private void createVelocityTracker(MotionEvent event) {
80 | if (mVelocityTracker == null) {
81 | mVelocityTracker = VelocityTracker.obtain();
82 | }
83 | mVelocityTracker.addMovement(event);
84 | }
85 |
86 | /**
87 | * 回收VelocityTracker对象。
88 | */
89 | private void recycleVelocityTracker() {
90 | mVelocityTracker.recycle();
91 | mVelocityTracker = null;
92 | }
93 |
94 | /**
95 | * 获取滑动速度
96 | *
97 | * @return 滑动速度,以每秒钟移动了多少像素值为单位。
98 | */
99 | private int getScrollVelocity() {
100 | mVelocityTracker.computeCurrentVelocity(1000);
101 | int velocity = (int) mVelocityTracker.getYVelocity();
102 | return Math.abs(velocity);
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/UpdateActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.ImageView;
7 | import android.widget.TextView;
8 |
9 | import androidx.appcompat.app.AppCompatActivity;
10 |
11 | import com.alibaba.fastjson.JSONObject;
12 |
13 | import cn.wearbbs.music.R;
14 | import cn.wearbbs.music.api.AppServiceApi;
15 | import cn.wearbbs.music.application.MainApplication;
16 | import cn.wearbbs.music.util.SharedPreferencesUtil;
17 | import cn.wearbbs.music.view.MessageView;
18 |
19 | /**
20 | * 更新
21 | */
22 | public class UpdateActivity extends AppCompatActivity {
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_update);
28 | init();
29 | }
30 |
31 | public void onClick(View view) {
32 | finish();
33 | }
34 |
35 | @SuppressLint("StringFormatMatches")
36 | public void init() {
37 | findViewById(R.id.lv_loading).setVisibility(View.VISIBLE);
38 | new Thread(()->{
39 | JSONObject data = checkUpdate();
40 | if(data == null){
41 | runOnUiThread(this::showErrorMessage);
42 | }
43 | else if(data.getBoolean("needUpdate")){
44 | runOnUiThread(() -> {
45 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
46 | findViewById(R.id.sv_needUpdate).setVisibility(View.VISIBLE);
47 | TextView tv_hint = findViewById(R.id.tv_hint);
48 | tv_hint.setText(String.format(getString(R.string.needUpdateHint),data.getString("currentVersion"),data.getString("latestVersion")));
49 | TextView tv_changeLog = findViewById(R.id.tv_changeLog);
50 | tv_changeLog.setText(data.getString("changeLog"));
51 | });
52 | }
53 | else{
54 | runOnUiThread(() -> {
55 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
56 | findViewById(R.id.sv_noUpdate).setVisibility(View.VISIBLE);
57 | TextView tv_hint_no = findViewById(R.id.tv_hint_no);
58 | tv_hint_no.setText(String.format(getString(R.string.noUpdateHint),data.getString("currentVersion"),data.getString("latestVersion")));
59 | });
60 | }
61 | }).start();
62 | }
63 |
64 | /**
65 | * 检查更新(已知BUG:如果服务器返回的版本号不是数字,会导致崩溃)
66 | * @return 是否需要更新
67 | */
68 | public static JSONObject checkUpdate() {
69 | double latestVersion;
70 | double currentVersion;
71 | try{
72 | JSONObject info;
73 | info = AppServiceApi.getLatestVersionInfo();
74 | latestVersion = info.getDouble("latestVersion");
75 | currentVersion = Double.parseDouble(MainApplication.getApplicationVersion());
76 | info.put("needUpdate",currentVersion < latestVersion);
77 | info.put("currentVersion",currentVersion);
78 | return info;
79 | }
80 | catch (Exception e){
81 | return null;
82 | }
83 |
84 | }
85 |
86 | public void showErrorMessage(){
87 | findViewById(R.id.lv_loading).setVisibility(View.GONE);
88 | findViewById(R.id.tv_dev_no).setVisibility(View.GONE);
89 | findViewById(R.id.tv_dev).setVisibility(View.GONE);
90 |
91 | MessageView mv_message = findViewById(R.id.mv_message);
92 | mv_message.setVisibility(View.VISIBLE);
93 | mv_message.setContent(MessageView.LOAD_FAILED, v -> {
94 | mv_message.setVisibility(View.GONE);
95 | init();
96 | });
97 | }
98 |
99 | @Override
100 | public void finish(){
101 | AppServiceApi.resetServer();
102 | super.finish();
103 | }
104 |
105 | @Override
106 | public void onDestroy(){
107 | AppServiceApi.resetServer();
108 | super.onDestroy();
109 | }
110 |
111 |
112 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/UserProfileActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 |
10 | import androidx.appcompat.app.AlertDialog;
11 | import androidx.appcompat.app.AppCompatActivity;
12 |
13 | import com.alibaba.fastjson.JSON;
14 | import com.alibaba.fastjson.JSONObject;
15 | import com.bumptech.glide.Glide;
16 | import com.bumptech.glide.load.resource.bitmap.CircleCrop;
17 | import com.bumptech.glide.request.RequestOptions;
18 |
19 | import cn.jackuxl.api.UserApi;
20 | import cn.wearbbs.music.R;
21 | import cn.wearbbs.music.util.SharedPreferencesUtil;
22 |
23 | public class UserProfileActivity extends AppCompatActivity {
24 | private JSONObject profile;
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_userprofile);
29 | profile = JSON.parseObject(getIntent().getStringExtra("profile"));
30 | if(profile == null){
31 | profile = SharedPreferencesUtil.getJSONObject("profile");
32 | }
33 | else{
34 | findViewById(R.id.btn_logout).setVisibility(View.GONE);
35 | }
36 | init();
37 | }
38 |
39 | public void init(){
40 | ImageView iv_avatar = findViewById(R.id.iv_avatar);
41 | RequestOptions options = RequestOptions.bitmapTransform(new CircleCrop()).placeholder(R.drawable.ic_baseline_photo_size_select_actual_24).error(R.drawable.ic_baseline_photo_size_select_actual_24);
42 | Glide.with(this).load(profile.getString("avatarUrl").replace("http://","https://")).apply(options).into(iv_avatar);
43 | iv_avatar.setOnClickListener(v -> startActivity(new Intent(this, ViewPictureActivity.class).putExtra("url", profile.getString("avatarUrl").replace("http://", "https://"))));
44 |
45 | TextView tv_name = findViewById(R.id.tv_name);
46 | tv_name.setText(profile.getString("nickname"));
47 |
48 | TextView tv_id = findViewById(R.id.tv_id);
49 | tv_id.setText(String.format("ID:%s",profile.getString("userId")));
50 | }
51 |
52 | @SuppressLint("NonConstantResourceId")
53 | public void onClick(View view) {
54 | switch (view.getId()) {
55 | case R.id.main_title:
56 | finish();
57 | break;
58 | case R.id.btn_logout:
59 | // 退出登录
60 | new AlertDialog.Builder(this)
61 | .setTitle("提示")
62 | .setMessage("确定要退出登录吗")
63 | .setPositiveButton("确定", (dialogInterface, i) -> {
64 | UserApi api = new UserApi();
65 | api.setCookie(SharedPreferencesUtil.getString("cookie", ""));
66 | new Thread(() -> {
67 | api.logout();
68 | SharedPreferencesUtil.remove("cookie");
69 | SharedPreferencesUtil.remove("profile");
70 | setResult(RESULT_OK, new Intent().putExtra("logout",true));
71 | finish();
72 | }).start();
73 | })
74 | .setNegativeButton("手滑了", (dialogInterface, i) -> dialogInterface.dismiss())
75 | .create().show();
76 | break;
77 | case R.id.iv_avatar:
78 | break;
79 | }
80 |
81 | }
82 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/ui/ViewPictureActivity.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.ui;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.content.Intent;
6 | import android.content.pm.PackageManager;
7 | import android.graphics.Bitmap;
8 | import android.net.Uri;
9 | import android.os.Build;
10 | import android.os.Bundle;
11 | import android.os.Environment;
12 | import android.os.Looper;
13 | import android.view.View;
14 | import android.widget.Toast;
15 |
16 | import androidx.annotation.NonNull;
17 | import androidx.appcompat.app.AppCompatActivity;
18 |
19 | import com.bumptech.glide.Glide;
20 |
21 | import java.io.BufferedOutputStream;
22 | import java.io.File;
23 | import java.io.FileOutputStream;
24 | import java.io.IOException;
25 | import java.util.UUID;
26 |
27 | import cn.wearbbs.music.R;
28 | import me.panpf.sketch.SketchImageView;
29 |
30 | public class ViewPictureActivity extends AppCompatActivity {
31 | private static String mSaveMessage = "保存失败";
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_viewpicture);
37 | String url = getIntent().getStringExtra("url");
38 | SketchImageView sketchImageView = findViewById(R.id.iv_pic);
39 | sketchImageView.displayImage(url);
40 | sketchImageView.setZoomEnabled(true);
41 | }
42 |
43 | @SuppressLint("NonConstantResourceId")
44 | public void onClick(View view){
45 | switch (view.getId()){
46 | case R.id.ll_return:
47 | finish();
48 | break;
49 | case R.id.ll_save:
50 | checkPermissionForSave();
51 | break;
52 | }
53 | }
54 |
55 | public void savePicture(String photoUrl) {
56 | new Thread(()->{
57 | Bitmap bitmap = null;
58 | try {
59 | bitmap = Glide.with(ViewPictureActivity.this)
60 | .asBitmap()
61 | .load(photoUrl)
62 | .submit(512, 512).get();
63 | if(saveFile(bitmap)){
64 | mSaveMessage = "保存成功";
65 | }
66 | else{
67 | mSaveMessage = "保存失败";
68 | }
69 | } catch (Exception e) {
70 | e.printStackTrace();
71 | }
72 | Looper.prepare();
73 | Toast.makeText(this, mSaveMessage, Toast.LENGTH_SHORT).show();
74 | Looper.loop();
75 | }).start();
76 | }
77 |
78 | public boolean saveFile(Bitmap bm) throws IOException {
79 | File dirFile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/");
80 | if (!dirFile.exists()) {
81 | if(!dirFile.mkdir()){
82 | return false;
83 | }
84 | }
85 |
86 | //图片命名
87 | String fileName = UUID.randomUUID().toString() + ".jpg";
88 | File myCaptureFile = new File(Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/" + fileName);
89 | if(!myCaptureFile.createNewFile()){
90 | return false;
91 | }
92 | BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
93 | bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);
94 | bos.flush();
95 | bos.close();
96 |
97 | //广播通知相册有图片更新
98 | Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
99 | Uri uri = Uri.fromFile(myCaptureFile);
100 | intent.setData(uri);
101 | sendBroadcast(intent);
102 | return true;
103 | }
104 |
105 | public void checkPermissionForSave(){
106 | // 读取权限
107 | String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
108 | if(Build.VERSION.SDK_INT>=23){
109 | // 检查权限是否已授权
110 | int hasPermission = checkSelfPermission(permission);
111 | // 如果没有授权
112 | if (hasPermission != PackageManager.PERMISSION_GRANTED) {
113 | // 请求权限
114 | requestPermissions(new String[]{permission}, 0);
115 | } else {
116 | // 已授权权限
117 | savePicture(getIntent().getStringExtra("url"));
118 | }
119 | } else{
120 | savePicture(getIntent().getStringExtra("url"));
121 | }
122 | }
123 |
124 | @Override
125 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
126 | if (grantResults.length > 0) {//grantResults 数组中存放的是授权结果
127 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
128 | // 同意授权
129 | savePicture(getIntent().getStringExtra("url"));
130 | }else {
131 | // 拒绝授权
132 | Toast.makeText(ViewPictureActivity.this, getString(R.string.permission_denied), Toast.LENGTH_SHORT).show();
133 | }
134 | }
135 | }
136 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/util/DownloadUtil.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.util;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import java.io.File;
6 | import java.io.FileOutputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.util.Objects;
10 |
11 | import okhttp3.Call;
12 | import okhttp3.Callback;
13 | import okhttp3.OkHttpClient;
14 | import okhttp3.Request;
15 | import okhttp3.Response;
16 |
17 | /**
18 | * 文件下载工具类
19 | * By Brick farmers
20 | * Url: https://blog.csdn.net/lixinxiaos/article/details/93977377
21 | */
22 |
23 | public class DownloadUtil {
24 |
25 | private static DownloadUtil downloadUtil;
26 | private final OkHttpClient okHttpClient;
27 |
28 | public static DownloadUtil get() {
29 | if (downloadUtil == null) {
30 | downloadUtil = new DownloadUtil();
31 | }
32 | return downloadUtil;
33 | }
34 |
35 | public DownloadUtil() {
36 | okHttpClient = new OkHttpClient();
37 | }
38 |
39 |
40 | /**
41 | * @param url 下载连接
42 | * @param destFileDir 下载的文件储存目录
43 | * @param destFileName 下载文件名称,后面记得拼接后缀,否则手机没法识别文件类型
44 | * @param listener 下载监听
45 | */
46 |
47 | public void download(final String url, final String destFileDir, final String destFileName, final OnDownloadListener listener) {
48 |
49 | Request request = new Request.Builder()
50 | .url(url)
51 | .build();
52 |
53 | OkHttpClient client = new OkHttpClient();
54 |
55 | //异步请求
56 | okHttpClient.newCall(request).enqueue(new Callback() {
57 | @Override
58 | public void onFailure(@NonNull Call call, @NonNull IOException e) {
59 | // 下载失败监听回调
60 | listener.onDownloadFailed(e);
61 | }
62 |
63 | @Override
64 | public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
65 |
66 | InputStream is = null;
67 | byte[] buf = new byte[2048];
68 | int len = 0;
69 | FileOutputStream fos = null;
70 |
71 | //储存下载文件的目录
72 | File dir = new File(destFileDir);
73 | if (!dir.exists()) {
74 | dir.mkdirs();
75 | }
76 | File file = new File(dir, destFileName);
77 |
78 | try {
79 |
80 | is = Objects.requireNonNull(response.body()).byteStream();
81 | long total = Objects.requireNonNull(response.body()).contentLength();
82 | fos = new FileOutputStream(file);
83 | long sum = 0;
84 | while ((len = is.read(buf)) != -1) {
85 | fos.write(buf, 0, len);
86 | sum += len;
87 | int progress = (int) (sum * 1.0f / total * 100);
88 | //下载中更新进度条
89 | listener.onDownloading(progress);
90 | }
91 | fos.flush();
92 | //下载完成
93 | listener.onDownloadSuccess(file);
94 | } catch (Exception e) {
95 | listener.onDownloadFailed(e);
96 | }finally {
97 |
98 | try {
99 | if (is != null) {
100 | is.close();
101 | }
102 | if (fos != null) {
103 | fos.close();
104 | }
105 | } catch (IOException e) {
106 |
107 | }
108 |
109 | }
110 |
111 |
112 | }
113 | });
114 | }
115 |
116 |
117 | public interface OnDownloadListener{
118 |
119 | /**
120 | * 下载成功之后的文件
121 | */
122 | void onDownloadSuccess(File file);
123 |
124 | /**
125 | * 下载进度
126 | */
127 | void onDownloading(int progress);
128 |
129 | /**
130 | * 下载异常信息
131 | */
132 |
133 | void onDownloadFailed(Exception e);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/util/QRCodeUtil.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.util;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Color;
5 | import android.text.TextUtils;
6 |
7 | import androidx.annotation.ColorInt;
8 | import androidx.annotation.Nullable;
9 |
10 | import com.google.zxing.BarcodeFormat;
11 | import com.google.zxing.EncodeHintType;
12 | import com.google.zxing.WriterException;
13 | import com.google.zxing.common.BitMatrix;
14 | import com.google.zxing.qrcode.QRCodeWriter;
15 |
16 | import java.util.Hashtable;
17 |
18 | /**
19 | * 二维码工具类
20 | * 来源:CSDN
21 | */
22 | public class QRCodeUtil {
23 |
24 | /**
25 | * 创建二维码位图
26 | *
27 | * @param content 字符串内容(支持中文)
28 | * @param width 位图宽度(单位:px)
29 | * @param height 位图高度(单位:px)
30 | * @return QRCode
31 | */
32 | @Nullable
33 | public static Bitmap createQRCodeBitmap(String content, int width, int height){
34 | return createQRCodeBitmap(content, width, height, "UTF-8", "H", "2", Color.BLACK, Color.WHITE);
35 | }
36 |
37 | /**
38 | * 创建二维码位图 (支持自定义配置和自定义样式)
39 | *
40 | * @param content 字符串内容
41 | * @param width 位图宽度,要求>=0(单位:px)
42 | * @param height 位图高度,要求>=0(单位:px)
43 | * @param character_set 字符集/字符转码格式 (支持格式:{@link CharacterSetECI })。传null时,zxing源码默认使用 "ISO-8859-1"
44 | * @param error_correction 容错级别 (支持级别:{@link ErrorCorrectionLevel })。传null时,zxing源码默认使用 "L"
45 | * @param margin 空白边距 (可修改,要求:整型且>=0), 传null时,zxing源码默认使用"4"。
46 | * @param color_black 黑色色块的自定义颜色值
47 | * @param color_white 白色色块的自定义颜色值
48 | * @return QRCode
49 | */
50 | @Nullable
51 | public static Bitmap createQRCodeBitmap(String content, int width, int height,
52 | @Nullable String character_set, @Nullable String error_correction, @Nullable String margin,
53 | @ColorInt int color_black, @ColorInt int color_white){
54 |
55 | /* 1.参数合法性判断 */
56 | if(TextUtils.isEmpty(content)){ // 字符串内容判空
57 | return null;
58 | }
59 |
60 | if(width < 0 || height < 0){ // 宽和高都需要>=0
61 | return null;
62 | }
63 |
64 | try {
65 | /* 2.设置二维码相关配置,生成BitMatrix(位矩阵)对象 */
66 | Hashtable hints = new Hashtable<>();
67 |
68 | if(!TextUtils.isEmpty(character_set)) {
69 | hints.put(EncodeHintType.CHARACTER_SET, character_set); // 字符转码格式设置
70 | }
71 |
72 | if(!TextUtils.isEmpty(error_correction)){
73 | hints.put(EncodeHintType.ERROR_CORRECTION, error_correction); // 容错级别设置
74 | }
75 |
76 | if(!TextUtils.isEmpty(margin)){
77 | hints.put(EncodeHintType.MARGIN, margin); // 空白边距设置
78 | }
79 | BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
80 |
81 | /* 3.创建像素数组,并根据BitMatrix(位矩阵)对象为数组元素赋颜色值 */
82 | int[] pixels = new int[width * height];
83 | for(int y = 0; y < height; y++){
84 | for(int x = 0; x < width; x++){
85 | if(bitMatrix.get(x, y)){
86 | pixels[y * width + x] = color_black; // 黑色色块像素设置
87 | } else {
88 | pixels[y * width + x] = color_white; // 白色色块像素设置
89 | }
90 | }
91 | }
92 |
93 | /* 4.创建Bitmap对象,根据像素数组设置Bitmap每个像素点的颜色值,之后返回Bitmap对象 */
94 | Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
95 | bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
96 | return bitmap;
97 | } catch (WriterException e) {
98 | e.printStackTrace();
99 | }
100 |
101 | return null;
102 | }
103 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/util/SharedPreferencesUtil.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.util;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import com.alibaba.fastjson.JSON;
7 | import com.alibaba.fastjson.JSONObject;
8 |
9 | import cn.wearbbs.music.application.MainApplication;
10 |
11 | public class SharedPreferencesUtil {
12 | public static void putString(String key, String value) {
13 | SharedPreferences.Editor sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE).edit();
14 | sp.putString(key, value);
15 | sp.apply();
16 | }
17 |
18 | public static void putBoolean(String key, Boolean value) {
19 | SharedPreferences.Editor sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE).edit();
20 | sp.putBoolean(key, value);
21 | sp.apply();
22 | }
23 |
24 | public static void putJSONObject(String key, JSONObject value) {
25 | SharedPreferences.Editor sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE).edit();
26 | sp.putString(key, value.toJSONString());
27 | sp.apply();
28 | }
29 |
30 | public static Boolean getBoolean(String key, Boolean defValue) {
31 | SharedPreferences sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE);
32 | return sp.getBoolean(key, defValue);
33 | }
34 |
35 | public static String getString(String key, String defValue) {
36 | SharedPreferences sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE);
37 | return sp.getString(key, defValue);
38 | }
39 |
40 | public static JSONObject getJSONObject(String key) {
41 | SharedPreferences sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE);
42 | return JSON.parseObject(sp.getString(key, "{}"));
43 | }
44 |
45 | public static void remove(String key) {
46 | SharedPreferences.Editor sp = MainApplication.getContext().getSharedPreferences("cn.wearbbs.music_preferences", Context.MODE_PRIVATE).edit();
47 | sp.remove(key);
48 | sp.apply();
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/util/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.util;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.os.Message;
8 | import android.widget.Toast;
9 |
10 | import org.apache.log4j.chainsaw.Main;
11 |
12 | import cn.wearbbs.music.application.MainApplication;
13 |
14 | public class ToastUtil {
15 | public static void show(Activity activity,String text){
16 | activity.runOnUiThread(()->{
17 | Toast.makeText(MainApplication.getContext(), text, Toast.LENGTH_LONG).show();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/view/LoadingView.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.LinearLayout;
9 |
10 | import androidx.annotation.Nullable;
11 |
12 | import cn.wearbbs.music.R;
13 |
14 | public class LoadingView extends LinearLayout {
15 | View mView;
16 |
17 | @SuppressLint("InflateParams")
18 | public LoadingView(Context context) {
19 | super(context);
20 | LayoutInflater mInflater = LayoutInflater.from(context);
21 | mView = mInflater.inflate(R.layout.view_loading, null);
22 | addView(mView);
23 | }
24 |
25 | @SuppressLint("InflateParams")
26 | public LoadingView(Context context, @Nullable AttributeSet attrs) {
27 | super(context, attrs);
28 | LayoutInflater mInflater = LayoutInflater.from(context);
29 | mView = mInflater.inflate(R.layout.view_loading, null);
30 | addView(mView);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/wearbbs/music/view/MessageView.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 | import android.widget.LinearLayout;
10 | import android.widget.TextView;
11 |
12 | import androidx.annotation.DrawableRes;
13 | import androidx.annotation.Nullable;
14 | import androidx.annotation.StringRes;
15 |
16 | import cn.wearbbs.music.R;
17 |
18 | public class MessageView extends LinearLayout {
19 | private final View mView;
20 | public final static int NO_LOGIN = 0,
21 | LOAD_FAILED = 1,
22 | NO_MUSIC = 2;
23 | @SuppressLint("InflateParams")
24 | public MessageView(Context context) {
25 | super(context);
26 | LayoutInflater mInflater = LayoutInflater.from(context);
27 | mView = mInflater.inflate(R.layout.view_message, null);
28 | addView(mView);
29 | }
30 |
31 | @SuppressLint("InflateParams")
32 | public MessageView(Context context, @Nullable AttributeSet attrs) {
33 | super(context, attrs);
34 | LayoutInflater mInflater = LayoutInflater.from(context);
35 | mView = mInflater.inflate(R.layout.view_message, null);
36 | addView(mView);
37 | }
38 |
39 | public void setImageResource(@DrawableRes int resId) {
40 | ImageView iv_img = findViewById(R.id.iv_img);
41 | iv_img.setImageResource(resId);
42 | }
43 |
44 | public void setText(@StringRes int resId) {
45 | TextView tv_img = findViewById(R.id.tv_img);
46 | tv_img.setText(resId);
47 | }
48 |
49 | public void setImageOnClickListener(OnClickListener listener){
50 | ImageView iv_img = findViewById(R.id.iv_img);
51 | iv_img.setOnClickListener(listener);
52 | }
53 |
54 |
55 | public void setContent(int contentId,@Nullable OnClickListener listener){
56 | switch (contentId){
57 | case NO_LOGIN:
58 | setText(R.string.msg_noLogin);
59 | setImageResource(R.drawable.ic_baseline_login_24);
60 | setImageOnClickListener(v -> {});
61 | break;
62 | case LOAD_FAILED:
63 | setText(R.string.load_failed);
64 | setImageResource(R.drawable.ic_baseline_refresh_24);
65 | setImageOnClickListener(listener);
66 | break;
67 | case NO_MUSIC:
68 | setText(R.string.msg_noMusic);
69 | setImageResource(R.drawable.ic_baseline_assignment_24);
70 | setImageOnClickListener(v -> {});
71 | break;
72 | }
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-night/icon_play_order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable-night/icon_play_order.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-night/icon_play_repeat_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable-night/icon_play_repeat_one.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | -
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/et_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_android_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_arrow_back_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_arrow_back_ios_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_arrow_forward_ios_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_assignment_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_assignment_turned_in_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_brightness_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_brightness_24_black.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_build_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_check_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_cloud_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_cloud_download_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_desktop_windows_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_family_restroom_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_favorite_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_favorite_border_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_file_copy_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_library_music_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_lock_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_login_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_menu_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_message_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_music_video_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_pause_circle_filled_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_person_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_phone_android_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_photo_size_select_actual_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_play_circle_filled_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_playlist_play_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_radio_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_refresh_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_save_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_sd_storage_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_search_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_settings_24.xml:
--------------------------------------------------------------------------------
1 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_share_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_star_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_supervised_user_circle_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_supervised_user_circle_primary_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_thumb_up_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_visibility_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_visibility_off_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_volume_down_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_volume_up_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_warning_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_outline_thumb_up_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_extra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/icon_extra.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_play_order.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/icon_play_order.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_play_repeat_one.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/icon_play_repeat_one.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_tip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/icon_tip.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/middle_ss.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/qrcode_group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/qrcode_group.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/qrcode_update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/qrcode_update.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/qrcode_update_dev.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/drawable/qrcode_update_dev.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ripple_item_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_progressbar_azure.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 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_progressbar_loading.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 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
29 |
30 |
38 |
39 |
40 |
41 |
46 |
47 |
53 |
54 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_ftp.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
25 |
26 |
35 |
36 |
44 |
45 |
46 |
47 |
58 |
59 |
64 |
65 |
72 |
73 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_localmusic.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
30 |
31 |
39 |
40 |
41 |
42 |
53 |
54 |
60 |
61 |
62 |
63 |
69 |
70 |
77 |
78 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
23 |
24 |
32 |
33 |
42 |
43 |
44 |
45 |
51 |
52 |
59 |
60 |
64 |
65 |
66 |
76 |
77 |
91 |
92 |
100 |
101 |
108 |
109 |
118 |
119 |
120 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_music.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
27 |
28 |
36 |
37 |
38 |
39 |
45 |
46 |
47 |
48 |
55 |
56 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_opensource.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
25 |
26 |
35 |
36 |
44 |
45 |
46 |
47 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_qrcode.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
19 |
28 |
29 |
37 |
38 |
39 |
40 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_reply.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
19 |
20 |
29 |
30 |
38 |
39 |
40 |
41 |
44 |
45 |
51 |
52 |
62 |
63 |
82 |
83 |
84 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
15 |
16 |
25 |
26 |
34 |
35 |
36 |
37 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_userprofile.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
18 |
19 |
27 |
28 |
37 |
38 |
46 |
47 |
48 |
49 |
59 |
60 |
68 |
69 |
78 |
79 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_viewpicture.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
25 |
26 |
33 |
34 |
41 |
42 |
50 |
51 |
62 |
63 |
64 |
72 |
73 |
81 |
82 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_lyrics.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
20 |
21 |
26 |
27 |
35 |
36 |
37 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_comment.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
22 |
23 |
31 |
32 |
43 |
44 |
54 |
55 |
56 |
57 |
58 |
59 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_hot.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_music.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
20 |
21 |
31 |
32 |
41 |
42 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_musiclist_info.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
23 |
24 |
28 |
29 |
35 |
36 |
42 |
43 |
51 |
52 |
62 |
63 |
64 |
65 |
78 |
79 |
80 |
81 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/widget_reply.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/app/src/main/res/mipmap/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - 无音乐
5 | - 加载私人FM
6 |
7 |
8 |
9 | - nothing
10 | - fm
11 |
12 |
13 |
14 |
15 | - 腕上视频
16 | - 腕管Pro
17 |
18 |
19 |
20 | - WristVideo
21 | - WristButlerPro
22 |
23 |
24 |
25 |
26 | - vercel
27 | - wearbbs
28 |
29 |
30 |
31 |
32 | - 24小时制
33 | - 12小时制
34 |
35 |
36 |
37 | - 24
38 | - 12
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2175F3
4 | #FAFAFA
5 | #999999
6 | #1f1f1f
7 | #BC2175F3
8 | #FFBB86FC
9 | #FF6200EE
10 | #FF3700B3
11 | #FF03DAC5
12 | #FF018786
13 | #FF000000
14 | #FFFFFFFF
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | @color/blue_500
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
24 |
25 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/root_preferences.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
11 |
12 |
19 |
20 |
21 |
30 |
33 |
34 |
35 |
38 |
39 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/test/java/cn/wearbbs/music/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.wearbbs.music;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:7.4.2'
9 | classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21'
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | jcenter()
20 | maven { url "https://jitpack.io" }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | android.enableJetifier=true
19 | android.defaults.buildfeatures.buildconfig=true
20 | android.nonTransitiveRClass=false
21 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenSourceWear/WearMusic/21d85e7db3766f3fe2585213e9676764be6c493d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jul 22 15:16:35 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = "WearMusicPro"
2 | include ':app'
3 |
--------------------------------------------------------------------------------