├── .gitattributes
├── .gitignore
├── 1.png
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ └── suspension-fab-1.1.0.aar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── config
│ │ ├── cn.kuwo.player.json
│ │ ├── com.kugou.android.json
│ │ ├── com.tencent.karaoke.json
│ │ ├── com.tencent.qqmusiclocalplayer.json
│ │ ├── me.singleneuron.originalmusicnotification_debugtool.json
│ │ ├── packages.json
│ │ └── version.json
│ └── xposed_init
│ ├── java
│ ├── cn
│ │ └── nexus6p
│ │ │ ├── QQMusicNotify
│ │ │ ├── BackgroundActivity.kt
│ │ │ ├── Base
│ │ │ │ ├── BasicInit.java
│ │ │ │ ├── BasicNotification.java
│ │ │ │ ├── BasicParam.kt
│ │ │ │ ├── BasicViewNotification.java
│ │ │ │ └── HookInterface.java
│ │ │ ├── ContentProvider.kt
│ │ │ ├── Fragment
│ │ │ │ ├── AppsFragment.java
│ │ │ │ ├── DetailFragment.kt
│ │ │ │ ├── ExperimentalFragment.java
│ │ │ │ ├── JsonDetailFragment.kt
│ │ │ │ ├── LogFragment.kt
│ │ │ │ ├── MediaNotificationFragment.java
│ │ │ │ ├── MusicNotificationFragment.java
│ │ │ │ ├── PlayingFragment.kt
│ │ │ │ ├── SettingFragment.kt
│ │ │ │ ├── SettingsFragment.java
│ │ │ │ ├── ThirdPartySourceFragment.kt
│ │ │ │ └── ThirdPartySourceListFragment.kt
│ │ │ ├── Hook
│ │ │ │ ├── cnkuwoplayer.java
│ │ │ │ ├── comkugouandroid.java
│ │ │ │ ├── comneteasecloudmusic.java
│ │ │ │ ├── comsingclient.java
│ │ │ │ ├── comtencentkaraoke.java
│ │ │ │ ├── comtencentqqmusic.java
│ │ │ │ ├── comtencentqqmusiclocalplayer.java
│ │ │ │ └── mesingleneuronoriginalmusicnotification_debugtool.kt
│ │ │ ├── MainActivity.java
│ │ │ ├── SharedPreferences
│ │ │ │ ├── BasePreference.kt
│ │ │ │ └── ContentProviderPreference.kt
│ │ │ ├── SimpleAlcatrazInteractiveCardView.kt
│ │ │ ├── Utils
│ │ │ │ ├── GeneralUtils.java
│ │ │ │ ├── HookStatue.java
│ │ │ │ ├── LogUtils.kt
│ │ │ │ ├── MediaSessionTokenHashMap.java
│ │ │ │ └── PreferenceUtil.java
│ │ │ └── initHook.java
│ │ │ └── removewhitenotificationforbugme
│ │ │ └── main.java
│ ├── me
│ │ └── qiwu
│ │ │ └── MusicNotification
│ │ │ ├── ColorUtil.java
│ │ │ └── NotificationHook.java
│ ├── name
│ │ └── mikanoshi
│ │ │ └── customiuizer
│ │ │ └── mods
│ │ │ └── System.java
│ └── soptqs
│ │ └── medianotification
│ │ └── utils
│ │ ├── ColorUtils.java
│ │ ├── ImageUtils.java
│ │ ├── NotificationUtils.java
│ │ ├── PaletteUtils.java
│ │ └── PreferenceUtils.java
│ └── res
│ ├── anim
│ ├── slide_left_in.xml
│ ├── slide_left_out.xml
│ ├── slide_right_in.xml
│ └── slide_right_out.xml
│ ├── drawable-hdpi
│ ├── ic_add.png
│ ├── ic_check.png
│ ├── ic_music.png
│ ├── ic_pause.png
│ ├── ic_play.png
│ ├── ic_skip_next.png
│ ├── ic_skip_previous.png
│ ├── ic_stop.png
│ ├── ic_thumb_down.png
│ └── ic_thumb_up.png
│ ├── drawable-mdpi
│ ├── ic_add.png
│ ├── ic_check.png
│ ├── ic_music.png
│ ├── ic_pause.png
│ ├── ic_play.png
│ ├── ic_skip_next.png
│ ├── ic_skip_previous.png
│ ├── ic_stop.png
│ ├── ic_thumb_down.png
│ └── ic_thumb_up.png
│ ├── drawable-night
│ ├── ic_github.xml
│ └── ic_mail_outline.xml
│ ├── drawable-v21
│ ├── ic_add.xml
│ ├── ic_check.xml
│ ├── ic_music.xml
│ ├── ic_pause.xml
│ ├── ic_play.xml
│ ├── ic_skip_next.xml
│ ├── ic_skip_previous.xml
│ ├── ic_stop.xml
│ ├── ic_thumb_down.xml
│ └── ic_thumb_up.xml
│ ├── drawable-xhdpi
│ ├── ic_add.png
│ ├── ic_check.png
│ ├── ic_music.png
│ ├── ic_pause.png
│ ├── ic_play.png
│ ├── ic_skip_next.png
│ ├── ic_skip_previous.png
│ ├── ic_stop.png
│ ├── ic_thumb_down.png
│ └── ic_thumb_up.png
│ ├── drawable-xxhdpi
│ ├── ic_add.png
│ ├── ic_check.png
│ ├── ic_music.png
│ ├── ic_pause.png
│ ├── ic_play.png
│ ├── ic_skip_next.png
│ ├── ic_skip_previous.png
│ ├── ic_stop.png
│ ├── ic_thumb_down.png
│ └── ic_thumb_up.png
│ ├── drawable
│ ├── background_image.xml
│ ├── color_drawable.xml
│ ├── edxp.webp
│ ├── edxp_icon.png
│ ├── ic_cancel.xml
│ ├── ic_check_circle.xml
│ ├── ic_delete_black_24dp.xml
│ ├── ic_github.xml
│ ├── ic_mail_outline.xml
│ ├── ic_music.png
│ ├── ic_refresh_black_24dp.xml
│ ├── ic_settings_black_24dp.xml
│ ├── ic_telegram_logo.xml
│ ├── icon.webp
│ ├── miui.webp
│ ├── singleneuron.webp
│ └── taichi.webp
│ ├── layout-v24
│ ├── layout_notification_collapsed.xml
│ ├── layout_notification_collapsed_stlye2.xml
│ ├── layout_notification_expanded.xml
│ └── layout_notification_expanded_stlye2.xml
│ ├── layout
│ ├── layout_notification_collapsed.xml
│ ├── layout_notification_collapsed_stlye2.xml
│ ├── layout_notification_expanded.xml
│ ├── layout_notification_expanded_stlye2.xml
│ ├── log_fragment.xml
│ ├── main_activity.xml
│ ├── notifition_layout.xml
│ ├── setting_fragment.xml
│ ├── simple_alcatraz_interactive_cardview.xml
│ └── third_party_source.xml
│ ├── values-night
│ └── colors.xml
│ ├── values
│ ├── colors.xml
│ ├── integers.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ ├── apps.xml
│ ├── detail.xml
│ ├── experimental.xml
│ ├── file_paths.xml
│ ├── json_detail.xml
│ ├── media_notification.xml
│ ├── music_notification.xml
│ ├── settings.xml
│ └── third_party_source.xml
├── build.gradle
├── debugTool
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── me
│ │ └── singleneuron
│ │ └── originalmusicnotification_debugtool
│ │ └── MainActivity.java
│ └── res
│ └── layout
│ └── activity_main.xml
├── google-play-badge.png
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── icon_原生音乐通知_new.png
├── icon_原生音乐通知_new_512.png
├── nexus6pcn.jks
├── settings.gradle
├── singleneuron.png
├── singleneuron_me.jks
├── 未标题-1.psd
└── 演示文稿1.ppt
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 |
45 | # External native build folder generated in Android Studio 2.2 and later
46 | .externalNativeBuild
47 |
48 | # Google Services (e.g. APIs or Firebase)
49 | google-services.json
50 |
51 | # Freeline
52 | freeline.py
53 | freeline/
54 | freeline_project_description.json
55 |
56 | 捕获.PNG
57 |
58 | .idea/
59 |
60 | app/debug/output.json
61 | .vscode/
62 | keystore.properties
63 | .settings
64 | .classpath
65 | .settings/
66 | .settings/org.eclipse.buildship.core.prefs
67 | .projeck
--------------------------------------------------------------------------------
/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/1.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 原生音乐通知
2 |
3 | [](https://github.com/hefuyicoder/ListenerMusicPlayer#license)
4 | [](https://www.android.com)
5 | [](https://android-arsenal.com/api?level=29)
6 | [](https://play.google.com/store/apps/details?id=cn.nexus6p.QQMusicNotify)
7 | 
8 |
9 | 
10 | An xposed moudle trying to make music player using standard notification
11 |
12 | Supported App: 轻听、全民K歌、酷我音乐、5Sing
13 | Supported System: AOSP Based、MIUI、Flyme……
14 |
15 | 
16 |
17 | 欢迎加入某些不靠谱插件交流群:951343825
18 |
19 | Telegram Channel/Group: https://t.me/NeuronDevelopChannel
20 |
21 | Canary版CI自动编译下载地址,任何使用风险自负:https://install.appcenter.ms/users/liziyuan123456-yeah.net/apps/xposedmusicnotify/distribution_groups/canary
22 |
23 | ### [隐私权政策](./PrivacyPolicy)
24 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /release
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 29
7 | buildToolsVersion '29.0.3'
8 |
9 | defaultConfig {
10 | applicationId "cn.nexus6p.QQMusicNotify"
11 | minSdkVersion 23
12 | //noinspection OldTargetApi,ExpiredTargetSdkVersion
13 | targetSdkVersion 29
14 | vectorDrawables.useSupportLibrary = true
15 | }
16 |
17 | repositories {
18 | maven { url 'https://jitpack.io' }
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled true
24 | shrinkResources true
25 | zipAlignEnabled true
26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
27 | }
28 | }
29 |
30 | signingConfigs {
31 | release {
32 | if (rootProject.file("keystore.properties").exists()) {
33 | def keystorePropertiesFile = rootProject.file("keystore.properties")
34 | def keystoreProperties = new Properties()
35 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
36 | storeFile file('nexus6pcn.jks')
37 | keyAlias keystoreProperties['keyAlias']
38 | keyPassword keystoreProperties['keyPassword']
39 | storePassword keystoreProperties['storePassword']
40 | }
41 | }
42 | }
43 |
44 | flavorDimensions "type"
45 | productFlavors {
46 | play {
47 | dimension "type"
48 | }
49 | apk {
50 | dimension "type"
51 | }
52 | }
53 |
54 | compileOptions {
55 | sourceCompatibility JavaVersion.VERSION_1_8
56 | targetCompatibility JavaVersion.VERSION_1_8
57 | }
58 | kotlinOptions {
59 | jvmTarget = "1.8"
60 | }
61 |
62 | buildFeatures {
63 | viewBinding = true
64 | }
65 |
66 | applicationVariants.all { variant ->
67 | def buildType = variant.buildType.name
68 | def variantName = variant.productFlavors[0].name
69 | if (buildType == "release" && variantName == "apk") {
70 | //variant.packageApplicationProvider.get().outputDirectory = new File(project.rootDir.absolutePath + "/app/release")
71 | variant.outputs.all { output ->
72 | output.outputFileName = "XposedMusicNotify-" + variant.versionName + "-release.apk"
73 | }
74 | }
75 | }
76 |
77 | }
78 |
79 | task buildAllRelease {
80 | group = 'build'
81 | dependsOn 'bundlePlayRelease'
82 | dependsOn 'assembleApkRelease'
83 | }
84 |
85 | dependencies {
86 | implementation fileTree(dir: 'libs', include: ['*.aar'])
87 | compileOnly 'de.robv.android.xposed:api:82'
88 | implementation 'androidx.preference:preference-ktx:1.1.1'
89 | implementation 'androidx.appcompat:appcompat:1.2.0'
90 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
91 | implementation 'androidx.palette:palette-ktx:1.0.0'
92 | implementation 'com.github.topjohnwu.libsu:core:2.5.1'
93 | implementation 'de.psdev.licensesdialog:licensesdialog:2.1.0'
94 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
95 | implementation 'com.google.android.material:material:1.3.0-alpha03'
96 | implementation 'io.alcatraz.alcatrazui:libalcatrazui:1.0.0'
97 | implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
98 | }
99 | repositories {
100 | mavenCentral()
101 | }
102 |
--------------------------------------------------------------------------------
/app/libs/suspension-fab-1.1.0.aar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/libs/suspension-fab-1.1.0.aar
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class cn.nexus6p.QQMusicNotify.*{*;}
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
40 |
41 |
46 |
49 |
50 |
58 |
59 |
62 |
65 |
68 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/app/src/main/assets/config/cn.kuwo.player.json:
--------------------------------------------------------------------------------
1 | {
2 | "versionName": "9.3.1.0",
3 | "versionCode": "9310",
4 | "class": "cn.kuwo.mod.notification.manager.KwNotificationManager",
5 | "method": "getPlayNotification",
6 | "iconID": "7f020c9b",
7 | "drawableClass": "cn.kuwo.player.R$drawable",
8 | "iconField": "notification_icon_white",
9 | "contextField": "mContext",
10 | "preSongIntent": "kuwo.play.pre",
11 | "playSongIntent": "kuwo.play.playing",
12 | "nextSongIntent": "kuwo.play.next",
13 | "IntentHandleActivity": "cn.kuwo.player.activities.EntryActivity",
14 | "getStatusClass": "cn.kuwo.a.b.b",
15 | "getStatusMethod": "r",
16 | "getStatusMethod2": "getStatus",
17 | "playProxyStatusClass": "cn.kuwo.service.PlayProxy$Status",
18 | "playProxyStatusField": "PLAYING",
19 | "extraActionIcon": "7f02058c",
20 | "extraActionIconField": "ic_notification_lrc_on",
21 | "extraActionIntent": "kuwo.desklrc.enable"
22 | }
--------------------------------------------------------------------------------
/app/src/main/assets/config/com.kugou.android.json:
--------------------------------------------------------------------------------
1 | {
2 | "versionName": "10.1.0",
3 | "versionCode": "10101",
4 | "class": "com.kugou.common.q.c",
5 | "method1": "bX",
6 | "method2": "aj"
7 | }
--------------------------------------------------------------------------------
/app/src/main/assets/config/com.tencent.karaoke.json:
--------------------------------------------------------------------------------
1 | {
2 | "versionName": "6.20.28.278",
3 | "versionCode": "493",
4 | "class": "com.tencent.karaoke.common.media.n",
5 | "method": "a",
6 | "titleID": "7f091d55",
7 | "textID": "7f091d53",
8 | "bitmapID": "7f091d50",
9 | "iconID": "7f0800dd",
10 | "intentClass": "com.tencent.karaoke.common.h$a",
11 | "preSongField": "d",
12 | "playSongField": "a",
13 | "nextSongField": "e",
14 | "deleteField": "b",
15 | "IntentHandleActivity": "com.tencent.karaoke.widget.intent.IntentHandleActivity",
16 | "params": [
17 | "android.content.Context",
18 | "com.tencent.karaoke.common.media.player.db.PlaySongInfo",
19 | "int",
20 | "java.lang.String",
21 | "android.graphics.drawable.Drawable"
22 | ],
23 | "idClass": "com.tencent.karaoke.R$a",
24 | "titleField": "play_notification_song_name",
25 | "textField": "play_notification_nickname",
26 | "bitmapField": "play_notification_cover"
27 | }
--------------------------------------------------------------------------------
/app/src/main/assets/config/com.tencent.qqmusiclocalplayer.json:
--------------------------------------------------------------------------------
1 | {
2 | "versionName": "1.2.2.3",
3 | "versionCode": "27"
4 | }
--------------------------------------------------------------------------------
/app/src/main/assets/config/me.singleneuron.originalmusicnotification_debugtool.json:
--------------------------------------------------------------------------------
1 | {
2 | "versionName": "1.0",
3 | "versionCode": "1"
4 | }
--------------------------------------------------------------------------------
/app/src/main/assets/config/packages.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "app": "com.tencent.karaoke",
4 | "name": "全民K歌",
5 | "supportedVersion": [
6 | {
7 | "versionName": "6.7.8.278",
8 | "versionCode": "356"
9 | },
10 | {
11 | "versionName": "6.9.8.278",
12 | "versionCode": "371"
13 | },{
14 | "versionName": "6.10.1.273",
15 | "versionCode": "376"
16 | },{
17 | "versionName": "6.15.28.278",
18 | "versionCode": "438"
19 | },{
20 | "versionName": "6.19.28.278",
21 | "versionCode": "482"
22 | },
23 | {
24 | "versionName": "6.20.28.278",
25 | "versionCode": "493"
26 | }
27 | ]
28 | },
29 | {
30 | "app": "com.tencent.qqmusiclocalplayer",
31 | "name": "轻听",
32 | "supportedVersion": [
33 | {
34 | "versionName": "1.2.2.3",
35 | "versionCode": "27"
36 | }
37 | ]
38 | },
39 | {
40 | "app": "com.sing.client",
41 | "name": "5Sing"
42 | },
43 | {
44 | "app": "cn.kuwo.player",
45 | "name": "酷我音乐",
46 | "supportedVersion": [
47 | {
48 | "versionName": "9.2.4.0",
49 | "versionCode": "9240"
50 | },
51 | {
52 | "versionName": "9.2.4.1",
53 | "versionCode": "9241"
54 | },
55 | {
56 | "versionName": "9.3.0.1",
57 | "versionCode": "9301"
58 | },
59 | {
60 | "versionName": "9.3.1.0",
61 | "versionCode": "9310"
62 | }
63 | ]
64 | },
65 | {
66 | "app": "me.singleneuron.originalmusicnotification_debugtool",
67 | "name": "原生音乐通知调试器",
68 | "supportedVersion": [
69 | {
70 | "versionName": "1.0",
71 | "versionCode": "1"
72 | },
73 | {
74 | "versionName": "1.1",
75 | "versionCode": "2"
76 | }
77 | ]
78 | },
79 | {
80 | "app": "com.kugou.android",
81 | "name": "酷狗音乐",
82 | "supportedVersion": [
83 | {
84 | "versionName": "10.1.0",
85 | "versionCode": "10101"
86 | }
87 | ]
88 | }
89 | ]
90 |
--------------------------------------------------------------------------------
/app/src/main/assets/config/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "2.9.2",
3 | "code": 29
4 | }
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | cn.nexus6p.QQMusicNotify.initHook
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/BackgroundActivity.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import android.view.MotionEvent
6 | import androidx.annotation.Keep
7 | import androidx.appcompat.app.AppCompatActivity
8 |
9 | @Keep
10 | class BackgroundActivity : AppCompatActivity() {
11 |
12 | override fun onCreate(savedInstanceState: Bundle?) {
13 | super.onCreate(savedInstanceState)
14 | Log.d("XposedMusicNotify", "BackgroundActivity已启动")
15 | moveTaskToBack(true)
16 | }
17 |
18 | override fun onBackPressed() {
19 | super.onBackPressed()
20 | this.finish()
21 | }
22 |
23 | override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
24 | this.finish()
25 | return super.dispatchTouchEvent(ev)
26 | }
27 |
28 | override fun onStart() {
29 | super.onStart()
30 | setVisible(true)
31 | }
32 |
33 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Base/BasicInit.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Base;
2 |
3 | import android.content.Context;
4 |
5 | public abstract class BasicInit implements HookInterface {
6 |
7 | public BasicParam basicParam = new BasicParam();
8 | public ClassLoader classLoader;
9 |
10 | @Override
11 | public abstract void init();
12 |
13 | @Override
14 | public void initBefore() {
15 | init();
16 | }
17 |
18 | @Override
19 | public final BasicInit setClassLoader(ClassLoader mClassLoader) {
20 | classLoader = mClassLoader;
21 | return this;
22 | }
23 |
24 | @Override
25 | public final BasicInit setContext(Context mContext) {
26 | basicParam.setContext(mContext);
27 | return this;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Base/BasicParam.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Base
2 |
3 | import android.app.PendingIntent
4 | import android.content.Context
5 | import android.graphics.Bitmap
6 | import android.media.session.MediaSession
7 |
8 | class BasicParam {
9 |
10 | constructor()
11 | constructor(mContext: Context, mIcon: Int, mTitle: CharSequence, mText: CharSequence, mBitmap: Bitmap?, mStatue: Boolean, mToken: MediaSession.Token? = null, mIntent: PendingIntent) {
12 | context = mContext
13 | iconID = mIcon
14 | titleString = mTitle
15 | textString = mText
16 | bitmap = mBitmap
17 | statue = mStatue
18 | token = mToken
19 | contentIntent = mIntent
20 | }
21 |
22 | constructor(mContext: Context, mIcon: Int, mTitle: CharSequence, mText: CharSequence, mBitmap: Bitmap?, mStatue: Boolean, mToken: MediaSession.Token? = null) {
23 | context = mContext
24 | iconID = mIcon
25 | titleString = mTitle
26 | textString = mText
27 | bitmap = mBitmap
28 | statue = mStatue
29 | token = mToken
30 | }
31 |
32 | lateinit var titleString: CharSequence
33 | lateinit var textString: CharSequence
34 | var iconID: Int = -1
35 | var statue: Boolean = true
36 | var token: MediaSession.Token? = null
37 | var bitmap: Bitmap? = null
38 | var context: Context? = null
39 | var contentIntent: PendingIntent? = null
40 | var deleteIntent: PendingIntent? = null
41 |
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Base/BasicViewNotification.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Base;
2 |
3 | import android.app.Notification;
4 | import android.graphics.drawable.BitmapDrawable;
5 | import android.os.Build;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 | import android.widget.RemoteViews;
10 | import android.widget.TextView;
11 |
12 | import de.robv.android.xposed.XposedBridge;
13 | import de.robv.android.xposed.XposedHelpers;
14 |
15 | public abstract class BasicViewNotification extends BasicNotification {
16 |
17 | public Notification oldNotification;
18 | public int titleID;
19 | public int textID;
20 | public int bitmapID;
21 | public String className = "";
22 | public String methodName = "";
23 |
24 | protected BasicViewNotification() {
25 | }
26 |
27 | public final Notification viewBuild() {
28 | if (oldNotification == null) {
29 | Log.e("QQMusicNotify", "oldNotification should not be null!");
30 | return null;
31 | }
32 | RemoteViews remoteViews = (RemoteViews) XposedHelpers.getObjectField(oldNotification,"bigContentView");
33 | View view = remoteViews.apply(basicParam.getContext(), null);
34 | /*if (view==null) {
35 | Log.e("XposedMusicNotify", "RemoteView shoud not be bull");
36 | return null;
37 | }*/
38 | TextView titleTextView = view.findViewById(titleID);
39 | TextView textTextView = view.findViewById(textID);
40 | ImageView imageView = view.findViewById(bitmapID);
41 | basicParam.setTitleString(titleTextView.getText());
42 | basicParam.setTextString(textTextView.getText());
43 | basicParam.setBitmap(((BitmapDrawable) imageView.getDrawable()).getBitmap());
44 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
45 | channelID = oldNotification.getChannelId();
46 | }
47 | return this.build();
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Base/HookInterface.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Base;
2 |
3 | import android.content.Context;
4 |
5 | public interface HookInterface {
6 |
7 | void init();
8 |
9 | void initBefore();
10 |
11 | HookInterface setClassLoader(ClassLoader classLoader);
12 |
13 | HookInterface setContext(Context context);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/ContentProvider.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify
2 |
3 | import android.content.ContentProvider
4 | import android.content.ContentValues
5 | import android.content.Context
6 | import android.content.SharedPreferences
7 | import android.database.Cursor
8 | import android.media.session.MediaSession
9 | import android.net.Uri
10 | import android.os.Build
11 | import android.os.Bundle
12 | import android.os.Process
13 | import android.util.Log
14 | import androidx.annotation.Keep
15 | import androidx.annotation.StringDef
16 | import cn.nexus6p.QQMusicNotify.Utils.GeneralUtils
17 | import cn.nexus6p.QQMusicNotify.Utils.LogUtils
18 | import cn.nexus6p.QQMusicNotify.Utils.MediaSessionTokenHashMap.mediaSessionTokenMap
19 | import org.json.JSONObject
20 |
21 | @Keep
22 | class ContentProvider : ContentProvider() {
23 |
24 | companion object {
25 | const val CONTENT_PROVIDER_JSON: String = "content_provider_json"
26 | const val CONTENT_PROVIDER_PREFERENCE: String = "content_provider_preference"
27 | const val CONTENT_PROVIDER_DEVICE_PROTECTED_PREFERENCE: String = "content_provider_device_protected_preference"
28 | const val CONTENT_PROVIDER_COMMIT: String = "content_provider_commit"
29 | const val PUSH_MEDIA_SESSION_TOKEN: String = "push_mediasession_token"
30 | const val PULL_MEDIA_SESSION_TOKEN: String = "pull_mediasession_token"
31 | const val GET_ALL_SESSION_TOKEN: String = "get_all_session_token"
32 |
33 | const val BUNDLE_KEY_JSON_STRING: String = "bundle_key_json_string"
34 | const val BUNDLE_KEY_MEDIA_SESSION_TOKEN: String = "bundle_key_mediasession_token"
35 |
36 | /*@JvmStatic
37 | val mediaSessionTokenMap: HashMap = HashMap()*/
38 | }
39 |
40 | override fun call(@ContentProviderParams method: String, arg: String?, extras: Bundle?): Bundle? {
41 | //Log.d("XposedMusicNotify", "ContentProvider is called")
42 | val bundle = Bundle()
43 | if (method == CONTENT_PROVIDER_COMMIT) {
44 | LogUtils.addLog(arg!!, context!!)
45 | return Bundle().apply {
46 | putBoolean("success", true)
47 | }
48 | }
49 | if (method == PUSH_MEDIA_SESSION_TOKEN) {
50 | if (extras==null) return Bundle().apply {
51 | putBoolean("success", false)
52 | }
53 | val token = extras.get(BUNDLE_KEY_MEDIA_SESSION_TOKEN) as MediaSession.Token
54 | Log.d("XposedMusicNotify","get $arg's token:$token")
55 | Log.d("XposedMusicNotify","process: "+Process.myPid())
56 | mediaSessionTokenMap[arg!!] = token
57 | Log.d("XposedMusicNotify", mediaSessionTokenMap.toString())
58 | return Bundle().apply {
59 | putBoolean("success", true)
60 | }
61 | }
62 | if (method == PULL_MEDIA_SESSION_TOKEN) {
63 | val token = mediaSessionTokenMap[arg]
64 | return Bundle().apply {
65 | putParcelable(BUNDLE_KEY_MEDIA_SESSION_TOKEN,token)
66 | }
67 | }
68 | if (method == GET_ALL_SESSION_TOKEN) {
69 | return Bundle().apply {
70 | Log.d("XposedMusicNotify", "send hashMap $mediaSessionTokenMap")
71 | Log.d("XposedMusicNotify","process: "+Process.myPid())
72 | putSerializable(BUNDLE_KEY_MEDIA_SESSION_TOKEN, mediaSessionTokenMap)
73 | }
74 | }
75 | if (method == CONTENT_PROVIDER_JSON) {
76 | //Log.d("XposedMusicNotify","getJsonFile: "+GeneralUtils.getAssetsString("$arg.json",context))
77 | bundle.putString(BUNDLE_KEY_JSON_STRING, GeneralUtils.getAssetsString("$arg.json", context))
78 | } else {
79 | val mSharedPreferences: SharedPreferences = when (method) {
80 | CONTENT_PROVIDER_PREFERENCE -> GeneralUtils.getSharedPreferenceOnUI(context)
81 | CONTENT_PROVIDER_DEVICE_PROTECTED_PREFERENCE -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
82 | context!!.createDeviceProtectedStorageContext().getSharedPreferences("deviceProtected", Context.MODE_PRIVATE)
83 | } else {
84 | context!!.getSharedPreferences("deviceProtected", Context.MODE_PRIVATE)
85 | }
86 | else -> throw IllegalArgumentException()
87 | }
88 |
89 | bundle.putString(BUNDLE_KEY_JSON_STRING, JSONObject(mSharedPreferences.all).toString())
90 |
91 | }
92 | return bundle
93 | }
94 |
95 | override fun onCreate(): Boolean {
96 | return true
97 | }
98 |
99 | @Retention(AnnotationRetention.SOURCE)
100 | @StringDef(CONTENT_PROVIDER_DEVICE_PROTECTED_PREFERENCE, CONTENT_PROVIDER_JSON, CONTENT_PROVIDER_PREFERENCE, CONTENT_PROVIDER_COMMIT, PULL_MEDIA_SESSION_TOKEN, PUSH_MEDIA_SESSION_TOKEN)
101 | @Target(AnnotationTarget.VALUE_PARAMETER)
102 | annotation class ContentProviderParams
103 |
104 | override fun query(uri: Uri, projection: Array?, selection: String?, selectionArgs: Array?, sortOrder: String?): Cursor? {
105 | throw NoSuchMethodException()
106 | }
107 |
108 | override fun getType(uri: Uri): String? {
109 | throw NoSuchMethodException()
110 | }
111 |
112 | override fun insert(uri: Uri, values: ContentValues?): Uri? {
113 | throw NoSuchMethodException()
114 | }
115 |
116 | override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array?): Int {
117 | throw NoSuchMethodException()
118 | }
119 |
120 | override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
121 | throw NoSuchMethodException()
122 | }
123 |
124 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/AppsFragment.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment;
2 |
3 |
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager;
6 | import android.os.Build;
7 | import android.os.Bundle;
8 |
9 | import androidx.annotation.Keep;
10 | import androidx.preference.Preference;
11 | import androidx.preference.PreferenceCategory;
12 | import androidx.preference.PreferenceFragmentCompat;
13 |
14 | import org.json.JSONArray;
15 |
16 | import cn.nexus6p.QQMusicNotify.BuildConfig;
17 | import cn.nexus6p.QQMusicNotify.R;
18 | import cn.nexus6p.QQMusicNotify.Utils.GeneralUtils;
19 |
20 | @Keep
21 | public class AppsFragment extends PreferenceFragmentCompat {
22 |
23 | @Override
24 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
25 | addPreferencesFromResource(R.xml.apps);
26 | //boolean PMEnabled = getSharedPreferenceOnUI(getActivity()).getBoolean("pm", true);
27 | try {
28 | JSONArray jsonArray = GeneralUtils.getSupportPackages(this.getContext());
29 | for (int i = 0; i < jsonArray.length(); i++) {
30 | String packageName = jsonArray.getJSONObject(i).getString("app");
31 | if (!(BuildConfig.DEBUG) && packageName.contains("com.kugou.android") && Build.VERSION.SDK_INT > 28)
32 | continue;
33 | Preference preference = new Preference(getActivity(), null);
34 | //if (PMEnabled) {
35 | PackageInfo packageInfo;
36 | try {
37 | packageInfo = getActivity().getPackageManager().getPackageInfo(packageName, 0);
38 | } catch (PackageManager.NameNotFoundException e) {
39 | packageInfo = null;
40 | }
41 | if (packageInfo == null) continue;
42 | else
43 | preference.setIcon(getActivity().getPackageManager().getApplicationIcon(packageName));
44 | //}
45 | preference.setTitle(jsonArray.getJSONObject(i).getString("name"));
46 | preference.setSummary(packageName);
47 | preference.setOnPreferenceClickListener(preference1 -> {
48 | getActivity().getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out, R.anim.slide_left_in, R.anim.slide_right_out).replace(R.id.content_frame, DetailFragment.Companion.newInstance(packageName)).addToBackStack(DetailFragment.class.getSimpleName()).commit();
49 | return true;
50 | });
51 | ((PreferenceCategory) findPreference("app")).addPreference(preference);
52 | }
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 |
57 | findPreference("thirdPartySource").setOnPreferenceClickListener(preference -> {
58 | getActivity().getSupportFragmentManager().beginTransaction().setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out, R.anim.slide_left_in, R.anim.slide_right_out).replace(R.id.content_frame, new ThirdPartySourceFragment()).addToBackStack(ThirdPartySourceFragment.class.getSimpleName()).commit();
59 | return true;
60 | });
61 |
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/ExperimentalFragment.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.Keep;
6 | import androidx.preference.PreferenceFragmentCompat;
7 |
8 | import cn.nexus6p.QQMusicNotify.MainActivity;
9 | import cn.nexus6p.QQMusicNotify.R;
10 |
11 | @Keep
12 | public class ExperimentalFragment extends PreferenceFragmentCompat {
13 | @Override
14 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
15 | addPreferencesFromResource(R.xml.experimental);
16 | findPreference("fakeTaichi").setOnPreferenceChangeListener((preference, newValue) -> {
17 | ((MainActivity) getActivity()).reload();
18 | return true;
19 | });
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/JsonDetailFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment
2 |
3 | import android.os.Bundle
4 | import androidx.annotation.Keep
5 | import androidx.preference.Preference
6 | import androidx.preference.PreferenceCategory
7 | import androidx.preference.PreferenceFragmentCompat
8 | import cn.nexus6p.QQMusicNotify.R
9 | import org.json.JSONObject
10 |
11 | @Keep
12 | class JsonDetailFragment private constructor() : PreferenceFragmentCompat() {
13 |
14 | companion object {
15 | fun newInstance(jsonString: String): JsonDetailFragment {
16 | val bundle = Bundle()
17 | bundle.putString("jsonString", jsonString)
18 | val jsonDetailFragment = JsonDetailFragment()
19 | jsonDetailFragment.arguments = bundle
20 | return jsonDetailFragment
21 | }
22 | }
23 |
24 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
25 | addPreferencesFromResource(R.xml.json_detail)
26 | if (arguments == null) throw IllegalAccessException("Arguments should not be null,please use newInstance to get a DetailFragment object and set the param as the packageName")
27 | try {
28 | val jsonString = requireArguments().getString("jsonString")
29 | val jsonObject = JSONObject(jsonString!!)
30 | val detailPreferenceCategory: PreferenceCategory = findPreference("JSONDetail")!!
31 | for (key in jsonObject.keys()) {
32 | val preference = Preference(requireContext())
33 | preference.title = key
34 | preference.summary = jsonObject.optString(key)
35 | detailPreferenceCategory.addItemFromInflater(preference)
36 | }
37 | } catch (e: Exception) {
38 | e.printStackTrace()
39 | }
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/MediaNotificationFragment.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.graphics.drawable.GradientDrawable;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.widget.Toast;
9 |
10 | import androidx.annotation.Keep;
11 | import androidx.preference.EditTextPreference;
12 | import androidx.preference.ListPreference;
13 | import androidx.preference.PreferenceFragmentCompat;
14 |
15 | import cn.nexus6p.QQMusicNotify.R;
16 |
17 | @Keep
18 | public class MediaNotificationFragment extends PreferenceFragmentCompat {
19 | @Override
20 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
21 | getPreferenceManager().setSharedPreferencesMode(Context.MODE_PRIVATE);
22 | addPreferencesFromResource(cn.nexus6p.QQMusicNotify.R.xml.media_notification);
23 | String[] strings = getContext().getResources().getStringArray(R.array.pickColorMode);
24 | ListPreference preference = findPreference("colorMethod");
25 | preference.setSummary(preference.getEntry());
26 | preference.setOnPreferenceChangeListener((preference1, newValue) -> {
27 | preference.setSummary(strings[Integer.parseInt(newValue.toString())]);
28 | //preferenceChangeListener(preference1,newValue);
29 | return true;
30 | });
31 |
32 | /*findPreference("inverseTextColors").setOnPreferenceChangeListener((preference1, newValue) -> {
33 | preferenceChangeListener(preference1,newValue);
34 | return true;
35 | });
36 |
37 | findPreference("highContrastText").setOnPreferenceChangeListener((preference1, newValue) -> {
38 | preferenceChangeListener(preference1,newValue);
39 | return true;
40 | });*/
41 |
42 | EditTextPreference colorPreference = findPreference("customColor");
43 | colorPreference.setSummary(colorPreference.getText());
44 | colorPreference.setOnPreferenceChangeListener((preference1, newValue) -> {
45 | if (!newValue.toString().matches("\\#[0-9a-fA-F]{6}")) {
46 | Log.d("newValue", newValue.toString());
47 | Toast.makeText(getActivity(), "请输入16进制RGB颜色", Toast.LENGTH_LONG).show();
48 | return false;
49 | }
50 | colorPreference.setSummary((CharSequence) newValue);
51 | GradientDrawable drawable = (GradientDrawable) getContext().getDrawable(R.drawable.color_drawable);
52 | drawable.setColor(Color.parseColor((String) newValue));
53 | colorPreference.setIcon(drawable);
54 | //preferenceChangeListener(preference1,newValue);
55 | return true;
56 | });
57 | GradientDrawable drawable = (GradientDrawable) getContext().getDrawable(R.drawable.color_drawable);
58 | drawable.setColor(Color.parseColor(colorPreference.getText()));
59 | findPreference("customColor").setIcon(drawable);
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/MusicNotificationFragment.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment;
2 |
3 | import android.os.Bundle;
4 | import android.widget.Button;
5 |
6 | import androidx.annotation.Keep;
7 | import androidx.appcompat.app.AlertDialog;
8 | import androidx.preference.PreferenceFragmentCompat;
9 |
10 | import com.google.android.material.dialog.MaterialAlertDialogBuilder;
11 |
12 | import cn.nexus6p.QQMusicNotify.MainActivity;
13 | import cn.nexus6p.QQMusicNotify.R;
14 | import cn.nexus6p.QQMusicNotify.Utils.HookStatue;
15 |
16 | import static cn.nexus6p.QQMusicNotify.Utils.GeneralUtils.deviceContextPreferenceChangeListener;
17 |
18 | @Keep
19 | public class MusicNotificationFragment extends PreferenceFragmentCompat {
20 | @Override
21 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
22 | addPreferencesFromResource(R.xml.music_notification);
23 | //GeneralUtils.bindPreference(this,"styleModify","always_show");
24 | if (HookStatue.isExpModuleActive(getActivity()) > 0) {
25 | findPreference("miuiModify").setSummary("仅太极·阳有效,请将SystemUI加入太极");
26 | }
27 |
28 | findPreference("styleModify").setOnPreferenceChangeListener((preference, newValue) -> {
29 | ((MainActivity) getActivity()).reload();
30 | return true;
31 | });
32 | /*findPreference("always_show").setOnPreferenceChangeListener((preference, newValue) -> {
33 | preferenceChangeListener(preference,newValue);
34 | return true;
35 | });*/
36 | findPreference("miuiModify").setOnPreferenceChangeListener((preference, newValue) -> {
37 | deviceContextPreferenceChangeListener(preference, newValue, getActivity());
38 | return true;
39 | });
40 | findPreference("miuiForceExpand").setOnPreferenceChangeListener((preference, newValue) -> {
41 | deviceContextPreferenceChangeListener(preference, newValue, getActivity());
42 | return true;
43 | });
44 |
45 | }
46 |
47 | @Override
48 | public void onStart() {
49 | super.onStart();
50 | AlertDialog dialog = new MaterialAlertDialogBuilder(getActivity())
51 | .setTitle("关于去白边及强制展开")
52 | .setMessage("此功能是否生效取决于您的手机系统及框架,且不属于本模块的常规功能范畴,本人不为其效果提供任何保证及咨询服务,本功能在您的手机上失效亦不会属于未来任何一个版本的修复内容。关于部分ROM上的通知如何去除白边或强制展开,请自行去相关论坛或手机系统交流群咨询。\n\n下面列出一个可能会有用但没用也不关我事的网址:\nhttps://github.com/singleNeuron/XposedRemoveNotificationWhiteFrame/releases")
53 | .setCancelable(false)
54 | .setPositiveButton("我已阅读并知悉 (5)", null)
55 | .create();
56 | dialog.show();
57 | Button button = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
58 | button.setEnabled(false);
59 | new Thread(() -> {
60 | for (int i = 5; i > 0; i--) {
61 | int finalI = i;
62 | getActivity().runOnUiThread(() -> {
63 | button.setText("我已阅读并知悉 (" + finalI + ")");
64 | });
65 | try {
66 | Thread.sleep(1000);
67 | } catch (InterruptedException e) {
68 | e.printStackTrace();
69 | }
70 | }
71 | getActivity().runOnUiThread(() -> {
72 | button.setText("我已阅读并知悉");
73 | });
74 | getActivity().runOnUiThread(() -> {
75 | button.setEnabled(true);
76 | });
77 | }).start();
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/PlayingFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment
2 |
3 | import android.graphics.drawable.BitmapDrawable
4 | import android.media.MediaMetadata
5 | import android.media.session.MediaController
6 | import android.media.session.MediaSession
7 | import android.os.Bundle
8 | import android.util.Log
9 | import android.view.LayoutInflater
10 | import android.view.View
11 | import android.view.ViewGroup
12 | import android.widget.LinearLayout
13 | import android.widget.Toast
14 | import androidx.fragment.app.Fragment
15 | import cn.nexus6p.QQMusicNotify.ContentProvider
16 | import cn.nexus6p.QQMusicNotify.SharedPreferences.ContentProviderPreference
17 | import cn.nexus6p.QQMusicNotify.SimpleAlcatrazInteractiveCardView
18 | import soptqs.medianotification.utils.PaletteUtils
19 |
20 | private lateinit var linearLayout: LinearLayout
21 |
22 | class PlayingFragment : Fragment() {
23 |
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | linearLayout = LinearLayout(context)
26 | linearLayout.orientation = LinearLayout.VERTICAL
27 | return linearLayout
28 | }
29 |
30 | override fun onResume() {
31 | super.onResume()
32 | linearLayout.removeAllViews()
33 | val packageManager = requireContext().packageManager
34 | val hashMap: HashMap? = ContentProviderPreference.getBundle(ContentProvider.GET_ALL_SESSION_TOKEN,null,requireContext())?.getSerializable(ContentProvider.BUNDLE_KEY_MEDIA_SESSION_TOKEN) as HashMap?
35 | if (hashMap==null) {
36 | Toast.makeText(requireContext(), "获取失败", Toast.LENGTH_SHORT).show()
37 | return
38 | }
39 | Log.d("XposedMusicNotify","get hashMap $hashMap")
40 | for (entry in hashMap) {
41 | val cardView = SimpleAlcatrazInteractiveCardView(requireContext())
42 | cardView.titleLine = try {
43 | packageManager.getApplicationLabel(packageManager.getApplicationInfo(entry.key,0)).toString()
44 | } catch (e:Exception) {
45 | entry.key
46 | }
47 | try{
48 | val metaData = MediaController(requireContext(),entry.value).metadata ?: continue
49 | Log.d("XposedMusicNotify",metaData.keySet().toTypedArray().joinToString())
50 | var title = metaData.getString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE)
51 | if (title.isNullOrBlank()) title = metaData.getString(MediaMetadata.METADATA_KEY_TITLE)
52 | cardView.firstLine = title
53 | cardView.secondLine = metaData.getString(MediaMetadata.METADATA_KEY_ARTIST)
54 | var bitmap = metaData.getBitmap(MediaMetadata.METADATA_KEY_DISPLAY_ICON)
55 | if (bitmap==null) bitmap = metaData.getBitmap(MediaMetadata.METADATA_KEY_ART)
56 | if (bitmap==null) bitmap = metaData.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
57 | var icon = packageManager.getApplicationIcon(entry.key)
58 | if (bitmap!=null) {
59 | icon = BitmapDrawable(resources,bitmap)
60 | } else if (icon is BitmapDrawable) {
61 | bitmap = icon.bitmap
62 | }
63 | cardView.iconDrawable = icon
64 | if (bitmap!=null) {
65 | cardView.color = PaletteUtils.getSwatch(PaletteUtils.getPalette(bitmap),requireContext()).rgb
66 | }
67 | linearLayout.addView(cardView)
68 | }catch (e:Exception) {
69 | e.printStackTrace()
70 | }
71 | }
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/SettingFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment
2 |
3 | import android.content.ActivityNotFoundException
4 | import android.content.Intent
5 | import android.net.Uri
6 | import android.os.Bundle
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import android.widget.ImageView
11 | import android.widget.LinearLayout
12 | import android.widget.TextView
13 | import androidx.cardview.widget.CardView
14 | import androidx.core.content.ContextCompat
15 | import androidx.fragment.app.Fragment
16 | import cn.nexus6p.QQMusicNotify.R
17 | import cn.nexus6p.QQMusicNotify.Utils.GeneralUtils
18 | import cn.nexus6p.QQMusicNotify.Utils.HookStatue
19 | import cn.nexus6p.QQMusicNotify.Utils.LogUtils
20 |
21 | class SettingFragment : Fragment() {
22 |
23 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
24 | super.onCreateView(inflater, container, savedInstanceState)
25 | val view = inflater.inflate(R.layout.setting_fragment, container, false)
26 | childFragmentManager.beginTransaction().setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out, R.anim.slide_left_in, R.anim.slide_right_out).replace(R.id.content_frame3, SettingsFragment()).addToBackStack(SettingsFragment::class.java.simpleName).commit()
27 |
28 | val shardPreferences = GeneralUtils.getSharedPreferenceOnUI(context)
29 |
30 | val cardView = view.findViewById(R.id.cardview)
31 | val cardViewLinearLayout = view.findViewById(R.id.setting_linearLayout)
32 | val cardViewTitle = view.findViewById(R.id.cardView_Title)
33 | val cardViewImage = view.findViewById(R.id.cardView_image)
34 | val statue = HookStatue.getStatue(activity)
35 | cardViewTitle.text = HookStatue.getStatueName(statue)
36 | if (HookStatue.isActive(statue)) {
37 | cardViewImage.setImageResource(R.drawable.ic_check_circle)
38 | if (shardPreferences.getBoolean("colorCardView", true)) cardViewLinearLayout.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.green))
39 | } else {
40 | cardViewImage.setImageResource(R.drawable.ic_cancel)
41 | if (shardPreferences.getBoolean("colorCardView", true)) cardViewLinearLayout.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.colorError))
42 | }
43 |
44 | if (statue.name.contains("taichi", true)) {
45 | if (HookStatue.isActive(statue)) {
46 | cardView.setOnClickListener {
47 | requireActivity().supportFragmentManager.beginTransaction().setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out, R.anim.slide_left_in, R.anim.slide_right_out).replace(R.id.content_frame, LogFragment(), "logFragment").addToBackStack(LogFragment::class.java.simpleName).commit()
48 | }
49 | cardViewImage.apply {
50 | setOnClickListener {
51 | //activity!!.toast("跳转到太极")
52 | val t = Intent("me.weishu.exp.ACTION_MODULE_MANAGE");
53 | t.data = Uri.parse("package:" + "cn.nexus6p.QQMusicNotify");
54 | t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
55 | try {
56 | startActivity(t);
57 | } catch (e: ActivityNotFoundException) {
58 | //ignore
59 | }
60 | }
61 | isClickable = true
62 | }
63 | } else {
64 | cardView.apply {
65 | setOnClickListener {
66 | //activity!!.toast("跳转到太极")
67 | val t = Intent("me.weishu.exp.ACTION_MODULE_MANAGE");
68 | t.data = Uri.parse("package:" + "cn.nexus6p.QQMusicNotify");
69 | t.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
70 | try {
71 | startActivity(t);
72 | } catch (e: ActivityNotFoundException) {
73 | //ignore
74 | }
75 | }
76 | isClickable = true
77 | }
78 | }
79 | } else {
80 | cardView.setOnClickListener {
81 | requireActivity().supportFragmentManager.beginTransaction().setCustomAnimations(R.anim.slide_right_in, R.anim.slide_left_out, R.anim.slide_left_in, R.anim.slide_right_out).replace(R.id.content_frame, LogFragment(), "logFragment").addToBackStack(LogFragment::class.java.simpleName).commit()
82 | }
83 | }
84 |
85 | return view
86 | }
87 |
88 | override fun onResume() {
89 | super.onResume()
90 | LogUtils.cleanLog(GeneralUtils.getSharedPreferenceOnUI(context).getInt("logMaxLine", 1000), requireContext())
91 | val cardViewSummary = requireView().findViewById(R.id.cardView_summary)
92 | cardViewSummary.text = "已应用" + LogUtils.getLineCount(requireContext()) + "次"
93 | }
94 |
95 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Fragment/ThirdPartySourceFragment.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Fragment
2 |
3 | import android.content.DialogInterface
4 | import android.graphics.Color
5 | import android.os.Bundle
6 | import android.view.LayoutInflater
7 | import android.view.View
8 | import android.view.ViewGroup
9 | import android.widget.EditText
10 | import android.widget.ProgressBar
11 | import android.widget.Toast
12 | import androidx.annotation.Keep
13 | import androidx.core.content.ContextCompat
14 | import androidx.fragment.app.Fragment
15 | import cn.nexus6p.QQMusicNotify.R
16 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
17 | import com.google.android.material.floatingactionbutton.FloatingActionButton
18 | import org.json.JSONObject
19 | import java.io.File
20 | import java.net.URL
21 |
22 | @Keep
23 | class ThirdPartySourceFragment : Fragment() {
24 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
25 | super.onCreateView(inflater, container, savedInstanceState)
26 | val view = inflater.inflate(R.layout.third_party_source, container, false)
27 | childFragmentManager.beginTransaction().replace(R.id.content_frame2, ThirdPartySourceListFragment()).addToBackStack(ThirdPartySourceListFragment::class.java.simpleName).commit()
28 | val floatingActionButton = view.findViewById(R.id.floating_action_button)
29 | floatingActionButton.setColorFilter(Color.WHITE)
30 | floatingActionButton.rippleColor = ContextCompat.getColor(requireContext(), R.color.colorPrimaryVariant)
31 | floatingActionButton.setOnClickListener {
32 | val editText = EditText(activity)
33 | MaterialAlertDialogBuilder(requireContext())
34 | .setTitle("请输入源地址")
35 | .setView(editText)
36 | .setNegativeButton("取消", null)
37 | .setPositiveButton("确定", DialogInterface.OnClickListener { _, _ ->
38 | val builder = MaterialAlertDialogBuilder(requireContext())
39 | builder.setTitle("下载中...description.json")
40 | builder.setCancelable(false)
41 | val progressBar = ProgressBar(context)
42 | builder.setView(progressBar)
43 | val alertDialog = builder.create()
44 | alertDialog.show()
45 | Thread(Runnable {
46 | try {
47 | val jsonString: String = URL(editText.text.toString() + (if (editText.text.toString().endsWith("/")) "" else "/") + "description.json").readText()
48 | val jsonObject = JSONObject(jsonString)
49 | val id = jsonObject.optString("id")
50 | val files = File(requireContext().getExternalFilesDir("ThirdPartySource").toString() + File.separator + id)
51 | if (!files.exists()) files.mkdir()
52 | File(files.toString() + File.separator + "description.json").writeText(jsonString)
53 | File(files.toString() + File.separator + "packages.json").writeBytes(URL(editText.text.toString() + (if (editText.text.toString().endsWith("/")) "" else "/") + "packages.json").readBytes())
54 | requireActivity().runOnUiThread {
55 | childFragmentManager.beginTransaction().replace(R.id.content_frame2, ThirdPartySourceListFragment()).commit()
56 | }
57 | } catch (e: Exception) {
58 | requireActivity().runOnUiThread { Toast.makeText(requireActivity(), e.toString(), Toast.LENGTH_SHORT).show() }
59 | e.printStackTrace()
60 | } finally {
61 | requireActivity().runOnUiThread(alertDialog::dismiss)
62 | }
63 | }).start()
64 | }).show()
65 | }
66 | return view
67 | }
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/cnkuwoplayer.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationChannel;
5 | import android.app.NotificationManager;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.SharedPreferences;
9 | import android.graphics.Bitmap;
10 | import android.media.session.MediaSession;
11 |
12 | import androidx.annotation.Keep;
13 |
14 | import cn.nexus6p.QQMusicNotify.Base.BasicNotification;
15 | import cn.nexus6p.QQMusicNotify.Utils.GeneralUtils;
16 | import cn.nexus6p.QQMusicNotify.Utils.PreferenceUtil;
17 | import de.robv.android.xposed.XC_MethodReplacement;
18 | import de.robv.android.xposed.XposedHelpers;
19 |
20 | import static android.content.Context.NOTIFICATION_SERVICE;
21 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
22 | import static de.robv.android.xposed.XposedHelpers.getObjectField;
23 |
24 | @Keep
25 | public class cnkuwoplayer extends BasicNotification {
26 |
27 | private static MediaSession.Token mTOKEN;
28 |
29 | @Override
30 | public void init() {
31 | SharedPreferences preference = PreferenceUtil.getJSONPreference("cn.kuwo.player", basicParam.getContext());
32 | String className = preference.getString("class", "");
33 | String methodName = preference.getString("method", "");
34 | //int iconID = preference.getInt("iconID", -1);
35 | String contextField = preference.getString("contextField", "");
36 | String preSongIntentName = preference.getString("preSongIntent", "");
37 | String playSongIntentName = preference.getString("playSongIntent", "");
38 | String nextSongIntentName = preference.getString("nextSongIntent", "");
39 | String IntentHandleActivity = preference.getString("IntentHandleActivity", "");
40 | String getStatusClass = preference.getString("getStatusClass", "");
41 | String getStatusMethod = preference.getString("getStatusMethod", "");
42 | String getStatusMethod2 = preference.getString("getStatusMethod2", "");
43 | String playProxyStatusClass = preference.getString("playProxyStatusClass", "");
44 | String playProxyStatusField = preference.getString("playProxyStatusField", "");
45 | //extraActionIcon = preference.getInt("extraActionIcon", -1);
46 | String extraActionIntentName = preference.getString("extraActionIntent", "");
47 |
48 | Class drawableClass = XposedHelpers.findClass(preference.getString("drawableClass",""),classLoader);
49 | int iconID = XposedHelpers.getStaticIntField(drawableClass,preference.getString("iconField",""));
50 | extraActionIcon = XposedHelpers.getStaticIntField(drawableClass,preference.getString("extraActionIconField",""));
51 |
52 | final Class notifyClazz = XposedHelpers.findClass(className, classLoader);
53 | findAndHookMethod(notifyClazz, methodName, Bitmap.class, String.class, String.class, String.class, new XC_MethodReplacement() {
54 | @Override
55 | protected Notification replaceHookedMethod(MethodHookParam param) throws Throwable {
56 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
57 | channelID = "music1";
58 | NotificationChannel channel = new NotificationChannel(channelID, "音乐通知", NotificationManager.IMPORTANCE_LOW);
59 | channel.setSound(null, null);
60 | channel.enableVibration(false);
61 | ((NotificationManager) GeneralUtils.getContext().getSystemService(NOTIFICATION_SERVICE)).deleteNotificationChannel("music");
62 | ((NotificationManager) GeneralUtils.getContext().getSystemService(NOTIFICATION_SERVICE)).createNotificationChannel(channel);
63 | }
64 | basicParam.setIconID(iconID);
65 | basicParam.setContext((Context) getObjectField(param.thisObject, contextField));
66 | basicParam.setBitmap((Bitmap) param.args[0]);
67 | if (mTOKEN == null)
68 | mTOKEN = new MediaSession(basicParam.getContext(), "MediaSessionHelper").getSessionToken();
69 | basicParam.setToken(mTOKEN);
70 | basicParam.setTitleString((CharSequence) param.args[1]);
71 | basicParam.setTextString((CharSequence) param.args[2]);
72 | preSongIntent = new Intent(preSongIntentName);
73 | playIntent = new Intent(playSongIntentName);
74 | nextSongIntent = new Intent(nextSongIntentName);
75 | contentIntent = new Intent(basicParam.getContext(), XposedHelpers.findClass(IntentHandleActivity, classLoader));
76 | contentIntent.setAction("android.intent.action.MAIN")
77 | .addCategory("android.intent.category.LAUNCHER");
78 | intentRequestID = 1;
79 | hasExtraAction = true;
80 | extraActionIntent = new Intent(extraActionIntentName);
81 | Object object = XposedHelpers.callStaticMethod(XposedHelpers.findClass(getStatusClass, classLoader), getStatusMethod);
82 | Object object2 = XposedHelpers.callMethod(object, getStatusMethod2);
83 | Object object3 = XposedHelpers.getStaticObjectField(XposedHelpers.findClass(playProxyStatusClass, classLoader), playProxyStatusField);
84 | basicParam.setStatue(object2.equals(object3));
85 | return build();
86 | }
87 | });
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comkugouandroid.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.content.SharedPreferences;
4 | import android.os.Build;
5 | import android.widget.Toast;
6 |
7 | import androidx.annotation.Keep;
8 |
9 | import cn.nexus6p.QQMusicNotify.Base.BasicInit;
10 | import cn.nexus6p.QQMusicNotify.BuildConfig;
11 | import cn.nexus6p.QQMusicNotify.Utils.PreferenceUtil;
12 | import de.robv.android.xposed.XC_MethodHook;
13 | import de.robv.android.xposed.XC_MethodReplacement;
14 | import de.robv.android.xposed.XposedBridge;
15 | import de.robv.android.xposed.XposedHelpers;
16 |
17 | @Keep
18 | public class comkugouandroid extends BasicInit {
19 |
20 | @Override
21 | public void init() {
22 | if ((!BuildConfig.DEBUG) && Build.VERSION.SDK_INT > 28) return;
23 | try {
24 | Class preferenceClass = XposedHelpers.findClass("com.kugou.framework.setting.preference.Preference", classLoader);
25 | XposedHelpers.findAndHookMethod("com.kugou.framework.setting.preference.PreferenceGroup", classLoader, "removePreference", preferenceClass, new XC_MethodHook() {
26 | @Override
27 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
28 | Object preference = param.args[0];
29 | String key = (String) XposedHelpers.callMethod(preference, "getKey");
30 | XposedBridge.log("XposedMusicNotify: get key " + key);
31 | if (key.contains("USE_KG_NOTIFICATION")) {
32 | Toast.makeText(basicParam.getContext(), "stop kugou removing " + key, Toast.LENGTH_SHORT).show();
33 | param.setResult(true);
34 | }
35 | }
36 | });
37 | } catch (Exception e) {
38 | e.printStackTrace();
39 | }
40 | SharedPreferences preference = PreferenceUtil.getJSONPreference("com.kugou.android", basicParam.getContext());
41 | String className = preference.getString("class", "");
42 | try {
43 | String method1 = preference.getString("method1", "");
44 | XposedHelpers.findAndHookMethod(className, classLoader, method1, new XC_MethodReplacement() {
45 | @Override
46 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
47 | return false;
48 | }
49 | });
50 | } catch (Exception e) {
51 | e.printStackTrace();
52 | }
53 | try {
54 | String method2 = preference.getString("method2", "");
55 | XposedHelpers.findAndHookMethod(className, classLoader, method2, boolean.class, new XC_MethodReplacement() {
56 | @Override
57 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
58 | return false;
59 | }
60 | });
61 | } catch (Exception e) {
62 | e.printStackTrace();
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comneteasecloudmusic.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.content.SharedPreferences;
4 |
5 | import androidx.annotation.Keep;
6 |
7 | import cn.nexus6p.QQMusicNotify.Base.BasicInit;
8 | import de.robv.android.xposed.XC_MethodHook;
9 | import de.robv.android.xposed.XposedHelpers;
10 |
11 | @Keep
12 | public class comneteasecloudmusic extends BasicInit {
13 |
14 | @Override
15 | public void init() {
16 | XposedHelpers.findAndHookMethod(SharedPreferences.class, "getInt", String.class, int.class, new XC_MethodHook() {
17 | @Override
18 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
19 | if (param.args[0].equals("notificationBackground")) {
20 | param.setResult(2);
21 | }
22 | }
23 | });
24 | XposedHelpers.findAndHookMethod(SharedPreferences.Editor.class, "putInt", String.class, int.class, new XC_MethodHook() {
25 | @Override
26 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
27 | if (param.args[0].equals("notificationBackground")) {
28 | param.args[1] = 2;
29 | }
30 | }
31 | });
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comsingclient.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.app.Notification;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.drawable.BitmapDrawable;
7 | import android.media.session.MediaSession;
8 | import android.view.View;
9 | import android.widget.ImageView;
10 | import android.widget.RemoteViews;
11 | import android.widget.TextView;
12 |
13 | import androidx.annotation.Keep;
14 |
15 | import cn.nexus6p.QQMusicNotify.Base.BasicViewNotification;
16 | import de.robv.android.xposed.XC_MethodHook;
17 | import de.robv.android.xposed.XposedHelpers;
18 |
19 | @Keep
20 | public class comsingclient extends BasicViewNotification {
21 |
22 | private static MediaSession.Token mTOKEN;
23 |
24 | @Override
25 | public void init() {
26 |
27 | Class songClazz = XposedHelpers.findClass("com.sing.client.model.Song", classLoader);
28 | XposedHelpers.findAndHookMethod("com.kugou.common.player.manager.b", classLoader, "h", songClazz, new XC_MethodHook() {
29 | @Override
30 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
31 | oldNotification = (Notification) XposedHelpers.getObjectField(param.thisObject, "b");
32 | basicParam.setContext((Context) XposedHelpers.getObjectField(param.thisObject, "a"));
33 | basicParam.setIconID(0x7f0207f1);
34 | titleID = 0x7f100bf8;
35 | textID = 0x7f100bf9;
36 | bitmapID = 0x7f100bf7;
37 | RemoteViews remoteViews = (RemoteViews) XposedHelpers.getObjectField(oldNotification,"bigContentView");
38 | View view = remoteViews.apply(basicParam.getContext(), null);
39 | try {
40 | basicParam.setBitmap(((BitmapDrawable) ((ImageView) view.findViewById(bitmapID)).getDrawable()).getBitmap());
41 | basicParam.setTextString(((TextView) view.findViewById(titleID)).getText());
42 | basicParam.setTextString(((TextView) view.findViewById(textID)).getText());
43 | } catch (Exception e) {
44 | e.printStackTrace();
45 | }
46 | if (mTOKEN == null)
47 | mTOKEN = new MediaSession(basicParam.getContext(), "MediaSessionHelper").getSessionToken();
48 | basicParam.setToken(mTOKEN);
49 | playIntent = new Intent("com.sing.client.click_action_pause");
50 | preSongIntent = new Intent("com.sing.client.click_action_pre");
51 | nextSongIntent = new Intent("com.sing.client.click_action");
52 | hasExtraAction = false;
53 | extraActionIcon = 0x7f020207;
54 | extraActionIntent = new Intent("com.sing.client.click_action_lyric");
55 | contentIntent = new Intent().putExtra("isFrom", "isFromPlay").setClass(basicParam.getContext(), XposedHelpers.findClass("com.sing.client.play.ui.PlayerActivity", classLoader));
56 | intentRequestID = 5;
57 | XposedHelpers.setObjectField(param.thisObject, "b", build());
58 | }
59 | });
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comtencentkaraoke.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.app.Notification;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.SharedPreferences;
7 | import android.media.session.MediaSession;
8 | import android.net.Uri;
9 | import android.os.Parcelable;
10 |
11 | import androidx.annotation.Keep;
12 |
13 | import org.json.JSONArray;
14 |
15 | import cn.nexus6p.QQMusicNotify.Base.BasicViewNotification;
16 | import cn.nexus6p.QQMusicNotify.SharedPreferences.ContentProviderPreference;
17 | import cn.nexus6p.QQMusicNotify.Utils.PreferenceUtil;
18 | import de.robv.android.xposed.XC_MethodHook;
19 | import de.robv.android.xposed.XposedBridge;
20 | import de.robv.android.xposed.XposedHelpers;
21 |
22 | @Keep
23 | public class comtencentkaraoke extends BasicViewNotification {
24 |
25 | private static MediaSession.Token mTOKEN;
26 |
27 | @Override
28 | public void init() {
29 | SharedPreferences preference = PreferenceUtil.getJSONPreference("com.tencent.karaoke", basicParam.getContext());
30 | className = preference.getString("class", "");
31 | methodName = preference.getString("method", "");
32 | //titleID = preference.getInt("titleID", -1);
33 | //textID = preference.getInt("textID", -1);
34 | //bitmapID = preference.getInt("bitmapID", -1);
35 | basicParam.setIconID(preference.getInt("iconID", -1));
36 | String intentClass = preference.getString("intentClass", "");
37 | String preSongField = preference.getString("preSongField", "");
38 | String playSongField = preference.getString("playSongField", "");
39 | String nextSongField = preference.getString("nextSongField", "");
40 | String deleteField = preference.getString("deleteField", "");
41 | String IntentHandleActivity = preference.getString("IntentHandleActivity", "");
42 |
43 | Class idClass = XposedHelpers.findClass(preference.getString("idClass",""),classLoader);
44 | titleID = XposedHelpers.getStaticIntField(idClass,preference.getString("titleField",""));
45 | textID = XposedHelpers.getStaticIntField(idClass,preference.getString("textField",""));
46 | bitmapID = XposedHelpers.getStaticIntField(idClass,preference.getString("bitmapField",""));
47 |
48 | JSONArray params = ((ContentProviderPreference) preference).jsonObject.optJSONArray("params");
49 | Object[] objects = new Object[params.length() + 1];
50 | try {
51 | for (int i = 0; i < params.length(); i++) {
52 | objects[i] = (params.get(i).toString().equals("int")) ? int.class : XposedHelpers.findClass(params.get(i).toString(), classLoader);
53 | }
54 | } catch (Exception e) {
55 | e.printStackTrace();
56 | }
57 | objects[params.length()] = new XC_MethodHook() {
58 | @Override
59 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
60 | basicParam.setContext((Context) param.args[0]);
61 | Parcelable playSongInfo = (Parcelable) param.args[1];
62 | oldNotification = (Notification) param.getResult();
63 | basicParam.setStatue(((int) param.args[2]) == 8);
64 | if (mTOKEN == null)
65 | mTOKEN = new MediaSession(basicParam.getContext(), "Karaoke media button").getSessionToken();
66 | basicParam.setToken(mTOKEN);
67 | preSongIntent = new Intent((String) XposedHelpers.getStaticObjectField(XposedHelpers.findClass(intentClass, classLoader), preSongField)).putExtra("play_current_song", playSongInfo);
68 | playIntent = new Intent((String) XposedHelpers.getStaticObjectField(XposedHelpers.findClass(intentClass, classLoader), playSongField)).putExtra("play_current_song", playSongInfo);
69 | nextSongIntent = new Intent((String) XposedHelpers.getStaticObjectField(XposedHelpers.findClass(intentClass, classLoader), nextSongField)).putExtra("play_current_song", playSongInfo);
70 | contentIntent = new Intent("com.tencent.karaoke.action.PLAYER");
71 | contentIntent.setData(Uri.parse("qmkege://"))
72 | .putExtra("action", "notification_player")
73 | .putExtra("from", "from_notification")
74 | .setClassName(basicParam.getContext(), XposedHelpers.findClass(IntentHandleActivity, classLoader).getCanonicalName())
75 | .addCategory("android.intent.category.DEFAULT");
76 | XposedBridge.log("加载方法完毕");
77 | param.setResult(viewBuild());
78 | }
79 | };
80 |
81 | XposedHelpers.findAndHookMethod(className, classLoader, methodName, objects);
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comtencentqqmusic.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import androidx.annotation.Keep;
4 |
5 | import cn.nexus6p.QQMusicNotify.Base.BasicInit;
6 | import de.robv.android.xposed.XC_MethodReplacement;
7 | import de.robv.android.xposed.XposedHelpers;
8 |
9 | @Keep
10 | public class comtencentqqmusic extends BasicInit {
11 |
12 | private ClassLoader mClassloader;
13 |
14 | @Override
15 | public void init() {
16 | XposedHelpers.findAndHookMethod("com.tencent.qqmusic.fragment.morefeatures.settings.providers.NotificationStyleSettingProvider", mClassloader, "shouldUseAndroidMediaNotificationStyle", new XC_MethodReplacement() {
17 | @Override
18 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
19 | return true;
20 | }
21 | });
22 | XposedHelpers.findAndHookMethod("com.tencent.qqmusic.fragment.morefeatures.settings.providers.NotificationStyleSettingProvider", mClassloader, "shouldUseQQMusicNotificationStyle", new XC_MethodReplacement() {
23 | @Override
24 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
25 | return false;
26 | }
27 | });
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Hook/comtencentqqmusiclocalplayer.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Hook;
2 |
3 | import android.app.Notification;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Bitmap;
7 | import android.media.session.MediaSession;
8 |
9 | import androidx.annotation.Keep;
10 |
11 | import cn.nexus6p.QQMusicNotify.Base.BasicNotification;
12 | import de.robv.android.xposed.XC_MethodReplacement;
13 | import de.robv.android.xposed.XposedHelpers;
14 |
15 | import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
16 |
17 | @Keep
18 | public class comtencentqqmusiclocalplayer extends BasicNotification {
19 |
20 | private static MediaSession.Token mTOKEN;
21 |
22 | @Override
23 | public void init() {
24 | final Class notifyClazz = XposedHelpers.findClass("com.tencent.qqmusiclocalplayer.business.k.s", classLoader);
25 | final Class infoClazz = XposedHelpers.findClass("com.tencent.qqmusiclocalplayer.c.e", classLoader);
26 | final Class clazz3 = XposedHelpers.findClass("com.tencent.a.d.t", classLoader);
27 | final Class clazzO = XposedHelpers.findClass("com.tencent.qqmusicsdk.a.o", classLoader);
28 | findAndHookMethod(notifyClazz, "b", Context.class, infoClazz, Bitmap.class, new XC_MethodReplacement() {
29 | @Override
30 | protected Notification replaceHookedMethod(MethodHookParam param) throws Throwable {
31 | basicParam.setIconID(0x7f020099);
32 | basicParam.setContext((Context) param.args[0]);
33 | basicParam.setBitmap((Bitmap) param.args[2]);
34 | basicParam.setStatue((!(Boolean) XposedHelpers.callStaticMethod(clazzO, "a") && ( (boolean) XposedHelpers.callStaticMethod(clazzO, "e") || (boolean) XposedHelpers.callStaticMethod(clazzO, "b"))));
35 | if (mTOKEN == null)
36 | mTOKEN = new MediaSession(basicParam.getContext(), "mbr").getSessionToken();
37 | basicParam.setToken(mTOKEN);
38 | basicParam.setTitleString((CharSequence) XposedHelpers.callMethod(param.args[1], "getName"));
39 | basicParam.setTextString((CharSequence) XposedHelpers.callMethod(param.args[1], "getSinger"));
40 | preSongIntent = new Intent("com.tencent.qqmusicsdk.ACTION_SERVICE_PREVIOUS_TASKBAR");
41 | playIntent = new Intent("com.tencent.qqmusicsdk.ACTION_SERVICE_TOGGLEPAUSE_TASKBAR");
42 | nextSongIntent = new Intent("com.tencent.qqmusicsdk.ACTION_SERVICE_NEXT_TASKBAR");
43 | contentIntent = new Intent("android.intent.action.MAIN");
44 | contentIntent.addCategory("android.intent.category.LAUNCHER").setClassName(basicParam.getContext(), (String) XposedHelpers.callStaticMethod(clazz3, "d", basicParam.getContext()));
45 | return build();
46 | }
47 | });
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/SharedPreferences/BasePreference.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.SharedPreferences
2 |
3 | import android.content.SharedPreferences
4 |
5 | abstract class BasePreference : SharedPreferences {
6 |
7 | override fun contains(p0: String?): Boolean {
8 | throw NoSuchMethodException()
9 | }
10 |
11 | override fun unregisterOnSharedPreferenceChangeListener(p0: SharedPreferences.OnSharedPreferenceChangeListener?) {
12 | throw NoSuchMethodException()
13 | }
14 |
15 | override fun getAll(): MutableMap? {
16 | throw NoSuchMethodException()
17 | }
18 |
19 | override fun edit(): SharedPreferences.Editor {
20 | throw NoSuchMethodException()
21 | }
22 |
23 | override fun getLong(p0: String?, p1: Long): Long {
24 | throw NoSuchMethodException()
25 | }
26 |
27 | override fun getFloat(p0: String?, p1: Float): Float {
28 | throw NoSuchMethodException()
29 | }
30 |
31 | override fun getStringSet(p0: String?, p1: MutableSet?): MutableSet {
32 | throw NoSuchMethodException()
33 | }
34 |
35 | override fun registerOnSharedPreferenceChangeListener(p0: SharedPreferences.OnSharedPreferenceChangeListener?) {
36 | throw NoSuchMethodException()
37 | }
38 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/SharedPreferences/ContentProviderPreference.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.SharedPreferences
2 |
3 | import android.content.ContentResolver
4 | import android.content.Context
5 | import android.content.Intent
6 | import android.net.Uri
7 | import android.os.Bundle
8 | import cn.nexus6p.QQMusicNotify.BackgroundActivity
9 | import cn.nexus6p.QQMusicNotify.BuildConfig
10 | import cn.nexus6p.QQMusicNotify.ContentProvider
11 | import org.json.JSONObject
12 |
13 | class ContentProviderPreference private constructor() : BasePreference() {
14 |
15 | constructor(@ContentProvider.ContentProviderParams position: String, key: String?, context: Context) : this() {
16 | var bundle: Bundle? = null
17 | if (position == ContentProvider.CONTENT_PROVIDER_COMMIT) {
18 | getBundle(position, key, context)
19 | return
20 | }
21 | if (position == ContentProvider.CONTENT_PROVIDER_JSON) {
22 | bundle = getBundle(position, key, context)
23 | } else if (position == ContentProvider.CONTENT_PROVIDER_PREFERENCE || position == ContentProvider.CONTENT_PROVIDER_DEVICE_PROTECTED_PREFERENCE) {
24 | bundle = getBundle(position, null, context)
25 | }
26 | if (bundle == null) {
27 | this.jsonObject = JSONObject()
28 | } else {
29 | //Log.d("XposedMusicNotify", "getBundle: $bundle")
30 | originalJsonString = bundle.getString(ContentProvider.BUNDLE_KEY_JSON_STRING)
31 | try {
32 | if (!originalJsonString!!.startsWith('['))
33 | this.jsonObject = JSONObject(originalJsonString!!)
34 | } catch (e: Exception) {
35 | e.printStackTrace()
36 | jsonObject = JSONObject()
37 | }
38 | }
39 | }
40 |
41 | lateinit var jsonObject: JSONObject
42 | var originalJsonString: String? = null
43 |
44 | override fun getBoolean(key: String?, defValue: Boolean): Boolean {
45 | return jsonObject.optBoolean(key, defValue)
46 | }
47 |
48 | override fun getInt(key: String?, defValue: Int): Int {
49 | return jsonObject.optString(key, defValue.toString()).toInt(16)
50 | }
51 |
52 | override fun getString(key: String?, defValue: String?): String? {
53 | return jsonObject.optString(key, defValue ?: "")
54 | }
55 |
56 | fun getJSONString(): String {
57 | return jsonObject.toString(4)
58 | }
59 |
60 | companion object {
61 |
62 | fun getBundle(@ContentProvider.ContentProviderParams position: String, key: String?, context: Context): Bundle? {
63 | return getBundle(position,key,context,null)
64 | }
65 |
66 | fun getBundle(@ContentProvider.ContentProviderParams position: String, key: String?, context: Context, extras: Bundle?): Bundle? {
67 | try {
68 | val contentResolver: ContentResolver = context.contentResolver
69 | val uri = Uri.parse("content://cn.nexus6p.QQMusicNotify.provider/")
70 | var result: Bundle? = null
71 | try {
72 | result = contentResolver.call(uri, position, key, extras)
73 | } catch (e: RuntimeException) {
74 | try {
75 | val intent = Intent()
76 | intent.setClassName(BuildConfig.APPLICATION_ID, BackgroundActivity::class.java.name)
77 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
78 | context.startActivity(intent)
79 | } catch (e1: Throwable) {
80 | return null
81 | }
82 | }
83 | if (result == null) {
84 | result = contentResolver.call(uri, position, key, extras)
85 | }
86 | if (result == null) {
87 | return null
88 | }
89 | return result
90 | } catch (ignored: Throwable) {
91 | return null
92 | }
93 | }
94 | }
95 |
96 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/SimpleAlcatrazInteractiveCardView.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.graphics.drawable.Drawable
6 | import android.util.AttributeSet
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.widget.LinearLayout
10 | import androidx.annotation.ColorInt
11 | import androidx.annotation.DrawableRes
12 | import androidx.core.content.ContextCompat
13 | import cn.nexus6p.QQMusicNotify.databinding.SimpleAlcatrazInteractiveCardviewBinding
14 |
15 | open class SimpleAlcatrazInteractiveCardView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.googleBlue) : LinearLayout(context, attrs, defStyleAttr) {
16 |
17 | protected val binding: SimpleAlcatrazInteractiveCardviewBinding = SimpleAlcatrazInteractiveCardviewBinding.inflate(LayoutInflater.from(context), this, true)
18 |
19 | var active: Boolean = false
20 | set(value) {
21 | val color = if (value) ContextCompat.getColor(context, R.color.green)
22 | else ContextCompat.getColor(context, R.color.colorError)
23 | this.color = color
24 | val drawable = if (value) R.drawable.ic_check_circle else R.drawable.ic_cancel
25 | this.iconDrawable = context.getDrawable(drawable)
26 | this.iconTint = Color.WHITE
27 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.visibility = View.VISIBLE
28 | field = value
29 | }
30 |
31 | @ColorInt
32 | var color: Int = ContextCompat.getColor(context, R.color.colorPrimary)
33 | set(value) {
34 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayLayer.setBackgroundColor(value)
35 | field = value
36 | }
37 |
38 | @DrawableRes
39 | var iconRes: Int = -1
40 | set(value) {
41 | if (value==-1) return
42 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.setImageResource(value)
43 | field = value
44 | }
45 |
46 | var iconDrawable: Drawable? = null
47 | set(value) {
48 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.setImageDrawable(value)
49 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.visibility = if (value!=null) View.VISIBLE else View.GONE
50 | field = value
51 | }
52 |
53 | @ColorInt
54 | var iconTint: Int = Color.WHITE
55 | set(value) {
56 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.setColorFilter(value)
57 | field = value
58 | }
59 |
60 | var firstLine: String?
61 | get() {
62 | return binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayInfo.text.toString()
63 | }
64 | set(value) {
65 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayInfo.text = value
66 | }
67 |
68 | var secondLine: String?
69 | get() {
70 | return binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlaySubinfo.text.toString()
71 | }
72 | set(value) {
73 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlaySubinfo.text = value
74 | }
75 |
76 | var titleLine: String?
77 | get() {
78 | return binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlaySubinfo.toString()
79 | }
80 | set(value) {
81 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayTitle.text = value
82 | }
83 |
84 | init {
85 | binding.alcatrazInteractiveCard.setShowOverlay(true)
86 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayIndicatorImage.visibility = View.VISIBLE
87 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayTitle.visibility = View.VISIBLE
88 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlayInfo.visibility = View.VISIBLE
89 | binding.alcatrazInteractiveCard.cardBinding.alcInteractiveCardOverlaySubinfo.visibility = View.VISIBLE
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Utils/LogUtils.kt:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Utils
2 |
3 | import android.content.Context
4 | import android.util.Log
5 | import cn.nexus6p.QQMusicNotify.ContentProvider
6 | import cn.nexus6p.QQMusicNotify.SharedPreferences.ContentProviderPreference
7 | import com.topjohnwu.superuser.Shell
8 | import java.io.File
9 | import java.text.SimpleDateFormat
10 | import java.util.*
11 |
12 | class LogUtils {
13 |
14 | companion object {
15 | fun cleanLog(max: Int, context: Context) {
16 | val logFile = File(context.filesDir.absolutePath + File.separator + "log.txt")
17 | if (!logFile.exists()) return
18 | val fileLineCount: Int = getLineCount(context)
19 | if (fileLineCount <= max) return
20 | val tmpFile = File(context.filesDir.absolutePath + File.separator + "log.tmp")
21 | if (tmpFile.exists()) tmpFile.writeText("")
22 | tmpFile.writeBytes(logFile.readBytes())
23 | val command = "head -" + max + " " + tmpFile.absolutePath + " > " + logFile.absolutePath
24 | Log.d("log clean", command)
25 | val result = Shell.sh(command).exec()
26 | if (!result.isSuccess) Log.w("clean log", result.err.toString())
27 | tmpFile.delete()
28 | }
29 |
30 | fun addLogByContentProvider(packageName: String, className: String, context: Context) {
31 | val string: String = SimpleDateFormat("[yyyy-MM-dd HH:mm:ss] ", Locale.getDefault()).format(Date()) + className + " hooked " + packageName + " \n"
32 | ContentProviderPreference(ContentProvider.CONTENT_PROVIDER_COMMIT, string, context)
33 | }
34 |
35 | fun addLog(string: String, context: Context) {
36 | val logFile = File(context.filesDir.absolutePath + File.separator + "log.txt")
37 | if (!logFile.exists()) logFile.createNewFile()
38 | val tmpFile = File(context.filesDir.absolutePath + File.separator + "log.tmp")
39 | if (tmpFile.exists()) tmpFile.writeText("")
40 | tmpFile.writeBytes(logFile.readBytes())
41 | logFile.writeText(string)
42 | logFile.appendText(tmpFile.readText())
43 | tmpFile.delete()
44 | }
45 |
46 | fun getLineCount(context: Context): Int {
47 | val logFile = File(context.filesDir.absolutePath + File.separator + "log.txt")
48 | if (!logFile.exists()) return 0
49 | if (logFile.length() < 1) return 0
50 | val lineResult = Shell.sh("wc -l " + logFile.absolutePath).exec()
51 | if (!lineResult.isSuccess) {
52 | Log.w("clean log", lineResult.err.toString())
53 | return 0
54 | }
55 | Log.d("log clean", lineResult.out.toString())
56 | return Integer.parseInt(lineResult.out[0].replace(logFile.absolutePath, "").replace(" ", ""))
57 | }
58 | }
59 |
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Utils/MediaSessionTokenHashMap.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Utils;
2 |
3 | import android.media.session.MediaSession;
4 |
5 | import java.util.HashMap;
6 |
7 | public class MediaSessionTokenHashMap {
8 |
9 | final public static HashMap mediaSessionTokenMap = new HashMap<>();
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/QQMusicNotify/Utils/PreferenceUtil.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.QQMusicNotify.Utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import org.json.JSONArray;
7 |
8 | import cn.nexus6p.QQMusicNotify.BuildConfig;
9 | import cn.nexus6p.QQMusicNotify.ContentProvider;
10 | import cn.nexus6p.QQMusicNotify.SharedPreferences.ContentProviderPreference;
11 |
12 | final public class PreferenceUtil {
13 |
14 | @SuppressWarnings("ConstantConditions")
15 | public static boolean isGooglePlay = BuildConfig.FLAVOR.equals("play");
16 |
17 | public static SharedPreferences getPreference(Context context) {
18 | return new ContentProviderPreference(ContentProvider.CONTENT_PROVIDER_PREFERENCE, null, context);
19 | }
20 |
21 | public static SharedPreferences getJSONPreference(String packageName, Context context) {
22 | return new ContentProviderPreference(ContentProvider.CONTENT_PROVIDER_JSON, packageName, context);
23 | }
24 |
25 | public static JSONArray getSupportPackages(Context context) {
26 | JSONArray jsonArray = null;
27 | try {
28 | jsonArray = new JSONArray(((ContentProviderPreference) PreferenceUtil.getJSONPreference("packages", context)).getOriginalJsonString());
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | }
32 | return jsonArray;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/cn/nexus6p/removewhitenotificationforbugme/main.java:
--------------------------------------------------------------------------------
1 | package cn.nexus6p.removewhitenotificationforbugme;
2 |
3 | import android.content.res.Resources;
4 |
5 | import java.util.ArrayList;
6 |
7 | import de.robv.android.xposed.IXposedHookInitPackageResources;
8 | import de.robv.android.xposed.IXposedHookLoadPackage;
9 | import de.robv.android.xposed.XC_MethodHook;
10 | import de.robv.android.xposed.XposedHelpers;
11 | import de.robv.android.xposed.callbacks.XC_InitPackageResources;
12 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
13 |
14 | public class main implements IXposedHookInitPackageResources, IXposedHookLoadPackage {
15 |
16 | private static ArrayList nameStrings = new ArrayList<>();
17 | static {
18 | nameStrings.add("notification_background_custom_padding_left");
19 | nameStrings.add("notification_background_custom_padding_top");
20 | nameStrings.add("notification_background_custom_padding_right");
21 | nameStrings.add("notification_background_custom_padding_bottom");
22 | nameStrings.add("notification_custom_view_margin_end");
23 | nameStrings.add("notification_custom_view_margin_start");
24 | nameStrings.add("notification_custom_view_corner_radius");
25 | nameStrings.add("notification_row_extra_padding");
26 | nameStrings.add("notification_custom_view_margin");
27 | }
28 |
29 | @Override
30 | public void handleInitPackageResources(XC_InitPackageResources.InitPackageResourcesParam resparam) throws Throwable {
31 | for (String nameString : nameStrings) {
32 | try {
33 | final int ID = resparam.res.getIdentifier(nameString, "dimen", "com.android.systemui");
34 | resparam.res.setReplacement(ID, 0);
35 | } catch (Exception e) {
36 | e.printStackTrace();
37 | }
38 | }
39 | }
40 |
41 | @Override
42 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
43 | if (!lpparam.packageName.equals("com.android.systemui")) return;
44 | final ClassLoader classLoader = lpparam.classLoader;
45 |
46 | XposedHelpers.findAndHookMethod(Resources.class, "getDimensionPixelSize", int.class, new XC_MethodHook() {
47 | @Override
48 | protected void afterHookedMethod(MethodHookParam param) throws Throwable {
49 | final ArrayList IDs = new ArrayList<>();
50 | for (String nameString : nameStrings) {
51 | try {
52 | IDs.add(((Resources)param.thisObject).getIdentifier(nameString, "dimen", "com.android.systemui"));
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | }
56 | }
57 | int resID = (int) param.args[0];
58 | for (Integer ID : IDs) {
59 | if (resID == ID) {
60 | param.setResult(0);
61 | return;
62 | }
63 | }
64 | }
65 | });
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/me/qiwu/MusicNotification/ColorUtil.java:
--------------------------------------------------------------------------------
1 | package me.qiwu.MusicNotification;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Color;
5 |
6 | import androidx.annotation.ColorInt;
7 | import androidx.palette.graphics.Palette;
8 |
9 | /**
10 | * Created by Deng on 2019/2/20.
11 | */
12 |
13 | public class ColorUtil {
14 | public static int[] getColor(Bitmap bitmap) {
15 | int backgroundColor = Color.BLACK;
16 | int textColor = Color.WHITE;
17 | if (bitmap != null) {
18 | Palette palette = Palette.from(bitmap).generate();
19 | Palette.Swatch swatch = palette.getDominantSwatch();
20 | if (swatch != null) {
21 | backgroundColor = swatch.getRgb();
22 | textColor = getTextColor(palette, backgroundColor);
23 | }
24 | }
25 | return new int[]{backgroundColor, textColor};
26 | }
27 |
28 | private static int getTextColor(Palette palette, int color) {
29 | boolean isLightColor = isColorLight(color);
30 | int textColor = isLightColor ? palette.getDarkMutedColor(Color.BLACK) : palette.getLightMutedColor(palette.getLightVibrantColor(Color.WHITE));
31 | if (getDifference(color, textColor) < 100) {
32 | textColor = getReadableColor(color, textColor);
33 | }
34 | return textColor;
35 | }
36 |
37 | private static int getReadableColor(int backgroundColor, int textColor) {
38 | boolean isLight = isColorLight(backgroundColor);
39 | for (int i = 0; getDifference(textColor, backgroundColor) < 100 && i < 100; i++) {
40 | textColor = getMixedColor(textColor, isLight ? Color.BLACK : Color.WHITE);
41 | }
42 | if (getDifference(textColor, backgroundColor) < 100) {
43 | return isLight ? Color.BLACK : Color.WHITE;
44 | }
45 | return textColor;
46 | }
47 |
48 | //获取两种颜色的差异
49 | private static double getDifference(@ColorInt int color1, @ColorInt int color2) {
50 | double diff = Math.abs(0.299 * (Color.red(color1) - Color.red(color2)));
51 | diff += Math.abs(0.587 * (Color.green(color1) - Color.green(color2)));
52 | diff += Math.abs(0.114 * (Color.blue(color1) - Color.blue(color2)));
53 | return diff;
54 | }
55 |
56 | //获取两种颜色的混合颜色
57 | private static int getMixedColor(@ColorInt int color1, @ColorInt int color2) {
58 | return Color.rgb(
59 | (Color.red(color1) + Color.red(color2)) / 2,
60 | (Color.green(color1) + Color.green(color2)) / 2,
61 | (Color.blue(color1) + Color.blue(color2)) / 2
62 | );
63 | }
64 |
65 | private static boolean isColorLight(@ColorInt int color) {
66 | return getColorDarkness(color) < 0.5;
67 | }
68 |
69 | private static double getColorDarkness(@ColorInt int color) {
70 | if (color == Color.BLACK)
71 | return 1.0;
72 | else if (color == Color.WHITE || color == Color.TRANSPARENT)
73 | return 0.0;
74 | else
75 | return (1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255);
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/name/mikanoshi/customiuizer/mods/System.java:
--------------------------------------------------------------------------------
1 | package name.mikanoshi.customiuizer.mods;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | import de.robv.android.xposed.XC_MethodHook;
7 | import de.robv.android.xposed.XposedHelpers;
8 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
9 |
10 | public class System {
11 | public static void ExpandNotificationsHook(XC_LoadPackage.LoadPackageParam paramLoadPackageParam) {
12 | XposedHelpers.findAndHookMethod("com.android.systemui.statusbar.phone.StatusBar", paramLoadPackageParam.classLoader, "updateRowStates", new XC_MethodHook() {
13 | protected void afterHookedMethod(MethodHookParam param1MethodHookParam) {
14 | ViewGroup viewGroup = (ViewGroup) XposedHelpers.getObjectField(param1MethodHookParam.thisObject, "mStackScroller");
15 | for (int i = viewGroup.getChildCount() - 1; i >= 0; i--) {
16 | View view = viewGroup.getChildAt(i);
17 | if (view != null && view.getClass().getSimpleName().equalsIgnoreCase("ExpandableNotificationRow"))
18 | try {
19 | XposedHelpers.getObjectField(XposedHelpers.callMethod(view, "getEntry"), "notification");
20 | XposedHelpers.callMethod(view, "setSystemExpanded", true);
21 | } finally {
22 | view = null;
23 | }
24 | }
25 | }
26 | });
27 | }
28 | }
29 |
30 |
31 | /* Location: C:\Users\Neuron\Documents\Tencent Files\[数据删除]\FileRecv\MobileFile\classes.jar!\name\mikanoshi\customiuizer\mods\System.class
32 | * Java compiler version: 6 (50.0)
33 | * JD-Core Version: 1.1.2
34 | */
--------------------------------------------------------------------------------
/app/src/main/java/soptqs/medianotification/utils/ColorUtils.java:
--------------------------------------------------------------------------------
1 | package soptqs.medianotification.utils;
2 |
3 | import android.graphics.Color;
4 |
5 | import androidx.annotation.ColorInt;
6 |
7 | public class ColorUtils {
8 |
9 | public static boolean isColorLight(@ColorInt int color) {
10 | return getColorDarkness(color) < 0.5;
11 | }
12 |
13 | private static double getColorDarkness(@ColorInt int color) {
14 | if (color == Color.BLACK)
15 | return 1.0;
16 | else if (color == Color.WHITE || color == Color.TRANSPARENT)
17 | return 0.0;
18 | else
19 | return (1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255);
20 | }
21 |
22 | @ColorInt
23 | public static int getInverseColor(@ColorInt int color) {
24 | return (0xFFFFFF - color) | 0xFF000000;
25 | }
26 |
27 | public static boolean isColorSaturated(@ColorInt int color) {
28 | double max = Math.max(0.299 * Color.red(color), Math.max(0.587 * Color.green(color), 0.114 * Color.blue(color)));
29 | double min = Math.min(0.299 * Color.red(color), Math.min(0.587 * Color.green(color), 0.114 * Color.blue(color)));
30 | double diff = Math.abs(max - min);
31 | return diff > 20;
32 | }
33 |
34 | @ColorInt
35 | public static int getMixedColor(@ColorInt int color1, @ColorInt int color2) {
36 | return Color.rgb(
37 | (Color.red(color1) + Color.red(color2)) / 2,
38 | (Color.green(color1) + Color.green(color2)) / 2,
39 | (Color.blue(color1) + Color.blue(color2)) / 2
40 | );
41 | }
42 |
43 | public static double getDifference(@ColorInt int color1, @ColorInt int color2) {
44 | double diff = Math.abs(0.299 * (Color.red(color1) - Color.red(color2)));
45 | diff += Math.abs(0.587 * (Color.green(color1) - Color.green(color2)));
46 | diff += Math.abs(0.114 * (Color.blue(color1) - Color.blue(color2)));
47 | return diff;
48 | }
49 |
50 | @ColorInt
51 | public static int getReadableText(@ColorInt int textColor, @ColorInt int backgroundColor) {
52 | return getReadableText(textColor, backgroundColor, 100);
53 | }
54 |
55 | @ColorInt
56 | public static int getReadableText(@ColorInt int textColor, @ColorInt int backgroundColor, int difference) {
57 | boolean isLight = isColorLight(backgroundColor);
58 | for (int i = 0; getDifference(textColor, backgroundColor) < difference && i < 100; i++) {
59 | textColor = getMixedColor(textColor, isLight ? Color.BLACK : Color.WHITE);
60 | }
61 |
62 | return textColor;
63 | }
64 |
65 | }
--------------------------------------------------------------------------------
/app/src/main/java/soptqs/medianotification/utils/PaletteUtils.java:
--------------------------------------------------------------------------------
1 | package soptqs.medianotification.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Color;
7 |
8 | import androidx.annotation.ColorInt;
9 | import androidx.palette.graphics.Palette;
10 |
11 | import java.util.Collections;
12 | import java.util.List;
13 |
14 | import cn.nexus6p.QQMusicNotify.Utils.PreferenceUtil;
15 |
16 | public class PaletteUtils {
17 |
18 | public static Palette getPalette(Bitmap bitmap) {
19 | if (bitmap != null) return Palette.from(bitmap).generate();
20 | else return null;
21 | }
22 |
23 | public static Palette.Swatch getSwatch(Palette palette, Context context) {
24 | SharedPreferences prefs = PreferenceUtil.getPreference(context);
25 |
26 | if (palette == null)
27 | return new Palette.Swatch(Color.parseColor(prefs.getString(PreferenceUtils.PREF_CUSTOM_COLOR, "#FFFFFF")), 1);
28 |
29 | Palette.Swatch swatch = null;
30 | switch (Integer.parseInt(prefs.getString(PreferenceUtils.PREF_COLOR_METHOD, "0"))) {
31 | case PreferenceUtils.COLOR_METHOD_DOMINANT:
32 | swatch = palette.getDominantSwatch();
33 | break;
34 | case PreferenceUtils.COLOR_METHOD_PRIMARY:
35 | swatch = getBestPaletteSwatchFrom(palette);
36 | break;
37 | case PreferenceUtils.COLOR_METHOD_VIBRANT:
38 | swatch = palette.getVibrantSwatch();
39 | break;
40 | case PreferenceUtils.COLOR_METHOD_MUTED:
41 | swatch = palette.getMutedSwatch();
42 | break;
43 | case PreferenceUtils.COLOR_METHOD_PHONOGRAPH:
44 | swatch = getHighestPopulationSwatch(palette.getSwatches());
45 | break;
46 | }
47 |
48 | if (swatch == null)
49 | swatch = new Palette.Swatch(Color.parseColor(prefs.getString(PreferenceUtils.PREF_CUSTOM_COLOR, "#FFFFFF")), 1);
50 |
51 | return swatch;
52 | }
53 |
54 |
55 | @ColorInt
56 | public static int getTextColor(Palette palette, Palette.Swatch swatch, Context context) {
57 | SharedPreferences prefs = PreferenceUtil.getPreference(context);
58 | if (prefs.getBoolean(PreferenceUtils.PREF_HIGH_CONTRAST_TEXT, false)) {
59 | if (ColorUtils.isColorLight(swatch.getRgb()))
60 | return Color.BLACK;
61 | else return Color.WHITE;
62 | } else {
63 | int background = swatch.getRgb();
64 | if (prefs.getBoolean(PreferenceUtils.PREF_INVERSE_TEXT_COLORS, true)) {
65 | int inverse = -1;
66 | if (palette != null) {
67 | switch (Integer.parseInt(prefs.getString(PreferenceUtils.PREF_COLOR_METHOD, "0"))) {
68 | case PreferenceUtils.COLOR_METHOD_DOMINANT:
69 | inverse = ColorUtils.isColorSaturated(background) ? palette.getMutedColor(-1) : palette.getVibrantColor(-1);
70 | break;
71 | case PreferenceUtils.COLOR_METHOD_VIBRANT:
72 | inverse = palette.getMutedColor(-1);
73 | break;
74 | case PreferenceUtils.COLOR_METHOD_MUTED:
75 | inverse = palette.getVibrantColor(-1);
76 | break;
77 | }
78 |
79 | if (inverse != -1)
80 | return ColorUtils.getReadableText(inverse, background, 150);
81 | }
82 |
83 | /*inverse = ColorUtils.getInverseColor(background);
84 | if (ColorUtils.getDifference(background, inverse) > 120 && ColorUtils.isColorSaturated(background))
85 | return ColorUtils.getReadableText(inverse, background, 150);*/
86 | }
87 | return ColorUtils.getReadableText(background, background);
88 | }
89 | }
90 |
91 | private static Palette.Swatch getBestPaletteSwatchFrom(Palette palette) {
92 | if (palette != null) {
93 | if (palette.getVibrantSwatch() != null)
94 | return palette.getVibrantSwatch();
95 | else if (palette.getMutedSwatch() != null)
96 | return palette.getMutedSwatch();
97 | else if (palette.getDarkVibrantSwatch() != null)
98 | return palette.getDarkVibrantSwatch();
99 | else if (palette.getDarkMutedSwatch() != null)
100 | return palette.getDarkMutedSwatch();
101 | else if (palette.getLightVibrantSwatch() != null)
102 | return palette.getLightVibrantSwatch();
103 | else if (palette.getLightMutedSwatch() != null)
104 | return palette.getLightMutedSwatch();
105 | else if (!palette.getSwatches().isEmpty())
106 | return getBestPaletteSwatchFrom(palette.getSwatches());
107 | }
108 | return null;
109 | }
110 |
111 | private static Palette.Swatch getBestPaletteSwatchFrom(List swatches) {
112 | if (swatches == null) return null;
113 | return Collections.max(swatches, (opt1, opt2) -> {
114 | int a = opt1 == null ? 0 : opt1.getPopulation();
115 | int b = opt2 == null ? 0 : opt2.getPopulation();
116 | return a - b;
117 | });
118 | }
119 |
120 | public static Palette.Swatch getHighestPopulationSwatch(List swatches) {
121 | Palette.Swatch highestSwatch = null;
122 | for (Palette.Swatch swatch : swatches) {
123 | if (swatch != null) {
124 | if (highestSwatch == null || swatch.getPopulation() > highestSwatch.getPopulation())
125 | highestSwatch = swatch;
126 | }
127 | }
128 | return highestSwatch;
129 | }
130 | }
--------------------------------------------------------------------------------
/app/src/main/java/soptqs/medianotification/utils/PreferenceUtils.java:
--------------------------------------------------------------------------------
1 | package soptqs.medianotification.utils;
2 |
3 | public class PreferenceUtils {
4 |
5 | public static final String PREF_COLOR_METHOD = "colorMethod";
6 | public static final String PREF_CUSTOM_COLOR = "customColor";
7 | public static final String PREF_HIGH_CONTRAST_TEXT = "highContrastText";
8 | public static final String PREF_ALWAYS_DISMISSIBLE = "always_show";
9 | public static final String PREF_INVERSE_TEXT_COLORS = "inverseTextColors";
10 | public static final int COLOR_METHOD_DOMINANT = 0;
11 | public static final int COLOR_METHOD_PRIMARY = 1;
12 | public static final int COLOR_METHOD_VIBRANT = 2;
13 | public static final int COLOR_METHOD_MUTED = 3;
14 | public static final int COLOR_METHOD_PHONOGRAPH = 4;
15 | public static final int COLOR_METHOD_DEFAULT = 5;
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/slide_right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_music.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_pause.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_skip_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_skip_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_skip_previous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_skip_previous.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_stop.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_thumb_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_thumb_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_thumb_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-hdpi/ic_thumb_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_music.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_pause.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_skip_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_skip_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_skip_previous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_skip_previous.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_stop.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_thumb_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_thumb_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_thumb_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-mdpi/ic_thumb_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-night/ic_github.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
16 |
19 |
22 |
25 |
28 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-night/ic_mail_outline.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_add.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_check.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_music.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_pause.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_play.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_skip_next.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_skip_previous.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_stop.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_thumb_down.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_thumb_up.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_music.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_pause.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_skip_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_skip_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_skip_previous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_skip_previous.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_stop.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_thumb_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_thumb_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_thumb_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xhdpi/ic_thumb_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_add.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_check.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_check.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_music.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_pause.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_play.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_skip_next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_skip_next.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_skip_previous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_skip_previous.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_stop.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_thumb_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_thumb_down.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_thumb_up.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable-xxhdpi/ic_thumb_up.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_image.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/color_drawable.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edxp.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/edxp.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable/edxp_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/edxp_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_cancel.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_github.xml:
--------------------------------------------------------------------------------
1 |
6 |
10 |
13 |
16 |
19 |
22 |
25 |
28 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_mail_outline.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_music.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/ic_music.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_refresh_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_telegram_logo.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
27 |
30 |
31 |
32 |
38 |
41 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/icon.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable/miui.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/miui.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable/singleneuron.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/singleneuron.webp
--------------------------------------------------------------------------------
/app/src/main/res/drawable/taichi.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/app/src/main/res/drawable/taichi.webp
--------------------------------------------------------------------------------
/app/src/main/res/layout-v24/layout_notification_collapsed.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
43 |
44 |
49 |
50 |
59 |
60 |
61 |
62 |
73 |
74 |
79 |
80 |
89 |
90 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v24/layout_notification_collapsed_stlye2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
38 |
39 |
44 |
45 |
54 |
55 |
56 |
57 |
68 |
69 |
74 |
75 |
84 |
85 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v24/layout_notification_expanded.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
56 |
57 |
66 |
67 |
68 |
69 |
78 |
79 |
87 |
88 |
92 |
93 |
99 |
100 |
106 |
107 |
113 |
114 |
120 |
121 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/app/src/main/res/layout-v24/layout_notification_expanded_stlye2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
37 |
38 |
44 |
45 |
50 |
51 |
60 |
61 |
62 |
63 |
72 |
73 |
81 |
82 |
86 |
87 |
93 |
94 |
100 |
101 |
107 |
108 |
114 |
115 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_notification_collapsed.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
23 |
24 |
30 |
31 |
32 |
33 |
44 |
45 |
50 |
51 |
60 |
61 |
62 |
63 |
73 |
74 |
83 |
84 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_notification_collapsed_stlye2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
38 |
39 |
44 |
45 |
54 |
55 |
56 |
57 |
67 |
68 |
77 |
78 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_notification_expanded.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
42 |
43 |
49 |
50 |
55 |
56 |
65 |
66 |
67 |
68 |
77 |
78 |
86 |
87 |
91 |
92 |
98 |
99 |
105 |
106 |
112 |
113 |
119 |
120 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_notification_expanded_stlye2.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
37 |
38 |
44 |
45 |
50 |
51 |
60 |
61 |
62 |
63 |
72 |
73 |
81 |
82 |
86 |
87 |
93 |
94 |
100 |
101 |
107 |
108 |
114 |
115 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/log_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
18 |
19 |
25 |
26 |
27 |
28 |
29 |
30 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/main_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
23 |
24 |
25 |
26 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/notifition_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
21 |
22 |
23 |
29 |
30 |
31 |
32 |
42 |
43 |
49 |
50 |
55 |
56 |
65 |
66 |
67 |
68 |
77 |
78 |
87 |
88 |
92 |
93 |
100 |
101 |
107 |
108 |
114 |
115 |
121 |
122 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/setting_fragment.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
15 |
16 |
29 |
30 |
38 |
39 |
47 |
48 |
55 |
56 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/simple_alcatraz_interactive_cardview.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/third_party_source.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #1A73E8
4 | #69a1ff
5 | #101010
6 | #212121
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #1A73E8
4 | #0049b5
5 | #FF5252
6 | #efefef
7 | #F5F5F5
8 | #4CAF50
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/integers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 300
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 原生音乐通知
4 | Trying to make music players using standard notification
5 |
6 | - 优势
7 | - 最优
8 | - 活力
9 | - 柔和
10 | - 主要
11 | - 默认
12 |
13 |
14 | - Dominant
15 | - Primary
16 | - Vibrant
17 | - Muted
18 | - Main
19 | - Always Default
20 |
21 |
22 | - 0
23 | - 1
24 | - 2
25 | - 3
26 | - 4
27 | - 5
28 |
29 |
30 | - Cloudflare CDN(推荐)
31 | - Github(不推荐,无法保证速度且中国大陆极有可能无法访问)
32 | - Coding(中国大陆访问备选)
33 | - 自定义(仅限调试)
34 |
35 |
36 | - 0
37 | - 1
38 | - 2
39 | - 3
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/apps.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
12 |
13 |
14 |
18 |
22 |
25 |
28 |
32 |
35 |
38 |
42 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/experimental.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/json_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/media_notification.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
17 |
20 |
26 |
27 |
28 |
31 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/music_notification.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
12 |
16 |
21 |
22 |
23 |
26 |
30 |
34 |
37 |
38 |
39 |
40 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/third_party_source.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
14 |
17 |
18 |
21 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | ext.kotlin_version = '1.4.10'
4 | repositories {
5 | maven{
6 | url "https://maven.google.com"
7 | }
8 | google()
9 | jcenter()
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:4.1.0'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | maven{
20 | url "https://maven.google.com"
21 | }
22 | google()
23 | jcenter()
24 | }
25 | gradle.projectsEvaluated {
26 | tasks.withType(JavaCompile) {
27 | options.compilerArgs << "-Xlint:deprecation"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/debugTool/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/debugTool/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 | defaultConfig {
8 | applicationId "me.singleneuron.originalmusicnotification_debugtool"
9 | minSdkVersion 24
10 | targetSdkVersion 29
11 | versionCode 2
12 | versionName "1.1"
13 | }
14 |
15 | compileOptions {
16 | sourceCompatibility JavaVersion.VERSION_1_8
17 | targetCompatibility JavaVersion.VERSION_1_8
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 |
27 | }
28 |
29 | repositories {
30 | maven { url 'https://jitpack.io' }
31 | }
32 |
33 | dependencies {
34 | implementation 'com.github.topjohnwu.libsu:core:2.5.0'
35 | }
36 |
--------------------------------------------------------------------------------
/debugTool/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/debugTool/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/debugTool/src/main/java/me/singleneuron/originalmusicnotification_debugtool/MainActivity.java:
--------------------------------------------------------------------------------
1 | package me.singleneuron.originalmusicnotification_debugtool;
2 |
3 |
4 | import android.app.Activity;
5 | import android.content.ContentResolver;
6 | import android.content.Intent;
7 | import android.net.Uri;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.widget.TextView;
11 |
12 | import com.topjohnwu.superuser.Shell;
13 |
14 | import org.json.JSONArray;
15 | import org.json.JSONException;
16 |
17 | import java.io.PrintWriter;
18 | import java.io.StringWriter;
19 |
20 | public class MainActivity extends Activity {
21 |
22 | public TextView textView;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_main);
28 | textView = findViewById(R.id.textView);
29 | TextView textView = findViewById(R.id.textView2);
30 | findViewById(R.id.Button1).setOnClickListener(v -> {
31 | try {
32 | String string = getSupportPackages();
33 | JSONArray jsonArray = new JSONArray(string);
34 | textView.setText(jsonArray.toString(4));
35 | } catch (JSONException e) {
36 | e.printStackTrace();
37 | StringWriter stringWriter = new StringWriter();
38 | PrintWriter printWriter = new PrintWriter(stringWriter);
39 | e.printStackTrace(printWriter);
40 | textView.setText(stringWriter.toString());
41 | }
42 | });
43 | findViewById(R.id.Button2).setOnClickListener(v -> {
44 | callBackgroundActivity();
45 | });
46 | try {
47 | Shell.Result result = Shell.sh("su --version").exec();
48 | writeToTextview("su --version: " + (result.isSuccess() ? result.getOut().toString() : result.getErr().toString()));
49 | writeToTextview("taichi_magisk: " + System.getProperty("taichi_magisk"));
50 | Shell.Result result2 = Shell.su("getenforce").exec();
51 | writeToTextview("SeLinux (real statue go by root):" + (result2.isSuccess() ? result2.getOut().toString() : result2.getErr().toString()));
52 | writeToTextview("---------------");
53 | toHookOnInit();
54 | toHook();
55 | } catch (Exception e) {
56 | e.printStackTrace();
57 | StringWriter stringWriter = new StringWriter();
58 | PrintWriter printWriter = new PrintWriter(stringWriter);
59 | e.printStackTrace(printWriter);
60 | writeToTextview(stringWriter.toString());
61 | }
62 | }
63 |
64 | public void toHook() {
65 | writeToTextview("原生音乐通知未找到");
66 | Log.d("XposedMusicNotify_DebugTool", "原生音乐通知未找到");
67 | }
68 |
69 | public void toHookOnInit() {
70 | writeToTextview("初始化时原生音乐通知未找到");
71 | Log.d("XposedMusicNotify_DebugTool", "原生音乐通知未附加到Application");
72 | }
73 |
74 | public void writeToTextview(String string) {
75 | textView.setText(textView.getText() + string + "\n\n");
76 | }
77 |
78 | private String getSupportPackages() {
79 | Bundle bundle = getBundle("content_provider_json", "packages");
80 | return bundle.getString("bundle_key_json_string");
81 | }
82 |
83 | private Bundle getBundle(String position, String key) {
84 | try {
85 | ContentResolver contentResolver = this.getContentResolver();
86 | Uri uri = Uri.parse("content://cn.nexus6p.QQMusicNotify.provider/");
87 | Bundle result = null;
88 | try {
89 | result = contentResolver.call(uri, position, key, null);
90 | } catch (RuntimeException e) {
91 | callBackgroundActivity();
92 | }
93 | if (result == null) {
94 | result = contentResolver.call(uri, position, key, null);
95 | }
96 | if (result == null) {
97 | return null;
98 | }
99 | return result;
100 | } catch (Throwable ignored) {
101 | return null;
102 | }
103 | }
104 |
105 | private void callBackgroundActivity() {
106 | try {
107 | Intent intent = new Intent();
108 | intent.setClassName("cn.nexus6p.QQMusicNotify", "cn.nexus6p.QQMusicNotify.BackgroundActivity");
109 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
110 | this.startActivity(intent);
111 | } catch (Throwable e1) {
112 | e1.printStackTrace();
113 | }
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/debugTool/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
20 |
21 |
25 |
26 |
31 |
32 |
38 |
39 |
45 |
46 |
47 |
48 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/google-play-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/google-play-badge.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | android.useAndroidX=true
2 | android.enableJetifier=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Oct 19 08:28:22 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
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 |
--------------------------------------------------------------------------------
/icon_原生音乐通知_new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/icon_原生音乐通知_new.png
--------------------------------------------------------------------------------
/icon_原生音乐通知_new_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/icon_原生音乐通知_new_512.png
--------------------------------------------------------------------------------
/nexus6pcn.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/nexus6pcn.jks
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':debugTool'
2 |
--------------------------------------------------------------------------------
/singleneuron.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/singleneuron.png
--------------------------------------------------------------------------------
/singleneuron_me.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/singleneuron_me.jks
--------------------------------------------------------------------------------
/未标题-1.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/未标题-1.psd
--------------------------------------------------------------------------------
/演示文稿1.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Cryolitia/XposedMusicNotify/9033ea094074ce797d6c34b9a816ae7f9c79be5e/演示文稿1.ppt
--------------------------------------------------------------------------------