82 Commits

Author SHA1 Message Date
570e5a23ba chore: update target sdk to 36 2025-08-19 17:02:41 +08:00
90aec5b9fa chore: update jdk to 21 2025-08-19 17:02:33 +08:00
7f3cdba757 chore: bump gradle to 8.14.3 2025-08-19 17:02:22 +08:00
9536b42c2b chore: bump dependencies 2025-08-19 17:02:00 +08:00
a7582de004 refactor: update KavaRef usage to 1.0.1 2025-07-06 21:37:37 +08:00
29b14a811e refactor: migrate and update to YukiHookAPI 1.3.0 2025-06-25 23:22:49 +08:00
9b9eda8a39 docs: update README 2025-06-24 14:11:25 +08:00
cfa065b57e docs: update README 2025-06-20 12:52:18 +08:00
YuSaki丶Kanade
492d0dad67 fix: block coloros 15 fixSmallIcon method (#78)
* fix: block coloros 15 fixSmallIcon method

* fix: hook error

* feat: complete ColorOS 15 support

* docs: update README

---------

Co-authored-by: fankesyooni <qzmmcn@163.com>
2025-05-29 22:12:27 +08:00
YuSaki丶Kanade
d26f68c1a7 fix: DND and updateIconsForLayout hook (#79) 2025-05-28 22:50:39 +08:00
d9520cb484 chore: disable type auto conversion for sweet-property 2025-05-09 23:20:08 +08:00
884aa87617 chore: update project files 2025-05-09 23:20:06 +08:00
YuSaki丶Kanade
51e52f3eba fix: block coloros 15 useAppIconForSmallIcon method (#77) 2025-04-22 02:15:08 +08:00
YuSaki丶Kanade
9aae48c785 fix: coloros 15 removed updateIconsForLayout method (#76) 2025-04-21 22:40:21 +08:00
ee77842fbb chore: bump dependencies 2025-03-16 23:29:32 +08:00
3794035789 chore: bump gradle to 8.13 2025-03-16 23:29:26 +08:00
a8c1ba3166 chore: bump ci to v4 2025-02-22 01:10:00 +08:00
4d39eb4b9d chore: update .gitignore 2025-02-22 01:09:50 +08:00
2ffd36cc21 docs: update license 2025-01-13 11:17:22 +08:00
d95e53f6e4 refactor: support Android 15 edge-to-edge system bars 2024-11-25 18:50:23 +08:00
115ccf0822 chore: update target sdk to 35 2024-11-10 21:36:17 +08:00
982f73444a chore: some tweaks in build.gradle.kts 2024-11-10 21:35:12 +08:00
93fdd307a2 chore: update project files 2024-11-10 21:35:09 +08:00
75789c0286 chore: bump dependencies 2024-11-10 21:35:02 +08:00
b1ca7be6ed chore: bump gradle to 8.10.2 2024-11-10 21:06:44 +08:00
c4087db1e6 docs: add Android 15 option 2024-10-10 09:09:42 +08:00
hamjin
bf69aed1b4 feat: Replace ghproxy.com with ghp.ci (#69) 2024-10-03 15:48:55 +08:00
a0c001b7e4 Revert "feat: Custom GitHub Proxy (#68)"
This reverts commit 1b0fcdfce6.
2024-10-03 01:27:38 +08:00
hamjin
1b0fcdfce6 feat: Custom GitHub Proxy (#68)
* feat: Custom GitHub Proxy

Signed-off-by: hamjin <jinham@qq.com>

* refactor: organize text layout

---------

Signed-off-by: hamjin <jinham@qq.com>
Co-authored-by: Fankesyooni <37344460+fankes@users.noreply.github.com>
2024-10-03 00:29:03 +08:00
8d42d47ab4 chore: update .editorconfig 2024-06-21 10:11:02 +08:00
a7c43149e3 chore: update project files 2024-06-21 10:10:54 +08:00
053c8b837c refactor: support Kotlin 2.0.0 2024-06-20 11:26:22 +08:00
1fdaf81560 chore: bump dependencies 2024-06-20 11:25:22 +08:00
67937edd0f chore: bump gradle to 8.7 2024-06-20 11:25:13 +08:00
bb9e965cca chore: update .editorconfig 2024-06-20 11:25:08 +08:00
d7e487c4ce chore: bump dependencies 2024-02-20 11:39:43 +08:00
11480f6d4a chore: bump gradle to 8.6 2024-02-20 11:39:39 +08:00
a09d039b48 chore: update .editorconfig 2024-01-13 21:25:46 +08:00
95b49168cb docs: update copyright date to 2024 for all existing files 2024-01-01 01:23:24 +08:00
49b942efda style: merge to new ktlint version & rules 2023-12-29 21:39:05 +08:00
025183d8f0 chore: update project files 2023-12-29 21:39:00 +08:00
78205b2c6c chore: bump dependencies 2023-12-28 23:55:23 +08:00
c3ac4d4be1 chore: bump gradle to 8.5 2023-12-28 23:53:40 +08:00
a22d36c79d chore: update .gitignore 2023-12-28 23:53:29 +08:00
8889d6fa5f docs: use relative link 2023-12-11 02:39:42 +08:00
8662637e6a chore: update project files 2023-12-11 02:39:39 +08:00
b88b7b6907 chore: bump dependency versions 2023-12-11 00:27:21 +08:00
ae0f163d57 docs: update piracy statement 2023-12-11 00:27:18 +08:00
757313ee14 style: optimize code 2023-12-11 00:26:17 +08:00
Fankesyooni
0ee83ff83a Merge pull request #65 from hamjin/master
Fix: ColorOS 14 new hook points
2023-12-03 12:35:12 +08:00
hamjin
29c3a839f4 Bugfix for ColorOS 14
Tested On OnePlus PHK110 14.0.0.200 with com.android.systemui 14.99.09

Signed-off-by: hamjin <jinham@qq.com>
2023-12-03 11:49:12 +08:00
faf443960c docs: update promotion 2023-11-18 18:16:50 +08:00
41cf6a209a chore: bump "com.highcapable.sweetdependency" version to 1.0.4 2023-11-14 01:02:38 +08:00
71a37d8bf3 chore: bump "com.highcapable.sweetproperty" version to 1.0.5 2023-11-08 15:20:21 +08:00
4afddae4e1 chore: updaye project files 2023-11-08 15:17:45 +08:00
3714c3f06d chore: bump dependencies 2023-11-04 03:52:02 +08:00
6d624b3992 chore: bump plugin versions
- bump "com.highcapable.sweetdependency" version to 1.0.3
- bump "com.highcapable.sweetproperty" version to 1.0.4
2023-11-04 03:48:54 +08:00
b3a3e0993c docs: replace download links 2023-11-03 13:56:46 +08:00
c34f121145 docs: update release channel 2023-10-26 21:30:06 +08:00
b2a65a4f3c fix: catch toast when no looper 2023-10-22 22:38:16 +08:00
799d758671 chore: update target sdk to 34 2023-10-21 01:22:33 +08:00
9f323f466a feat(docs): update YukiHookAPI owner link 2023-10-21 01:22:13 +08:00
713d5bc008 refactor: remove DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION 2023-10-21 01:21:31 +08:00
e0f50984b0 refactor: migrate to YukiHookAPI new usage 2023-10-07 21:07:40 +08:00
1e0efe8f86 chore: bump dependency versions 2023-10-07 21:07:32 +08:00
358fc16b0e chore: bump plugin versions
- bump "com.highcapable.sweetdependency" version to 1.0.2
- bump "com.highcapable.sweetproperty" version to 1.0.3
2023-09-26 09:08:58 +08:00
fc69d7b544 refactor: add new R8 rules to fix possible problems 2023-09-19 08:18:46 +08:00
5e37c1b7dc ci: fix artifacts name 2023-09-19 01:52:17 +08:00
147a33d8ee feat: simple support Android 14 display name 2023-09-18 00:21:14 +08:00
75ec1317fa docs: optimize comments 2023-09-18 00:19:06 +08:00
62d4e727ff feat: lots of changes
- add BuildConfigWrapper
- merge to new project promote
- add ci version tag support
- Fix system api compat issues
2023-09-18 00:17:25 +08:00
c4573d221b docs: update README 2023-09-18 00:16:01 +08:00
b74adce241 style: optimize code 2023-09-18 00:15:13 +08:00
bd57f76232 docs: move images to img-src 2023-09-18 00:13:19 +08:00
e67110fd65 refactor: use new payment code 2023-09-18 00:12:18 +08:00
2c48401d21 fix: class not found when R8 since android gradle plugin 8+ 2023-09-18 00:11:32 +08:00
bcac9a3752 ci: optimize and add artifacts post to Telegram 2023-09-18 00:11:07 +08:00
656fc0446c chore: add Android 14 option 2023-09-18 00:10:37 +08:00
b4f0b65264 chore: migrate build script from groovy to kts
- using SweetDependency, SweetProperty
- merge singing key file configs to properties
- update gradle and dependencies
2023-09-18 00:10:08 +08:00
a577c49e56 chore: clean up build step files 2023-09-18 00:08:23 +08:00
1431457e37 [Change Commit Specification] Use the new commit spec from here on
child commits:
chore: add .editorconfig
2023-09-18 00:05:38 +08:00
4edf7a2df2 Modify support ColorOS 13.1 notify panel alpha in MainActivity 2023-07-15 13:55:05 +08:00
68 changed files with 1382 additions and 907 deletions

33
.editorconfig Normal file
View File

@@ -0,0 +1,33 @@
# noinspection EditorConfigKeyCorrectness
[{*.kt,*.kts}]
ktlint_standard_annotation = disabled
ktlint_standard_filename = disabled
ktlint_standard_wrapping = disabled
ktlint_standard_import-ordering = enabled
ktlint_standard_max-line-length = disabled
ktlint_standard_multiline-if-else = disabled
ktlint_standard_argument-list-wrapping = disabled
ktlint_standard_parameter-list-wrapping = disabled
ktlint_standard_trailing-comma-on-declaration-site = disabled
ktlint_function_signature_body_expression_wrapping = multiline
ktlint_standard_string-template-indent = disabled
ktlint_standard_function-signature = disabled
ktlint_standard_trailing-comma-on-call-site = disabled
ktlint_standard_multiline-expression-wrapping = disabled
ktlint_standard_no-empty-first-line-in-class-body = disabled
ktlint_standard_if-else-wrapping = disabled
ktlint_standard_if-else-bracing = disabled
ktlint_standard_statement-wrapping = disabled
ktlint_standard_blank-line-before-declaration = disabled
ktlint_standard_no-empty-file = disabled
ktlint_standard_property-naming = disabled
ktlint_standard_function-naming = disabled
ktlint_standard_chain-method-continuation = disabled
ktlint_standard_class-signature = disabled
ktlint_standard_condition-wrapping = disabled
ktlint_standard_class-signature = disabled
ij_continuation_indent_size = 2
indent_size = 4
indent_style = space
insert_final_newline = false
max_line_length = 150

View File

@@ -39,6 +39,8 @@ body:
attributes:
label: Android 版本
options:
- 15
- 14
- 13
- 12L/12.1
- 12

View File

@@ -13,17 +13,34 @@ on:
jobs:
build:
name: Build CI
if: ${{ success() }}
runs-on: ubuntu-latest
env:
APK_OUTPUT_PATH: 'app/build/outputs/apk'
TG_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TG_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
COMMIT_MESSAGE: |+
New push to GitHub\!
```
${{ github.event.head_commit.message }}
```by `${{ github.event.head_commit.author.name }}`
See commit detail [here](${{ github.event.head_commit.url }})
COMMIT_URL: ${{ github.event.head_commit.url }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Prepare GitHub Env
run: |
GITHUB_SHA=${{ github.sha }}
GITHUB_CI_COMMIT_ID=${GITHUB_SHA:0:7}
echo "GITHUB_CI_COMMIT_ID=$GITHUB_CI_COMMIT_ID" >> $GITHUB_ENV
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1
with:
cmake-version: '3.22.1'
- name: Prepare Java 11
uses: actions/setup-java@v3
- name: Prepare Java 21
uses: actions/setup-java@v4
with:
java-version: 11
java-version: 21
java-package: jdk
distribution: 'temurin'
cache: 'gradle'
@@ -34,7 +51,7 @@ jobs:
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }}
restore-keys: |
gradle-deps
- name: Cache Gradle Build
@@ -49,15 +66,23 @@ jobs:
run: |
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts(debug)
uses: actions/upload-artifact@v3
echo "DEBUG_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts (Debug)
uses: actions/upload-artifact@v4
with:
path: ${{ env.DEBUG_APK_FILE }}
name: app-debug
- name: Upload Artifacts(release)
uses: actions/upload-artifact@v3
path: ${{ env.DEBUG_APK_PATH }}
name: ColorOSNotifyIcon-debug-${{ github.event.head_commit.id }}
- name: Upload Artifacts (Release)
uses: actions/upload-artifact@v4
with:
path: ${{ env.RELEASE_APK_FILE }}
name: app-release
path: ${{ env.RELEASE_APK_PATH }}
name: ColorOSNotifyIcon-release-${{ github.event.head_commit.id }}
- name: Post Artifacts to Telegram
run: |
export debug=$(find ${{ env.APK_OUTPUT_PATH }}/debug -name "*.apk")
export release=$(find ${{ env.APK_OUTPUT_PATH }}/release -name "*.apk")
ESCAPED=`python3 -c 'import json,os,urllib.parse; msg = json.dumps(os.environ["COMMIT_MESSAGE"]); print(urllib.parse.quote(msg if len(msg) <= 1024 else json.dumps(os.environ["COMMIT_URL"])))'`
curl -v "https://api.telegram.org/bot${TG_BOT_TOKEN}/sendMediaGroup?chat_id=${TG_CHAT_ID}&media=%5B%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Fdebug%22%7D%2C%7B%22type%22%3A%22document%22%2C%20%22media%22%3A%22attach%3A%2F%2Frelease%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22:${ESCAPED}%7D%5D" \
-F debug="@$debug" \
-F release="@$release"

View File

@@ -11,18 +11,26 @@ on:
jobs:
build:
name: Pull request check
name: Pull Request Check
if: ${{ success() }}
runs-on: ubuntu-latest
env:
APK_OUTPUT_PATH: 'app/build/outputs/apk'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Prepare GitHub Env
run: |
GITHUB_SHA=${{ github.sha }}
GITHUB_CI_COMMIT_ID=${GITHUB_SHA:0:7}
echo "GITHUB_CI_COMMIT_ID=$GITHUB_CI_COMMIT_ID" >> $GITHUB_ENV
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1
with:
cmake-version: '3.22.1'
- name: Prepare Java 11
uses: actions/setup-java@v3
- name: Prepare Java 21
uses: actions/setup-java@v4
with:
java-version: 11
java-version: 21
java-package: jdk
distribution: 'temurin'
cache: 'gradle'
@@ -33,7 +41,7 @@ jobs:
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
key: gradle-deps-core-${{ hashFiles('**/build.gradle.kts') }}
restore-keys: |
gradle-deps
- name: Cache Gradle Build
@@ -48,15 +56,15 @@ jobs:
run: |
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts(debug)
uses: actions/upload-artifact@v3
echo "DEBUG_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts (Debug)
uses: actions/upload-artifact@v4
with:
path: ${{ env.DEBUG_APK_FILE }}
name: app-debug
- name: Upload Artifacts(release)
uses: actions/upload-artifact@v3
path: ${{ env.DEBUG_APK_PATH }}
name: ColorOSNotifyIcon-debug-${{ github.event.head_commit.id }}
- name: Upload Artifacts (Release)
uses: actions/upload-artifact@v4
with:
path: ${{ env.RELEASE_APK_FILE }}
name: app-release
path: ${{ env.RELEASE_APK_PATH }}
name: ColorOSNotifyIcon-release-${{ github.event.head_commit.id }}

117
.gitignore vendored
View File

@@ -1,15 +1,110 @@
## Fully .gtignore for IntelliJ, Android Studio and Gradle based Java projects
## References:
## - https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
## - https://github.com/android/platform-samples/blob/main/.gitignore
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
.idea/.name
.idea/artifacts
.idea/compiler.xml
.idea/jarRepositories.xml
.idea/modules.xml
.idea/*.iml
.idea/modules
.idea/caches
.idea/material_theme**
.idea/other.xml
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
*.ipr
# Kotlin
.kotlin
# Misc
.idea/misc.xml
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# Android studio 3.1+ additional
.idea/deployment*.xml
.idea/assetWizardSettings.xml
.idea/androidTestResultsUserPreferences.xml
# Android projects
**/local.properties
/captures
.externalNativeBuild
.cxx
local.properties
# Gradle projects
.gradle
build/
# Mkdocs temporary serving folder
docs-gen
site
*.bak
.idea/appInsightsSettings.xml
# Mac OS
.DS_Store

3
.idea/.gitignore generated vendored
View File

@@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/AndroidProjectSystem.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidProjectSystem">
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
</component>
</project>

6
.idea/compiler.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

20
.idea/gradle.xml generated
View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@@ -1,10 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="CheckImageSize" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
<inspection_tool class="YAMLSchemaValidation" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

6
.idea/kotlinc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.1.10" />
</component>
</project>

7
.idea/ktlint-plugin.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KtLint plugin">
<ktlintMode>MANUAL</ktlintMode>
<formatOnSave>false</formatOnSave>
</component>
</project>

6
.idea/ktlint.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KtlintProjectConfiguration">
<treatAsErrors>false</treatAsErrors>
</component>
</project>

10
.idea/migrations.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectMigrations">
<option name="MigrateToGradleLocalJavaHome">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
</component>
</project>

28
.idea/misc.xml generated
View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="app/src/main/res/drawable-night/bg_orange_round.xml" value="0.232" />
<entry key="app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.254" />
<entry key="app/src/main/res/drawable/bg_orange_round.xml" value="0.232" />
<entry key="app/src/main/res/drawable/ic_nf_icon_refresh.xml" value="0.232" />
<entry key="app/src/main/res/drawable/ic_nf_icon_update.xml" value="0.232" />
<entry key="app/src/main/res/drawable/ic_notify_icon.xml" value="0.232" />
<entry key="app/src/main/res/drawable/ic_system_clock.xml" value="0.232" />
<entry key="app/src/main/res/layout/activity_config.xml" value="0.4375" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.29182608695652174" />
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.4375" />
<entry key="app/src/main/res/layout/dia_icon_filter.xml" value="0.4375" />
<entry key="app/src/main/res/layout/dia_source_from.xml" value="0.4375" />
<entry key="app/src/main/res/layout/dia_source_from_string.xml" value="0.4375" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

17
.idea/runConfigurations.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
</set>
</option>
</component>
</project>

2
.idea/vcs.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,6 +0,0 @@
{
"keyAlias": "public",
"keyPassword": "123456",
"storeFileName": "universal.p12",
"storePassword": "123456"
}

View File

@@ -1,21 +1,25 @@
# ColorOS 通知图标增强
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/ColorOSNotifyIcon)
[![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/ColorOSNotifyIcon/blob/master/LICENSE)
[![Blank](https://img.shields.io/badge/version-v1.100-green)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/fankes/ColorOSNotifyIcon/total?label=Release)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.coloros.notify/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases)
[![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/XiaofangInternet)
<br/><br/>
<img src="https://github.com/fankes/ColorOSNotifyIcon/blob/master/app/src/main/ic_launcher-playstore.png?raw=true" width = "100" height = "100"/>
<br/>
[![GitHub license](https://img.shields.io/github/license/fankes/ColorOSNotifyIcon?color=blue&style=flat-square)](https://github.com/fankes/ColorOSNotifyIcon/blob/master/LICENSE)
[![GitHub CI](https://img.shields.io/github/actions/workflow/status/fankes/ColorOSNotifyIcon/commit_ci.yml?label=CI%20builds&style=flat-square)](https://github.com/fankes/ColorOSNotifyIcon/actions/workflows/commit_ci.yml)
[![GitHub release](https://img.shields.io/github/v/release/fankes/ColorOSNotifyIcon?display_name=release&logo=github&color=green&style=flat-square)](https://github.com/fankes/ColorOSNotifyIcon/releases)
![GitHub all releases](https://img.shields.io/github/downloads/fankes/ColorOSNotifyIcon/total?label=downloads&style=flat-square)
![GitHub all releases](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.coloros.notify/total?label=LSPosed%20downloads&labelColor=F48FB1&style=flat-square)
[![Telegram CI](https://img.shields.io/badge/CI%20builds-Telegram-blue.svg?logo=telegram&style=flat-square)](https://t.me/ColorOSNotifyIcon_CI)
[![Telegram](https://img.shields.io/badge/discussion-Telegram-blue.svg?logo=telegram&style=flat-square)](https://t.me/XiaofangInternet)
[![QQ](https://img.shields.io/badge/discussion-QQ-blue.svg?logo=tencent-qq&logoColor=red&style=flat-square)](https://qm.qq.com/cgi-bin/qm/qr?k=dp2h5YhWiga9WWb_Oh7kSHmx01X8I8ii&jump_from=webapi&authKey=Za5CaFP0lk7+Zgsk2KpoBD7sSaYbeXbsDgFjiWelOeH4VSionpxFJ7V0qQBSqvFM)
[![QQ 频道](https://img.shields.io/badge/discussion-QQ%20频道-blue.svg?logo=tencent-qq&logoColor=red&style=flat-square)](https://pd.qq.com/s/44gcy28h)
<img src="img-src/icon.png" width = "100" height = "100" alt="LOGO"/>
Optimize notification icons for ColorOS and adapt to native notification icon specifications.
为 ColorOS 优化通知图标以及适配原生通知图标规范,理论支持 OxygenOS 和 RealmeUI。
## Developer
## For Non-Chinese Users
[酷安 @星夜不荟](http://www.coolapk.com/u/876977)
This project will not be adapted i18n, please stay tuned for my new projects in the future.
## 项目迁移公告
@@ -25,12 +29,19 @@ Optimize notification icons for ColorOS and adapt to native notification icon sp
## 适配说明
- 此模块仅支持 <b>LSPosed</b>(作用域“系统界面”)、<b>~~EdXposed(随时停止支持)~~</b>、不支持<b>太极、无极</b>
- 此模块仅支持 **LSPosed** (作用域“系统界面”)、**~~EdXposed(随时停止支持)~~**、不支持**太极、无极**
- 目前仅在 ColorOS 12、12.1、13 for OnePlus 上测试通过,如有问题请提交 `issues`
- 建议在不低于 ColorOS 11 的版本上使用
## 注意事项
由于 ColorOS 15 版本的系统性通知图标行为变更,系统强制在通知图标初始化阶段就将图标强制替换为 APP 彩色图标进行破坏,所以目前加入了 “系统框架”
作用域如果在模块安装后没有自动勾选此作用域请手动进行勾选并重新启动系统以修复此破坏行为ColorOS 15 以下版本的系统无需勾选。
感谢 [Nep-Timeline](https://github.com/Nep-Timeline) 提供的解决方案。
## 历史背景
继 MIUI 之后的第二大系统 ColorOS 虽然支持原生通知图标,但是第三方推送五颜六色的图标系统并没有做适配,甚至系统自己的图标都是彩色的,极其不友好。
@@ -43,52 +54,63 @@ Optimize notification icons for ColorOS and adapt to native notification icon sp
- [Android 通知图标规范适配计划](https://github.com/fankes/AndroidNotifyIconAdapt)
## 请勿用于非法用途
## 发行渠道
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
| <img src="https://avatars.githubusercontent.com/in/15368?s=64&v=4" width = "30" height = "30" alt="LOGO"/> | [GitHub CI](https://github.com/fankes/ColorOSNotifyIcon/actions/workflows/commit_ci.yml) | CI 自动构建 (测试版) |
|------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|---------------|
## 发行渠道说明
| <img src="https://github.com/peter-iakovlev/Telegram/blob/public/Icon.png?raw=true" width = "30" height = "30" alt="LOGO"/> | [Telegram CI 频道](https://t.me/ColorOSNotifyIcon_CI) | CI 自动构建 (测试版) |
|-----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|---------------|
- [Automatic Build on Commit](https://github.com/fankes/ColorOSNotifyIcon/actions/workflows/commit_ci.yml)
| <img src="https://avatars.githubusercontent.com/in/15368?s=64&v=4" width = "30" height = "30" alt="LOGO"/> | [GitHub Releases](https://github.com/fankes/ColorOSNotifyIcon/releases) | 正式版 (稳定版) |
|------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------|-----------|
上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **GitHub Actions** 进行查看,本更新由开源的流程自动编译发布,**不保证其稳定性**,所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。
| <img src="https://avatars.githubusercontent.com/u/78217009?s=200&v=4?raw=true" width = "30" height = "30" alt="LOGO"/> | [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases) | 正式版 (稳定版) |
|------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-----------|
- [Release](https://github.com/fankes/ColorOSNotifyIcon/releases)
- [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases)
- [蓝奏云 **密码al5u**](https://fankes.lanzouy.com/b030rvjyf)
- [酷安应用市场](https://www.coolapk.com/apk/com.fankes.coloros.notify)
| <img src="https://github.com/fankes/fankes/assets/37344460/82113d3c-aa7b-4dd1-95c7-cda650065c12" width = "30" height = "30" alt="LOGO"/> | [123 云盘 **(密码al5u)**](https://www.123pan.com/s/5SlUVv-C8DBh.html) | 正式版 (稳定版) |
|------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|-----------|
上述更新为手动发布的稳定版,具体更新内容可点击上方的文字前往指定的发布页面查看,稳定版的更新将会同时发布到上述地址中,同步更新
本模块发布地址仅限于上述所列出的地址,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关
## 发行状态说明
## 注意事项
![Blank](https://img.shields.io/badge/build-passing-brightgreen)
<h3>1.&nbsp;本软件免费、由兴趣驱动开发,仅供学习交流使用。如果你是从其他非官方渠道付费获得本软件,可能已遭遇欺诈,欢迎向我们举报可疑行为。</h3>
上述状态为当前稳定版与自动构建版本一致或当前代码改动与稳定版无功能差异。
<h3>2.&nbsp;本软件采用 <strong>GNU Affero General Public License (AGPL 3.0)</strong> 许可证。根据该许可证的要求:</h3>
![Blank](https://img.shields.io/badge/build-pending-dbab09)
- 任何衍生作品必须采用相同的 AGPL 许可证
- 分发本软件或其修改版本时,必须提供完整的源代码
- 必须保留原始的版权声明及许可证信息
- 不得额外施加限制来限制他人对本软件的自由使用
上述状态为存在自动构建版本和新功能的更新但当前并未发布稳定版,处于预发行状态。
<h3>3.&nbsp;我们鼓励在遵守 AGPL 3.0 条款的前提下进行自由传播和改进,但请尊重作者署名权,勿冒用原作者名义。</h3>
![Blank](https://img.shields.io/badge/build-problem-red)
## 项目推广
上述状态为当前发行的稳定版可能存在严重问题但并未及时进行修复且并未发布稳定版。
<!--suppress HtmlDeprecatedAttribute -->
<div align="center">
<h2>嘿,还请君留步!👋</h2>
<h3>这里有 Android 开发工具、UI 设计、Gradle 插件、Xposed 模块和实用软件等相关项目。</h3>
<h3>如果下方的项目能为你提供帮助,不妨为我点个 star 吧!</h3>
<h3>所有项目免费、开源,遵循对应开源许可协议。</h3>
<h1><a href="https://github.com/fankes/fankes/blob/main/project-promote/README-zh-CN.md">→ 查看更多关于我的项目,请点击这里 ←</a></h1>
</div>
## 捐赠支持
## Star History
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<br/><br/>
<img src="https://github.com/fankes/YuKiHookAPI/blob/master/img-src/wechat_code.jpg?raw=true" width = "200" height = "200"/>
![Star History Chart](https://api.star-history.com/svg?repos=fankes/ColorOSNotifyIcon&type=Date)
## 隐私政策
- [PRIVACY](https://github.com/fankes/ColorOSNotifyIcon/blob/master/PRIVACY.md)
- [PRIVACY](PRIVACY.md)
## 许可证
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
```
Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@@ -101,9 +123,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
along with this program. If not, see <https://www.gnu.org/licenses/>.
```
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)
Powered by [YukiHookAPI](https://github.com/HighCapable/YukiHookAPI)
版权所有 © 2017-2023 Fankes Studio(qzmmcn@163.com)
版权所有 © 20174 Fankes Studio(qzmmcn@163.com)

1
app/.gitignore vendored
View File

@@ -1,3 +1,2 @@
/build
/src/main/assets/xposed_init
/src/main/resources/META-INF/yukihookapi_init

View File

@@ -1,88 +0,0 @@
import groovy.json.JsonSlurper
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp'
}
android {
signingConfigs {
universal {
def dirPath = rootProject.ext.app.signingConfigs.secretConfigsDirPath
def fileName = rootProject.ext.app.signingConfigs.secretConfigsFileName
def configs = new JsonSlurper().parse(file("${dirPath}/${fileName}"))
keyAlias configs.keyAlias
keyPassword configs.keyPassword
storeFile file("${dirPath}/${configs.storeFileName}")
storePassword configs.storePassword
v1SigningEnabled true
v2SigningEnabled true
}
}
namespace 'com.fankes.coloros.notify'
compileSdk rootProject.ext.android.compileSdk
defaultConfig {
applicationId 'com.fankes.coloros.notify'
minSdk rootProject.ext.android.minSdk
targetSdk rootProject.ext.android.targetSdk
versionCode rootProject.ext.app.versionCode
versionName rootProject.ext.app.versionName
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
debug {
minifyEnabled false
signingConfig signingConfigs.universal
}
release {
minifyEnabled true
shrinkResources true
zipAlignEnabled true
signingConfig signingConfigs.universal
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
freeCompilerArgs = [
'-Xno-param-assertions',
'-Xno-call-assertions',
'-Xno-receiver-assertions'
]
}
buildFeatures {
viewBinding true
}
lintOptions {
checkReleaseBuilds false
}
aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
}
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.1.11'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.11'
implementation 'com.github.duanhong169:drawabletoolbox:1.0.7'
implementation "com.github.topjohnwu.libsu:core:5.0.4"
implementation 'androidx.annotation:annotation:1.6.0'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

89
app/build.gradle.kts Normal file
View File

@@ -0,0 +1,89 @@
plugins {
autowire(libs.plugins.android.application)
autowire(libs.plugins.kotlin.android)
autowire(libs.plugins.kotlin.ksp)
}
android {
namespace = property.project.app.packageName
compileSdk = property.project.android.compileSdk
signingConfigs {
create("universal") {
keyAlias = property.project.app.signing.keyAlias
keyPassword = property.project.app.signing.keyPassword
storeFile = rootProject.file(property.project.app.signing.storeFilePath)
storePassword = property.project.app.signing.storePassword
enableV1Signing = true
enableV2Signing = true
}
}
defaultConfig {
applicationId = property.project.app.packageName
minSdk = property.project.android.minSdk
targetSdk = property.project.android.targetSdk
versionName = property.project.app.versionName
versionCode = property.project.app.versionCode
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
all { signingConfig = signingConfigs.getByName("universal") }
release {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures {
buildConfig = true
viewBinding = true
}
lint { checkReleaseBuilds = false }
androidResources.additionalParameters += listOf("--allow-reserved-package-id", "--package-id", "0x37")
}
androidComponents {
onVariants(selector().all()) {
it.outputs.forEach { output ->
val currentType = it.buildType
// Workaround for GitHub Actions.
// Why? I don't know, but it works.
// Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
// public inline fun CharSequence.isNotBlank(): Boolean defined in kotlin.text.
@Suppress("UNNECESSARY_SAFE_CALL", "RemoveRedundantCallsOfConversionMethods")
val currentSuffix = property.github.ci.commit.id?.let { suffix ->
// Workaround for GitHub Actions.
// Strongly transfer type to [String].
val sSuffix = suffix.toString()
if (sSuffix.isNotBlank()) "-$sSuffix" else ""
}
val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})"
if (output is com.android.build.api.variant.impl.VariantOutputImpl)
output.outputFileName.set("${property.project.name}-v$currentVersion-$currentType.apk")
}
}
}
dependencies {
compileOnly(de.robv.android.xposed.api)
implementation(com.highcapable.yukihookapi.api)
ksp(com.highcapable.yukihookapi.ksp.xposed)
implementation(com.highcapable.kavaref.kavaref.core)
implementation(com.highcapable.kavaref.kavaref.extension)
implementation(com.fankes.projectpromote.project.promote)
implementation(com.github.topjohnwu.libsu.core)
implementation(com.github.duanhong169.drawabletoolbox)
implementation(com.squareup.okhttp3.okhttp)
implementation(androidx.core.core.ktx)
implementation(androidx.appcompat.appcompat)
implementation(com.google.android.material.material)
implementation(androidx.constraintlayout.constraintlayout)
testImplementation(junit.junit)
androidTestImplementation(androidx.test.ext.junit)
androidTestImplementation(androidx.test.espresso.espresso.core)
}

View File

@@ -32,13 +32,15 @@
-adaptresourcefilecontents
-renamesourcefileattribute P
-keepattributes SourceFile,LineNumberTable
-keepattributes SourceFile,Signature,LineNumberTable
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
public static *** throwUninitializedProperty(...);
public static *** throwUninitializedPropertyAccessException(...);
}
-keepclassmembers class * implements androidx.viewbinding.ViewBinding {
-keep class * extends android.app.Activity
-keep class * implements androidx.viewbinding.ViewBinding {
<init>();
*** inflate(android.view.LayoutInflater);
}

View File

@@ -1,12 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.fankes.coloros.notify">
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
tools:node="remove" />
<permission
android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
tools:node="remove" />
<application
android:name=".application.CNNApplication"
android:allowBackup="true"

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/24.
* This file is created by fankes on 2022/1/24.
*/
@file:Suppress("unused")

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/30.
* This file is created by fankes on 2022/1/30.
*/
package com.fankes.coloros.notify.bean
@@ -47,13 +47,15 @@ data class IconDataBean(
) : Serializable {
fun toEnabledName() = ("$appName$packageName").base64 + "_enable"
fun toEnabledAllName() = ("$appName$packageName").base64 + "_enable_all"
override fun toString() = "{\n" +
" \"appName\": \"$appName\",\n" +
" \"packageName\": \"$packageName\",\n" +
" \"iconBitmap\": \"${iconBitmap.base64}\",\n" +
" \"iconColor\": \"#${Integer.toHexString(iconColor)}\",\n" +
" \"contributorName\": \"$contributorName\",\n" +
" \"isEnabled\": $isEnabled,\n" +
" \"isEnabledAll\": $isEnabledAll\n" +
" }"
override fun toString() = """
{
"appName": "$appName",
"packageName": "$packageName",
"iconBitmap": "${iconBitmap.base64}",
"iconColor": "#${Integer.toHexString(iconColor)}",
"contributorName": "$contributorName",
"isEnabled": $isEnabled,
"isEnabledAll": $isEnabledAll
}
""".trimIndent()
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,10 +18,15 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/2/2.
* This file is created by fankes on 2023/2/2.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
package com.fankes.coloros.notify.const
import com.fankes.coloros.notify.generated.AppProperties
import com.fankes.coloros.notify.wrapper.BuildConfigWrapper
/**
* 包名常量定义类
*/
@@ -50,4 +55,27 @@ object IconRuleSourceSyncType {
/** 自定义地址 */
const val CUSTOM_URL = 3000
}
/**
* 模块版本常量定义类
*/
object ModuleVersion {
/** 当前 GitHub 提交的 ID (CI 自动构建) */
const val GITHUB_COMMIT_ID = AppProperties.GITHUB_CI_COMMIT_ID
/** 版本名称 */
const val NAME = BuildConfigWrapper.VERSION_NAME
/** 版本号 */
const val CODE = BuildConfigWrapper.VERSION_CODE
/** 是否为 CI 自动构建版本 */
val isCiMode = GITHUB_COMMIT_ID.isNotBlank()
/** 当前版本名称后缀 */
val suffix = GITHUB_COMMIT_ID.let { if (it.isNotBlank()) "-$it" else "" }
override fun toString() = "$NAME$suffix($CODE)"
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/2/2.
* This file is created by fankes on 2023/2/2.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
@@ -28,7 +28,7 @@ import android.content.Context
import com.fankes.coloros.notify.const.IconRuleSourceSyncType
import com.fankes.coloros.notify.utils.factory.isUpperOfAndroidS
import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
@@ -134,7 +134,7 @@ object ConfigData {
private fun putString(data: PrefsData<String>, value: String) {
when (instance) {
is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method")
is PackageParam -> YLog.warn("Not support for this method")
else -> error("Unknown type for put prefs data")
}
}
@@ -158,7 +158,7 @@ object ConfigData {
internal fun putInt(data: PrefsData<Int>, value: Int) {
when (instance) {
is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method")
is PackageParam -> YLog.warn("Not support for this method")
else -> error("Unknown type for put prefs data")
}
}
@@ -182,7 +182,7 @@ object ConfigData {
internal fun putBoolean(data: PrefsData<Boolean>, value: Boolean) {
when (instance) {
is Context -> (instance as Context).prefs().edit { put(data, value) }
is PackageParam -> loggerW(msg = "Not support for this method")
is PackageParam -> YLog.warn("Not support for this method")
else -> error("Unknown type for put prefs data")
}
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/2/3.
* This file is created by fankes on 2023/2/3.
*/
@file:Suppress("unused", "MemberVisibilityCanBePrivate")

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/2/4.
* This file is created by fankes on 2023/2/4.
*/
@file:Suppress("SetTextI18n")

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,21 +18,22 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/2/26.
* This file is created by fankes on 2022/2/26.
*/
package com.fankes.coloros.notify.hook
import com.fankes.coloros.notify.const.PackageName
import com.fankes.coloros.notify.data.ConfigData
import com.fankes.coloros.notify.hook.entity.FrameworkHooker
import com.fankes.coloros.notify.hook.entity.SystemUIHooker
import com.fankes.coloros.notify.utils.factory.isNotColorOS
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.factory.configs
import com.highcapable.yukihookapi.hook.factory.encase
import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
@InjectYukiHookWithXposed
object HookEntry : IYukiHookXposedInit {
override fun onInit() = configs {
@@ -45,13 +46,13 @@ object HookEntry : IYukiHookXposedInit {
}
override fun onHook() = encase {
if (isNotColorOS) return@encase YLog.warn("Aborted Hook -> This System is not ColorOS")
loadSystem(FrameworkHooker)
loadApp(PackageName.SYSTEMUI) {
ConfigData.init(instance = this)
when {
isNotColorOS -> loggerW(msg = "Aborted Hook -> This System is not ColorOS")
ConfigData.isEnableModule.not() -> loggerW(msg = "Aborted Hook -> Hook Closed")
else -> loadHooker(SystemUIHooker)
}
if (ConfigData.isEnableModule)
loadHooker(SystemUIHooker)
else YLog.warn("Aborted Hook -> Hook Closed")
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by Nep-Timeline on 2025/5/27.
*/
package com.fankes.coloros.notify.hook.entity
import android.app.Notification
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
/**
* 系统框架核心 Hook 类
*/
object FrameworkHooker : YukiBaseHooker() {
/** ColorOS 存在的类 - 旧版本不存在 */
private val OplusNotificationFixHelperClass by lazyClassOrNull("com.android.server.notification.OplusNotificationFixHelper")
override fun onHook() {
/** 拦截 ColorOS 覆盖应用通知图标 */
OplusNotificationFixHelperClass?.resolve()?.optional()?.firstMethodOrNull {
name = "fixSmallIcon"
parameters(Notification::class, String::class, String::class, Boolean::class)
}?.hook()?.intercept()
}
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,9 +18,9 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/25.
* This file is created by fankes on 2022/3/25.
*/
@file:Suppress("StaticFieldLeak")
@file:Suppress("StaticFieldLeak", "ConstPropertyName")
package com.fankes.coloros.notify.hook.entity
@@ -32,7 +32,6 @@ import android.content.IntentFilter
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.Outline
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.os.SystemClock
@@ -43,6 +42,7 @@ import android.view.ViewGroup
import android.view.ViewOutlineProvider
import android.widget.ImageView
import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.children
import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.bean.IconDataBean
@@ -51,22 +51,30 @@ import com.fankes.coloros.notify.data.ConfigData
import com.fankes.coloros.notify.param.IconPackParams
import com.fankes.coloros.notify.param.factory.isAppNotifyHookAllOf
import com.fankes.coloros.notify.param.factory.isAppNotifyHookOf
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.appIconOf
import com.fankes.coloros.notify.utils.factory.appNameOf
import com.fankes.coloros.notify.utils.factory.colorAlphaOf
import com.fankes.coloros.notify.utils.factory.delayedRun
import com.fankes.coloros.notify.utils.factory.dp
import com.fankes.coloros.notify.utils.factory.dpFloat
import com.fankes.coloros.notify.utils.factory.drawableOf
import com.fankes.coloros.notify.utils.factory.isSystemInDarkMode
import com.fankes.coloros.notify.utils.factory.isUpperOfAndroidS
import com.fankes.coloros.notify.utils.factory.runInSafe
import com.fankes.coloros.notify.utils.factory.safeOf
import com.fankes.coloros.notify.utils.factory.safeOfFalse
import com.fankes.coloros.notify.utils.factory.systemAccentColor
import com.fankes.coloros.notify.utils.tool.ActivationPromptTool
import com.fankes.coloros.notify.utils.tool.BitmapCompatTool
import com.fankes.coloros.notify.utils.tool.IconAdaptationTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.kavaref.KavaRef.Companion.asResolver
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.kavaref.condition.type.VagueType
import com.highcapable.kavaref.extension.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.*
import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerE
import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.type.android.*
import com.highcapable.yukihookapi.hook.type.java.BooleanType
import com.highcapable.yukihookapi.hook.type.java.FloatType
import com.highcapable.yukihookapi.hook.type.java.IntType
import com.highcapable.yukihookapi.hook.type.java.LongType
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.log.YLog
import top.defaults.drawabletoolbox.DrawableBuilder
/**
@@ -75,110 +83,150 @@ import top.defaults.drawabletoolbox.DrawableBuilder
object SystemUIHooker : YukiBaseHooker() {
/** 原生存在的类 */
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
private val ContrastColorUtilClass by lazyClass("com.android.internal.util.ContrastColorUtil")
/** 原生存在的类 */
private const val NotificationUtilsClass = "${PackageName.SYSTEMUI}.statusbar.notification.NotificationUtils"
private val NotificationUtilsClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.notification.NotificationUtils")
/** 原生存在的类 */
private const val NotificationEntryClass = "${PackageName.SYSTEMUI}.statusbar.notification.collection.NotificationEntry"
private val NotificationIconAreaControllerClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.phone.NotificationIconAreaController")
/** 原生存在的类 */
private const val StatusBarIconClass = "com.android.internal.statusbar.StatusBarIcon"
private val NotificationEntryClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.notification.collection.NotificationEntry")
/** 原生存在的类 */
private const val StatusBarIconViewClass = "${PackageName.SYSTEMUI}.statusbar.StatusBarIconView"
private val StatusBarIconClass by lazyClass("com.android.internal.statusbar.StatusBarIcon")
/** 原生存在的类 */
private const val IconBuilderClass = "${PackageName.SYSTEMUI}.statusbar.notification.icon.IconBuilder"
private val StatusBarIconViewClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.StatusBarIconView")
/** 原生存在的类 */
private const val IconManagerClass = "${PackageName.SYSTEMUI}.statusbar.notification.icon.IconManager"
private val IconBuilderClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.notification.icon.IconBuilder")
/** 原生存在的类 */
private const val NotificationBackgroundViewClass = "${PackageName.SYSTEMUI}.statusbar.notification.row.NotificationBackgroundView"
private val IconManagerClass by lazyClass("${PackageName.SYSTEMUI}.statusbar.notification.icon.IconManager")
/** 原生存在的类 */
private const val PlayerViewHolderClass = "${PackageName.SYSTEMUI}.media.PlayerViewHolder"
private val NotificationBackgroundViewClass by lazyClassOrNull("${PackageName.SYSTEMUI}.statusbar.notification.row.NotificationBackgroundView")
/** 原生存在的类 */
private const val MediaDataClass = "${PackageName.SYSTEMUI}.media.MediaData"
private val PlayerViewHolderClass by lazyClassOrNull("${PackageName.SYSTEMUI}.media.PlayerViewHolder")
/** 原生存在的类 */
private val MediaDataClass by lazyClassOrNull("${PackageName.SYSTEMUI}.media.MediaData")
/** 原生存在的类 - 旧版本不存在 */
private val LegacyNotificationIconAreaControllerImpl by lazyClassOrNull("${PackageName.SYSTEMUI}.statusbar.phone.LegacyNotificationIconAreaControllerImpl")
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
private val OplusContrastColorUtilClass by lazyClassOrNull("com.oplusos.util.OplusContrastColorUtil")
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusNotificationBackgroundViewClass =
"com.oplusos.systemui.statusbar.notification.row.OplusNotificationBackgroundView"
private val OplusNotificationBackgroundViewClass by lazyClassOrNull("com.oplusos.systemui.statusbar.notification.row.OplusNotificationBackgroundView")
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusMediaControlPanelClass = "com.oplusos.systemui.media.OplusMediaControlPanel"
private val OplusMediaControlPanelClass by lazyClassOrNull("com.oplusos.systemui.media.OplusMediaControlPanel")
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusMediaViewControllerClass = "com.oplusos.systemui.media.OplusMediaViewController"
private val OplusMediaViewControllerClass by lazyClassOrNull("com.oplusos.systemui.media.OplusMediaViewController")
/** ColorOS 存在的类 - 旧版本不存在 */
private const val BasePlayViewHolderClass = "com.oplusos.systemui.media.base.BasePlayViewHolder"
private val BasePlayViewHolderClass by lazyClassOrNull("com.oplusos.systemui.media.base.BasePlayViewHolder")
/** ColorOS 存在的类 - 旧版本不存在 */
private val OplusNotificationSmallIconUtilClass by lazyClassOrNull("com.oplus.systemui.statusbar.notification.util.OplusNotificationSmallIconUtil")
/** 根据多个版本存在不同的包名相同的类 */
private val OplusNotificationIconAreaControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.policy.OplusNotificationIconAreaController",
"com.coloros.systemui.statusbar.policy.ColorNotificationIconAreaController"
private val OplusNotificationIconAreaControllerClass by lazyClass(
VariousClass(
"com.oplus.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.policy.OplusNotificationIconAreaController",
"com.coloros.systemui.statusbar.policy.ColorNotificationIconAreaController"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val SystemPromptControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.policy.SystemPromptController",
"com.coloros.systemui.statusbar.policy.ColorSystemPromptController"
private val SystemPromptControllerClass by lazyClass(
VariousClass(
"com.oplus.systemui.statusbar.controller.SystemPromptController",
"com.oplusos.systemui.statusbar.policy.SystemPromptController",
"com.coloros.systemui.statusbar.policy.ColorSystemPromptController"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtilClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil"
private val RoundRectDrawableUtilClass by lazyClass(
VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtil_CompanionClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil\$Companion"
private val RoundRectDrawableUtil_CompanionClass by lazyClass(
VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil\$Companion"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val DndAlertHelperClass = VariousClass(
"com.oplusos.systemui.notification.helper.DndAlertHelper",
"com.coloros.systemui.notification.helper.DndAlertHelper"
private val DndAlertHelperClass by lazyClass(
VariousClass(
"com.oplus.systemui.statusbar.notification.helper.DndAlertHelper",
"com.oplusos.systemui.notification.helper.DndAlertHelper",
"com.coloros.systemui.notification.helper.DndAlertHelper"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val OplusPowerNotificationWarningsClass = VariousClass(
"com.oplusos.systemui.notification.power.OplusPowerNotificationWarnings",
"com.coloros.systemui.notification.power.ColorosPowerNotificationWarnings"
private val OplusPowerNotificationWarningsClass by lazyClass(
VariousClass(
"com.oplus.systemui.statusbar.notification.power.OplusPowerNotificationWarnings",
"com.oplusos.systemui.notification.power.OplusPowerNotificationWarnings",
"com.coloros.systemui.notification.power.ColorosPowerNotificationWarnings"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val StatusBarNotificationPresenterClass = VariousClass(
"${PackageName.SYSTEMUI}.statusbar.phone.StatusBarNotificationPresenter",
"${PackageName.SYSTEMUI}.statusbar.phone.StatusBar"
private val StatusBarNotificationPresenterClass by lazyClass(
VariousClass(
"${PackageName.SYSTEMUI}.statusbar.phone.StatusBarNotificationPresenter",
"${PackageName.SYSTEMUI}.statusbar.phone.StatusBar"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val ExpandableNotificationRowClass = VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.ExpandableNotificationRow",
"${PackageName.SYSTEMUI}.statusbar.ExpandableNotificationRow"
private val ExpandableNotificationRowClass by lazyClass(
VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.ExpandableNotificationRow",
"${PackageName.SYSTEMUI}.statusbar.ExpandableNotificationRow"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationViewWrapperClass = VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.wrapper.NotificationViewWrapper",
"${PackageName.SYSTEMUI}.statusbar.notification.NotificationViewWrapper"
private val NotificationViewWrapperClass by lazyClass(
VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.wrapper.NotificationViewWrapper",
"${PackageName.SYSTEMUI}.statusbar.notification.NotificationViewWrapper"
)
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationHeaderViewWrapperClass = VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"${PackageName.SYSTEMUI}.statusbar.notification.NotificationHeaderViewWrapper"
private val NotificationHeaderViewWrapperClass by lazyClass(
VariousClass(
"${PackageName.SYSTEMUI}.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"${PackageName.SYSTEMUI}.statusbar.notification.NotificationHeaderViewWrapper"
)
)
/** 根据多个版本存在不同的方法相同的类 */
private val StatusBarIconControllerClass by lazyClass(
VariousClass(
"${PackageName.SYSTEMUI}.statusbar.StatusBarIconView",
"com.oplus.systemui.statusbar.phone.StatusBarIconControllerExImpl"
)
)
/** 缓存的彩色 APP 图标 */
@@ -222,10 +270,11 @@ object SystemUIHooker : YukiBaseHooker() {
* @return [Boolean]
*/
private val isOldNotificationBackground
get() = NotificationBackgroundViewClass.toClassOrNull()?.hasMethod {
name = "drawCustom"
paramCount = 2
} ?: false
get() = NotificationBackgroundViewClass?.resolve()?.optional(silent = true)
?.firstMethodOrNull {
name = "drawCustom"
parameterCount = 2
} != null
/**
* 打印日志
@@ -236,17 +285,17 @@ object SystemUIHooker : YukiBaseHooker() {
* @param isGrayscale 是否为灰度图标
*/
private fun loggerDebug(tag: String, context: Context, nf: StatusBarNotification?, isCustom: Boolean, isGrayscale: Boolean) {
if (ConfigData.isEnableModuleLog) loggerD(
if (ConfigData.isEnableModuleLog) YLog.debug(
msg = "(Processing $tag) ↓\n" +
"[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" +
"[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" +
"[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" +
"[Package Name]: ${nf?.packageName}\n" +
"[Sender Package Name]: ${nf?.opPkg}\n" +
"[Custom Icon]: $isCustom\n" +
"[Grayscale Icon]: $isGrayscale\n" +
"[From System Push]: ${nf?.isOplusPush}\n" +
"[String]: ${nf?.notification}"
"[Title]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TITLE)}\n" +
"[Content]: ${nf?.notification?.extras?.getString(Notification.EXTRA_TEXT)}\n" +
"[App Name]: ${context.appNameOf(packageName = nf?.packageName ?: "")}\n" +
"[Package Name]: ${nf?.packageName}\n" +
"[Sender Package Name]: ${nf?.opPkg}\n" +
"[Custom Icon]: $isCustom\n" +
"[Grayscale Icon]: $isGrayscale\n" +
"[From System Push]: ${nf?.isOplusPush}\n" +
"[String]: ${nf?.notification}"
)
}
@@ -265,24 +314,29 @@ object SystemUIHooker : YukiBaseHooker() {
/** 刷新状态栏小图标 */
private fun refreshStatusBarIcons() = runInSafe {
val nfField = StatusBarIconViewClass.toClass().field { name = "mNotification" }
val sRadiusField = StatusBarIconViewClass.toClass().field { name = "sIconRadiusFraction" }
val sNfSizeField = StatusBarIconViewClass.toClass().field { name = "sNotificationRoundIconSize" }
val roundUtil = RoundRectDrawableUtil_CompanionClass.toClass().method {
val nfField = StatusBarIconViewClass.resolve().optional().firstFieldOrNull { name = "mNotification" }
val sRadiusField = StatusBarIconViewClass.resolve().optional(silent = true).firstFieldOrNull {
name = "sIconRadiusFraction"
} ?: StatusBarIconControllerClass.resolve().optional(silent = true).firstFieldOrNull { name = "sIconRadiusFraction" }
val sNfSizeField = StatusBarIconViewClass.resolve().optional(silent = true).firstFieldOrNull {
name = "sNotificationRoundIconSize"
} ?: StatusBarIconControllerClass.resolve().optional(silent = true).firstFieldOrNull { name = "sNotificationRoundIconSize" }
val roundUtil = RoundRectDrawableUtil_CompanionClass.resolve().optional(silent = true).firstMethodOrNull {
name = "getRoundRectDrawable"
param(DrawableClass, FloatType, IntType, IntType, ContextClass)
}.onNoSuchMethod { loggerE(msg = "Your system not support \"getRoundRectDrawable\"!", e = it) }
.get(RoundRectDrawableUtilClass.toClass().field { name = "Companion" }.get().any())
parameters(Drawable::class, Float::class, Int::class, Int::class, Context::class)
}.apply {
if (this == null) YLog.error("Your system not support \"getRoundRectDrawable\"!")
}?.of(RoundRectDrawableUtilClass.resolve().optional().firstFieldOrNull { name = "Companion" }?.get())
/** 启动一个线程防止卡顿 */
Thread {
(notificationIconContainer?.children?.toList() ?: notificationIconInstances.takeIf { it.isNotEmpty() })?.forEach {
runInSafe {
/** 得到通知实例 */
val nf = nfField.get(it).cast<StatusBarNotification>() ?: return@Thread
val nf = nfField?.of(it)?.get<StatusBarNotification>() ?: return@Thread
/** 得到原始通知图标 */
val iconDrawable = nf.notification.smallIcon.loadDrawable(it.context)
?: return@Thread loggerW(msg = "refreshStatusBarIcons got null smallIcon")
?: return@Thread YLog.warn("refreshStatusBarIcons got null smallIcon")
/** 获取优化后的状态栏通知图标 */
compatStatusIcon(
context = it.context,
@@ -292,12 +346,16 @@ object SystemUIHooker : YukiBaseHooker() {
drawable = iconDrawable
).also { pair ->
/** 得到图标圆角 */
val sRadius = sRadiusField.get(it).float()
val sRadius = sRadiusField?.of(it)?.get<Float>()
/** 得到缩放大小 */
val sNfSize = sNfSizeField.get(it).int()
val sNfSize = sNfSizeField?.of(it)?.get<Int>()
/** 在主线程设置图标 */
it.post { (it as? ImageView?)?.setImageDrawable(roundUtil.invoke(pair.first, sRadius, sNfSize, sNfSize, it.context)) }
it.post {
val drawable = roundUtil?.invokeQuietly<Drawable>(pair.first, sRadius, sNfSize, sNfSize, it.context)
(it as? ImageView?)?.setImageDrawable(drawable)
}
}
}
}
@@ -306,10 +364,10 @@ object SystemUIHooker : YukiBaseHooker() {
/** 刷新通知小图标 */
private fun refreshNotificationIcons() = runInSafe {
notificationPresenter?.current()?.method {
notificationPresenter?.asResolver()?.optional()?.firstMethodOrNull {
name = "updateNotificationsOnDensityOrFontScaleChanged"
emptyParam()
}?.call()
emptyParameters()
}?.invoke()
modifyNotifyPanelAlpha(notificationPlayerView, isTint = true)
}
@@ -323,15 +381,19 @@ object SystemUIHooker : YukiBaseHooker() {
*/
private fun isGrayscaleIcon(context: Context, drawable: Drawable) =
if (ConfigData.isEnableColorIconCompat.not()) safeOfFalse {
ContrastColorUtilClass.toClass().let {
it.method {
name = "isGrayscaleIcon"
param(DrawableClass)
}.get(it.method {
name = "getInstance"
param(ContextClass)
}.get().invoke(context)).boolean(drawable)
}
ContrastColorUtilClass.resolve()
.optional(silent = true)
.let {
it.firstMethodOrNull {
name = "isGrayscaleIcon"
parameters(Drawable::class)
}?.of(
it.firstMethodOrNull {
name = "getInstance"
parameters(Context::class)
}?.invoke(context)
)?.invokeQuietly<Boolean>(drawable) == true
}
} else BitmapCompatTool.isGrayscaleDrawable(drawable)
/**
@@ -360,7 +422,11 @@ object SystemUIHooker : YukiBaseHooker() {
context.injectModuleAppResources()
var customPair: Triple<Drawable?, Int, Boolean>? = null
val statSysAdbIcon = runCatching {
context.resources.drawableOf("com.android.internal.R\$drawable".toClass().field { name = "stat_sys_adb" }.get().int())
val resId = "com.android.internal.R\$drawable".toClass()
.resolve()
.firstField { name = "stat_sys_adb" }
.get<Int>() ?: error("Resource not found")
context.resources.drawableOf(resId)
}.getOrNull() ?: context.resources.drawableOf(R.drawable.ic_unsupported)
when {
/** 替换系统图标为 Android 默认 */
@@ -371,7 +437,7 @@ object SystemUIHooker : YukiBaseHooker() {
iconDatas.takeIf { it.isNotEmpty() }?.forEach {
if (packageName == it.packageName && isAppNotifyHookOf(it)) {
if (isGrayscaleIcon.not() || isAppNotifyHookAllOf(it))
customPair = Triple(BitmapDrawable(context.resources, it.iconBitmap), it.iconColor, false)
customPair = Triple(it.iconBitmap.toDrawable(context.resources), it.iconColor, false)
return@run
}
}
@@ -611,267 +677,242 @@ object SystemUIHooker : YukiBaseHooker() {
/** 缓存图标数据 */
cachingIconDatas()
/** 移除开发者警告通知 */
SystemPromptControllerClass.hook {
injectMember {
method { name = "updateDeveloperMode" }
beforeHook {
/** 是否移除 */
if (ConfigData.isEnableRemoveDevNotify) resultNull()
}
}
SystemPromptControllerClass.resolve().optional().firstMethodOrNull {
name = "updateDeveloperMode"
}?.hook()?.before {
/** 是否移除 */
if (ConfigData.isEnableRemoveDevNotify) resultNull()
}
/** 移除充电完成通知 */
OplusPowerNotificationWarningsClass.hook {
injectMember {
method {
name = "showChargeErrorDialog"
param(IntType)
}
beforeHook {
/** 是否移除 */
if (args().first().int() == 7 && ConfigData.isEnableRemoveChangeCompleteNotify) resultNull()
}
}
OplusPowerNotificationWarningsClass.resolve().optional().firstMethodOrNull {
name = "showChargeErrorDialog"
parameters(Int::class)
}?.hook()?.before {
/** 是否移除 */
if (args().first().int() == 7 && ConfigData.isEnableRemoveChangeCompleteNotify) resultNull()
}
/** 移除免打扰通知 */
DndAlertHelperClass.hook {
injectMember {
method {
name { it.lowercase() == "sendnotificationwithendtime" }
param(LongType)
}
beforeHook {
/** 是否移除 */
if (ConfigData.isEnableRemoveDndAlertNotify) resultNull()
}
DndAlertHelperClass.resolve().optional(silent = true).apply {
firstMethodOrNull {
name { it.lowercase() == "sendnotificationwithendtime" }
parameters(Long::class)
}?.hook()?.before {
/** 是否移除 */
if (ConfigData.isEnableRemoveDndAlertNotify) resultNull()
}
firstMethodOrNull {
name = "operateNotification"
parameters(Long::class, Int::class, Boolean::class)
}?.hook()?.before {
/** 是否移除 */
if (ConfigData.isEnableRemoveDndAlertNotify) resultNull()
}
}
/** 拦截 ColorOS 使用应用图标判断 */
OplusNotificationSmallIconUtilClass?.resolve()?.optional()?.firstMethodOrNull {
name = "useAppIconForSmallIcon"
parameters(Notification::class)
}?.hook()?.before {
resultFalse()
}
/** 修复并替换 ColorOS 以及原生灰度图标色彩判断 */
NotificationUtilsClass.hook {
injectMember {
method {
name = "isGrayscale"
param(ImageViewClass, ContrastColorUtilClass)
}
replaceAny { args().first().cast<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } ?: callOriginal() }
}
injectMember {
method {
name = "isGrayscaleOplus"
param(ImageViewClass, OplusContrastColorUtilClass)
}
replaceAny { args().first().cast<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } ?: callOriginal() }
}.ignoredNoSuchMemberFailure()
NotificationUtilsClass.resolve().optional(silent = true).apply {
firstMethodOrNull {
name = "isGrayscale"
parameters(ImageView::class, ContrastColorUtilClass)
}?.hook()?.replaceAny { args().first().cast<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } ?: callOriginal() }
firstMethodOrNull {
name = "isGrayscaleOplus"
parameters(ImageView::class, OplusContrastColorUtilClass ?: VagueType)
}?.hook()?.replaceAny { args().first().cast<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } ?: callOriginal() }
}
/** 替换状态栏图标 */
IconManagerClass.hook {
injectMember {
method {
name = "getIconDescriptor"
param(NotificationEntryClass, BooleanType)
IconManagerClass.resolve().optional().firstMethodOrNull {
name = "getIconDescriptor"
parameters(NotificationEntryClass, Boolean::class)
}?.hook()?.after {
IconBuilderClass.resolve().optional().firstFieldOrNull { name = "context" }
?.of(IconManagerClass.resolve().optional().firstFieldOrNull { name = "iconBuilder" }?.of(instance)?.get())
?.getQuietly<Context>()?.also { context ->
NotificationEntryClass.resolve().optional().firstMethodOrNull {
name = "getSbn"
}?.of(args().first().any())?.invokeQuietly<StatusBarNotification>()?.also { nf ->
nf.notification.smallIcon.loadDrawable(context)?.also { iconDrawable ->
compatStatusIcon(
context = context,
nf = nf,
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable).also {
/** 缓存第一次的 APP 小图标 */
if (it.not()) context.appIconOf(nf.packageName)?.also { e -> appIcons[nf.packageName] = e }
},
packageName = nf.packageName,
drawable = iconDrawable
).also { pair ->
if (pair.second) StatusBarIconClass.resolve().optional().firstFieldOrNull {
name = "icon"
type = Icon::class
}?.of(result)?.set(Icon.createWithBitmap(pair.first.toBitmap()))
}
}
}
}
afterHook {
IconBuilderClass.toClass().field { name = "context" }
.get(field { name = "iconBuilder" }.get(instance).cast()).cast<Context>()?.also { context ->
NotificationEntryClass.toClass().method {
}
/** 得到状态栏图标实例 */
StatusBarIconViewClass.resolve().optional().firstMethodOrNull {
name = "setNotification"
parameters(StatusBarNotification::class)
}?.hook()?.after {
/** 注册壁纸颜色监听 */
if (args().first().any() != null) instance<ImageView>().also { registerWallpaperColorChanged(it) }
}
/** 注入通知控制器实例 */
StatusBarNotificationPresenterClass.resolve().optional().constructor {}.hookAll().after { notificationPresenter = instance }
/** 注入状态栏通知图标容器实例 */
OplusNotificationIconAreaControllerClass.resolve().optional().apply {
var way = 0
(firstMethodOrNull {
name = "updateIconsForLayout"
parameterCount = 10
} ?: firstMethodOrNull {
/** ColorOS 14 */
name = "updateIconsForLayout"
parameterCount = 5
} ?: firstMethodOrNull {
name = "updateIconsForLayout"
parameterCount = 1
}?.apply { way = 1 }
?: firstMethodOrNull {
name = "updateIconsForLayout"
}?.apply { way = 2 })?.hook()?.after {
when (way) {
2 -> notificationIconContainer = OplusNotificationIconAreaControllerClass.resolve().optional()
.firstMethodOrNull { name = "getNotificationIcons" }
?.of(instance)?.invoke<ViewGroup>()
1 -> {
notificationIconInstances.clear()
firstFieldOrNull { name = "mLastToShow" }?.of(instance)?.get<List<View>>()
?.takeIf { it.isNotEmpty() }?.forEach { notificationIconInstances.add(it) }
}
else -> notificationIconContainer = args(index = 1).cast()
}
}
}
/** 注入状态栏通知图标容器实例 */
(LegacyNotificationIconAreaControllerImpl ?: NotificationIconAreaControllerClass)
.resolve().optional().apply {
firstMethodOrNull {
name = "updateIconsForLayout"
parameterCount = 8
}?.hook()?.after {
notificationIconContainer = args(index = 1).cast()
}
}
/** 替换通知面板背景 - 新版本 */
if (!isOldNotificationBackground)
OplusNotificationBackgroundViewClass?.resolve()?.optional()?.apply {
firstMethodOrNull {
name { it == "drawRegionBlur" || it == "draw" }
parameterCount = 2
superclass()
}?.hook()?.before { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}
/** 替换通知面板背景 - 旧版本 */
if (isOldNotificationBackground)
NotificationBackgroundViewClass?.resolve()?.optional(silent = true)?.apply {
firstMethodOrNull {
name = "draw"
parameterCount = 2
}?.hook()?.before { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
firstMethodOrNull {
name = "drawCustom"
parameterCount = 2
}?.hook()?.before { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}
/** 替换通知面板背景 - 避免折叠展开通知二次修改通知面板背景 */
ExpandableNotificationRowClass.resolve().optional().apply {
firstMethodOrNull {
name = "updateBackgroundForGroupState"
emptyParameters()
}?.hook()?.before {
if (ConfigData.isEnableNotifyPanelAlpha)
firstFieldOrNull { name = "mShowGroupBackgroundWhenExpanded" }?.of(instance)?.set(true)
}
}
/** 替换媒体通知面板背景 - 设置媒体通知自动展开 */
OplusMediaControlPanelClass?.resolve()?.optional()?.apply {
firstMethodOrNull {
name = "bind"
parameterCount = 2
}?.hook()?.after {
/** 得到当前实例 */
val holder = OplusMediaControlPanelClass?.resolve()?.optional()?.firstFieldOrNull {
name = "mViewHolder"
superclass()
}?.of(instance)?.get()
/** 记录媒体通知 [View] */
notificationPlayerView = PlayerViewHolderClass?.resolve()?.optional()?.firstMethodOrNull {
name = "getPlayer"
emptyParameters()
}?.of(holder)?.invokeQuietly<View>()
/** 设置背景着色 */
modifyNotifyPanelAlpha(notificationPlayerView, isTint = true)
/** 当前是否正在播放 */
val isPlaying = MediaDataClass?.resolve()?.optional()?.firstMethodOrNull {
name = "isPlaying"
emptyParameters()
}?.of(args().first().any())?.invokeQuietly<Boolean>() ?: false
/** 当前通知是否展开 */
val isExpanded = OplusMediaViewControllerClass?.resolve()?.optional()?.firstMethodOrNull {
name = "getExpanded"
emptyParameters()
}?.of(firstFieldOrNull { name = "mOplusMediaViewController" }?.of(instance)?.get())?.invokeQuietly<Boolean>() ?: false
/** 符合条件后执行 */
if (ConfigData.isEnableNotifyMediaPanelAutoExp.not() || isExpanded || isPlaying.not()) return@after
/** 模拟手动展开通知 */
BasePlayViewHolderClass?.resolve()?.optional()?.firstMethodOrNull {
name = "getExpandButton"
emptyParameters()
}?.of(holder)?.invokeQuietly<View>()?.performClick()
}
}
/** 替换通知图标和样式 */
NotificationHeaderViewWrapperClass.resolve().optional().apply {
method {
name { it == "resolveHeaderViews" || it == "onContentUpdated" }
}.hookAll().after {
firstFieldOrNull { name = "mIcon" }?.of(instance)?.get<ImageView>()?.apply {
ExpandableNotificationRowClass.resolve().optional()
.firstMethodOrNull { name = "getEntry" }
?.of(NotificationViewWrapperClass.resolve().optional().firstFieldOrNull {
name = "mRow"
}?.of(instance)?.get())?.invokeQuietly()?.let {
it.asResolver().optional().firstMethodOrNull {
name = "getSbn"
}.get(args().first().any()).invoke<StatusBarNotification>()?.also { nf ->
nf.notification.smallIcon.loadDrawable(context)?.also { iconDrawable ->
compatStatusIcon(
context = context,
nf = nf,
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable).also {
/** 缓存第一次的 APP 小图标 */
if (it.not()) context.appIconOf(nf.packageName)?.also { e -> appIcons[nf.packageName] = e }
},
packageName = nf.packageName,
drawable = iconDrawable
).also { pair ->
if (pair.second) StatusBarIconClass.toClass().field {
name = "icon"
type = IconClass
}.get(result).set(Icon.createWithBitmap(pair.first.toBitmap()))
}?.invoke<StatusBarNotification>()
}.also { nf ->
nf?.notification?.also {
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
/** 执行替换 */
fun doParse() {
compatNotifyIcon(
context = context,
nf = nf,
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
packageName = context.packageName,
drawable = iconDrawable,
iconColor = it.color,
iconView = this
)
}
doParse()
/** 延迟重新设置防止部分机型的系统重新设置图标出现图标着色后黑白块问题 */
delayedRun(ms = 1500) { doParse() }
}
}
}
}
}
}
/** 得到状态栏图标实例 */
StatusBarIconViewClass.hook {
injectMember {
method {
name = "setNotification"
param(StatusBarNotificationClass)
}
afterHook {
/** 注册壁纸颜色监听 */
if (args().first().any() != null) instance<ImageView>().also { registerWallpaperColorChanged(it) }
}
}
}
/** 注入通知控制器实例 */
StatusBarNotificationPresenterClass.hook {
injectMember {
allMembers(MembersType.CONSTRUCTOR)
afterHook { notificationPresenter = instance }
}
}
/** 注入状态栏通知图标容器实例 */
OplusNotificationIconAreaControllerClass.hook {
injectMember {
var isOldWay = false
method {
name = "updateIconsForLayout"
paramCount = 10
}.remedys {
method {
name = "updateIconsForLayout"
paramCount = 1
}.onFind { isOldWay = true }
}
afterHook {
if (isOldWay) {
notificationIconInstances.clear()
field { name = "mLastToShow" }.get(instance).list<View>()
.takeIf { it.isNotEmpty() }?.forEach { notificationIconInstances.add(it) }
} else notificationIconContainer = args(index = 1).cast()
}
}
}
/** 替换通知面板背景 - 新版本 */
OplusNotificationBackgroundViewClass.hook {
injectMember {
method {
name = "drawRegionBlur"
paramCount = 2
}.remedys {
method {
name = "draw"
paramCount = 2
}
}
beforeHook { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}
injectMember {
method {
name = "draw"
paramCount = 2
superClass(isOnlySuperClass = true)
}
beforeHook { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}
}.ignoredHookClassNotFoundFailure().by { isOldNotificationBackground.not() }
/** 替换通知面板背景 - 旧版本 */
NotificationBackgroundViewClass.hook {
injectMember {
method {
name = "draw"
paramCount = 2
}
beforeHook { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}
injectMember {
method {
name = "drawCustom"
paramCount = 2
}
beforeHook { modifyNotifyPanelAlpha(instance(), args().last().cast<Drawable>()) }
}.ignoredNoSuchMemberFailure()
}.by { isOldNotificationBackground }
/** 替换通知面板背景 - 避免折叠展开通知二次修改通知面板背景 */
ExpandableNotificationRowClass.hook {
injectMember {
method {
name = "updateBackgroundForGroupState"
emptyParam()
}
beforeHook {
if (ConfigData.isEnableNotifyPanelAlpha) field { name = "mShowGroupBackgroundWhenExpanded" }.get(instance).setTrue()
}
}
}
/** 替换媒体通知面板背景 - 设置媒体通知自动展开 */
OplusMediaControlPanelClass.hook {
injectMember {
method {
name = "bind"
paramCount = 2
}
afterHook {
/** 得到当前实例 */
val holder = field {
name = "mViewHolder"
superClass(isOnlySuperClass = true)
}.get(instance).any()
/** 记录媒体通知 [View] */
notificationPlayerView = PlayerViewHolderClass.toClassOrNull()?.method {
name = "getPlayer"
emptyParam()
}?.get(holder)?.invoke()
/** 设置背景着色 */
modifyNotifyPanelAlpha(notificationPlayerView, isTint = true)
/** 当前是否正在播放 */
val isPlaying = MediaDataClass.toClassOrNull()?.method {
name = "isPlaying"
emptyParam()
}?.get(args().first().any())?.boolean() ?: false
/** 当前通知是否展开 */
val isExpanded = OplusMediaViewControllerClass.toClassOrNull()?.method {
name = "getExpanded"
emptyParam()
}?.get(field { name = "mOplusMediaViewController" }.get(instance).any())?.boolean() ?: false
/** 符合条件后执行 */
if (ConfigData.isEnableNotifyMediaPanelAutoExp.not() || isExpanded || isPlaying.not()) return@afterHook
/** 模拟手动展开通知 */
BasePlayViewHolderClass.toClassOrNull()?.method {
name = "getExpandButton"
emptyParam()
}?.get(holder)?.invoke<View>()?.performClick()
}
}
}.ignoredHookClassNotFoundFailure()
/** 替换通知图标和样式 */
NotificationHeaderViewWrapperClass.hook {
injectMember {
method { name { it == "resolveHeaderViews" || it == "onContentUpdated" } }.all()
afterHook {
NotificationHeaderViewWrapperClass.toClass()
.field { name = "mIcon" }.get(instance).cast<ImageView>()?.apply {
ExpandableNotificationRowClass.toClass()
.method { name = "getEntry" }
.get(NotificationViewWrapperClass.toClass().field {
name = "mRow"
}.get(instance).any()).call()?.let {
it.javaClass.method {
name = "getSbn"
}.get(it).invoke<StatusBarNotification>()
}.also { nf ->
nf?.notification?.also {
it.smallIcon.loadDrawable(context)?.also { iconDrawable ->
/** 执行替换 */
fun doParse() {
compatNotifyIcon(
context = context,
nf = nf,
isGrayscaleIcon = isGrayscaleIcon(context, iconDrawable),
packageName = context.packageName,
drawable = iconDrawable,
iconColor = it.color,
iconView = this
)
}
doParse()
/** 延迟重新设置防止部分机型的系统重新设置图标出现图标着色后黑白块问题 */
delayedRun(ms = 1500) { doParse() }
}
}
}
}
}
}
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/24.
* This file is created by fankes on 2022/1/24.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
@@ -28,7 +28,11 @@ import android.content.Context
import android.graphics.Color
import com.fankes.coloros.notify.bean.IconDataBean
import com.fankes.coloros.notify.data.ConfigData
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.bitmap
import com.fankes.coloros.notify.utils.factory.safeOf
import com.fankes.coloros.notify.utils.factory.safeOfNan
import com.fankes.coloros.notify.utils.factory.safeOfNull
import com.fankes.coloros.notify.utils.factory.snake
import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.param.PackageParam
import org.json.JSONArray
@@ -135,4 +139,4 @@ class IconPackParams(private val context: Context? = null, private val param: Pa
* @param dataJson 图标数据 JSON
*/
fun save(dataJson: String) = context?.prefs()?.edit { put(ConfigData.NOTIFY_ICONS_DATA, dataJson) }
}
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/2/15.
* This file is created by fankes on 2022/2/15.
* This file is Modified by fankes on 2023/2/3.
*/
package com.fankes.coloros.notify.param.factory

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/26.
* This file is created by fankes on 2022/3/26.
*/
package com.fankes.coloros.notify.service

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/30.
* This file is created by fankes on 2022/1/30.
*/
@file:Suppress("SetTextI18n", "InflateParams")
@@ -37,7 +37,16 @@ import com.fankes.coloros.notify.param.factory.isAppNotifyHookOf
import com.fankes.coloros.notify.param.factory.putAppNotifyHookAllOf
import com.fankes.coloros.notify.param.factory.putAppNotifyHookOf
import com.fankes.coloros.notify.ui.activity.base.BaseActivity
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.addOnBackPressedEvent
import com.fankes.coloros.notify.utils.factory.bindAdapter
import com.fankes.coloros.notify.utils.factory.callOnBackPressed
import com.fankes.coloros.notify.utils.factory.colorOf
import com.fankes.coloros.notify.utils.factory.copyToClipboard
import com.fankes.coloros.notify.utils.factory.navigate
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.showDialog
import com.fankes.coloros.notify.utils.factory.snake
import com.fankes.coloros.notify.utils.factory.toast
import com.fankes.coloros.notify.utils.tool.IconRuleManagerTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.YukiHookAPI
@@ -145,8 +154,8 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
if (b) showDialog {
title = "全部替换"
msg = "此功能仅针对严重不遵守规范的 APP 通知图标才需要开启例如APP 推送通知后无法识别出现的黑白块图标。\n\n" +
"此功能在一般情况下请保持关闭并跟随在线规则的配置,并不要随意改变此配置," +
"开启后 APP 的通知图标可能会被规则破坏,你确定还要开启吗?"
"此功能在一般情况下请保持关闭并跟随在线规则的配置,并不要随意改变此配置," +
"开启后 APP 的通知图标可能会被规则破坏,你确定还要开启吗?"
confirmButton { saveState() }
cancelButton { btn.isChecked = btn.isChecked.not() }
noCancelable()
@@ -188,10 +197,10 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
val pkgName = intent?.getStringExtra("pkgName") ?: ""
title = "新安装应用通知图标适配"
msg = "你已安装 $appName($pkgName)\n\n" +
"此应用未在通知优化名单中发现适配数据,若此应用发送的通知为彩色图标," +
"可随时点击本页面下方的“贡献通知图标优化名单”按钮提交贡献或请求适配。\n\n" +
"若你已知晓此应用会遵守原生通知图标规范,可忽略此提示。\n\n" +
"你可以现在立即同步适配列表,以获取最新的适配数据。"
"此应用未在通知优化名单中发现适配数据,若此应用发送的通知为彩色图标," +
"可随时点击本页面下方的“贡献通知图标优化名单”按钮提交贡献或请求适配。\n\n" +
"若你已知晓此应用会遵守原生通知图标规范,可忽略此提示。\n\n" +
"你可以现在立即同步适配列表,以获取最新的适配数据。"
confirmButton(text = "同步列表") { onStartRefresh() }
cancelButton(text = "复制名称+包名") { copyToClipboard(content = "$appName($pkgName)") }
neutralButton(text = "取消")
@@ -250,7 +259,7 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
onChanged?.invoke()
binding.configTitleCountText.text =
if (filterText.isBlank()) "已适配 ${iconDatas.size} 个 APP 的通知图标"
else "${filterText}” 匹配到 ${iconDatas.size} 个结果"
else "$filterText” 匹配到 ${iconDatas.size} 个结果"
binding.configListNoDataView.apply {
text = if (iconAllDatas.isEmpty()) "噫,竟然什么都没有~\n请点击右上角同步按钮获取云端数据" else "噫,竟然什么都没找到~"
isVisible = iconDatas.isEmpty()

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,25 +18,36 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/2/26.
* This file is created by fankes on 2022/2/26.
*/
@file:Suppress("SetTextI18n")
package com.fankes.coloros.notify.ui.activity
import androidx.core.view.isVisible
import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.const.ModuleVersion
import com.fankes.coloros.notify.data.ConfigData
import com.fankes.coloros.notify.data.factory.bind
import com.fankes.coloros.notify.databinding.ActivityMainBinding
import com.fankes.coloros.notify.param.IconPackParams
import com.fankes.coloros.notify.ui.activity.base.BaseActivity
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.androidVersionCodeName
import com.fankes.coloros.notify.utils.factory.colorOSFullVersion
import com.fankes.coloros.notify.utils.factory.colorOSNumberVersion
import com.fankes.coloros.notify.utils.factory.hideOrShowLauncherIcon
import com.fankes.coloros.notify.utils.factory.isLauncherIconShowing
import com.fankes.coloros.notify.utils.factory.isNotColorOS
import com.fankes.coloros.notify.utils.factory.isNotNoificationEnabled
import com.fankes.coloros.notify.utils.factory.navigate
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.openNotifySetting
import com.fankes.coloros.notify.utils.factory.showDialog
import com.fankes.coloros.notify.utils.factory.showTimePicker
import com.fankes.coloros.notify.utils.tool.GithubReleaseTool
import com.fankes.coloros.notify.utils.tool.I18nWarnTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.fankes.coloros.notify.utils.tool.YukiPromoteTool
import com.fankes.projectpromote.ProjectPromote
import com.highcapable.yukihookapi.YukiHookAPI
class MainActivity : BaseActivity<ActivityMainBinding>() {
@@ -51,19 +62,13 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/** 模块是否有效 */
internal var isModuleValied = false
/** 模块版本 */
private const val moduleVersion = BuildConfig.VERSION_NAME
/** 预发布的版本标识 */
private const val pendingFlag = ""
}
override fun onCreate() {
/** 设置可用性 */
isActivityLive = true
/** 检查更新 */
GithubReleaseTool.checkingForUpdate(context = this, moduleVersion) { version, function ->
GithubReleaseTool.checkingForUpdate(context = this, ModuleVersion.NAME) { version, function ->
binding.mainTextReleaseVersion.apply {
text = "点击更新 $version"
isVisible = true
@@ -89,7 +94,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
showDialog {
title = "配置通知图标优化名单"
msg = "模块需要获取在线规则以更新“通知图标优化名单”,它现在是空的,这看起来是你第一次使用模块,请首先进行配置才可以使用相关功能。\n" +
"你可以随时在本页面下方找到“配置通知图标优化名单”手动前往。"
"你可以随时在本页面下方找到“配置通知图标优化名单”手动前往。"
confirmButton(text = "前往") { navigate<ConfigureActivity>() }
cancelButton()
noCancelable()
@@ -103,29 +108,47 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
noCancelable()
}
/** 推广、恰饭 */
YukiPromoteTool.promote(context = this)
ProjectPromote.show(activity = this, ModuleVersion.toString())
}
else ->
showDialog {
title = "模块没有激活"
msg = "检测到模块没有激活,模块需要 Xposed 环境依赖," +
"同时需要系统拥有 Root 权限," +
"请自行查看本页面使用帮助与说明第二条。\n" +
"由于需要修改系统应用达到效果,模块不支持太极阴、应用转生。"
"同时需要系统拥有 Root 权限," +
"请自行查看本页面使用帮助与说明第二条。\n" +
"由于需要修改系统应用达到效果,模块不支持太极阴、应用转生。"
confirmButton(text = "我知道了")
noCancelable()
}
}
I18nWarnTool.checkingOrShowing(context = this)
binding.mainTextVersion.text = "模块版本:$moduleVersion $pendingFlag"
binding.mainTextVersion.text = "模块版本:${ModuleVersion.NAME}"
/** 设置 CI 自动构建标识 */
if (ModuleVersion.isCiMode)
binding.mainTextReleaseVersion.apply {
text = "CI ${ModuleVersion.GITHUB_COMMIT_ID}"
isVisible = true
setOnClickListener {
showDialog {
title = "CI 自动构建说明"
msg = """
你正在使用的是 CI 自动构建版本Commit ID 为 ${ModuleVersion.GITHUB_COMMIT_ID}
它是由代码提交后自动触发并构建、自动编译发布的,并未经任何稳定性测试,使用风险自负。
""".trimIndent()
confirmButton(text = "我知道了")
noCancelable()
}
}
}
binding.mainTextColorOsVersion.text = "系统版本:[$androidVersionCodeName] $colorOSFullVersion"
/** 媒体通知自动展开仅支持 12.1 - 旧版本适配过于复杂已放弃 */
if (colorOSNumberVersion != "V12.1") {
binding.notifyMediaPanelAutoExpSwitch.isVisible = false
binding.notifyMediaPanelAutoExpText.isVisible = false
}
/** 通知面板背景透明度功能仅支持 ColorOS 12、12.1、13 */
binding.notifyPanelConfigItem.isVisible = colorOSNumberVersion.let { it == "V12" || it == "V12.1" || it == "V13" }
/** 通知面板背景透明度功能仅支持 ColorOS 12、12.1、13、13.1 */
binding.notifyPanelConfigItem.isVisible = colorOSNumberVersion.let { it == "V12" || it == "V12.1" || it == "V13" || it == "V13.1" }
binding.notifyIconAutoSyncText.text = ConfigData.notifyIconFixAutoTime
binding.moduleEnableSwitch.bind(ConfigData.ENABLE_MODULE) {
onInitialize {
@@ -168,8 +191,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (it) showDialog {
title = "启用兼容模式"
msg = "启用兼容模式可修复部分系统版本可能出现无法判定通知图标反色的问题," +
"但是这也可能会导致新的问题,一般情况下不建议开启,确定要继续吗?\n\n" +
"如果系统界面刷新后通知图标颜色发生错误,请尝试重启一次系统界面。"
"但是这也可能会导致新的问题,一般情况下不建议开启,确定要继续吗?\n\n" +
"如果系统界面刷新后通知图标颜色发生错误,请尝试重启一次系统界面。"
confirmButton { applyChangesAndRefresh() }
cancelButton { cancelChanges() }
noCancelable()
@@ -194,7 +217,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (it) showDialog {
title = "破坏性功能警告"
msg = "开启这个功能后,任何通知栏中的通知图标都会忽略图标自身的着色属性,全部使用系统默认颜色 (系统提供的统一色调) 着色。\n\n" +
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
confirmButton { applyChangesAndRefresh() }
cancelButton { cancelChanges() }
noCancelable()
@@ -216,8 +239,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (it) showDialog {
title = "破坏性功能警告"
msg = "开启这个功能后,任何通知栏中的通知图标都会被强制替换为当前推送通知的 APP 的图标," +
"某些系统级别的 APP 通知图标可能会显示异常或发生图标丢失。\n\n" +
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
"某些系统级别的 APP 通知图标可能会显示异常或发生图标丢失。\n\n" +
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
confirmButton { applyChangesAndRefresh() }
cancelButton { cancelChanges() }
noCancelable()
@@ -261,9 +284,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (it) showDialog {
title = "注意"
msg = "开启这个功能后,当发现未适配的彩色通知图标时," +
"状态栏中显示的通知图标将会使用预置的占位符图标进行修补," +
"通知栏中显示的通知图标保持原始图标不变。\n\n" +
"此功能的作用仅为临时修复破坏规范的通知图标,仍然继续开启吗?"
"状态栏中显示的通知图标将会使用预置的占位符图标进行修补," +
"通知栏中显示的通知图标保持原始图标不变。\n\n" +
"此功能的作用仅为临时修复破坏规范的通知图标,仍然继续开启吗?"
confirmButton { applyChangesAndRefresh() }
cancelButton { cancelChanges() }
noCancelable()
@@ -296,11 +319,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
showDialog {
title = "每天 $it 自动更新"
msg = "设置保存后将在每天 $it 自动同步名单到最新云端数据,若数据已是最新则不会显示任何提示,否则会发送一条通知。\n\n" +
"请确保:\n\n" +
"1.模块没有被禁止前台以及后台联网权限\n" +
"2.模块没有被禁止被其它 APP 关联唤醒\n" +
"3.模块的系统通知权限已开启\n\n" +
"模块无需保持在后台运行,到达同步时间后会自动启动,如果到达时间后模块正在运行则会自动取消本次计划任务。"
"请确保:\n\n" +
"1.模块没有被禁止前台以及后台联网权限\n" +
"2.模块没有被禁止被其它 APP 关联唤醒\n" +
"3.模块的系统通知权限已开启\n\n" +
"模块无需保持在后台运行,到达同步时间后会自动启动,如果到达时间后模块正在运行则会自动取消本次计划任务。"
confirmButton(text = "保存设置") {
ConfigData.notifyIconFixAutoTime = it
this@MainActivity.binding.notifyIconAutoSyncText.text = it
@@ -334,7 +357,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.mainLinStatus.setBackgroundResource(
when {
YukiHookAPI.Status.isXposedModuleActive &&
(isModuleRegular.not() || isModuleValied.not() || ConfigData.isEnableModule.not()) -> R.drawable.bg_yellow_round
(isModuleRegular.not() || isModuleValied.not() || ConfigData.isEnableModule.not()) -> R.drawable.bg_yellow_round
YukiHookAPI.Status.isXposedModuleActive -> R.drawable.bg_green_round
else -> R.drawable.bg_dark_round
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/26.
* This file is created by fankes on 2022/3/26.
*/
@file:Suppress("DEPRECATION")

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,22 +18,22 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/30.
* This file is created by fankes on 2022/1/30.
*/
@file:Suppress("UNCHECKED_CAST")
package com.fankes.coloros.notify.ui.activity.base
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.WindowCompat
import androidx.viewbinding.ViewBinding
import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.utils.factory.isNotSystemInDarkMode
import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.kavaref.extension.genericSuperclassTypeArguments
import com.highcapable.kavaref.extension.toClassOrNull
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
@@ -49,10 +49,12 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
isMainThreadRunning = true
binding = current().generic()?.argument()?.method {
val bindingClass = javaClass.genericSuperclassTypeArguments().firstOrNull()?.toClassOrNull()
binding = bindingClass?.resolve()?.optional()?.firstMethodOrNull {
name = "inflate"
param(LayoutInflaterClass)
}?.get()?.invoke<VB>(layoutInflater) ?: error("binding failed")
parameters(LayoutInflater::class)
}?.invoke<VB>(layoutInflater) ?: error("binding failed")
if (Build.VERSION.SDK_INT >= 35) binding.root.fitsSystemWindows = true
setContentView(binding.root)
/** 隐藏系统的标题栏 */
supportActionBar?.hide()
@@ -61,6 +63,7 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
isAppearanceLightStatusBars = isNotSystemInDarkMode
isAppearanceLightNavigationBars = isNotSystemInDarkMode
}
@Suppress("DEPRECATION")
ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
window?.statusBarColor = it
window?.navigationBarColor = it

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/8.
* This file is created by fankes on 2022/1/8.
*/
@file:Suppress("SameParameterValue")

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/10/6.
* This file is created by fankes on 2022/10/6.
*/
package com.fankes.coloros.notify.utils.factory

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,8 +18,10 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/6/3.
* This file is created by fankes on 2022/6/3.
*/
@file:Suppress("DEPRECATION")
package com.fankes.coloros.notify.utils.factory
import android.content.Context

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,9 +18,9 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/7.
* This file is created by fankes on 2022/1/7.
*/
@file:Suppress("unused", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE")
@file:Suppress("unused", "DEPRECATION")
package com.fankes.coloros.notify.utils.factory
@@ -38,7 +38,6 @@ import androidx.viewbinding.ViewBinding
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.progressindicator.CircularProgressIndicator
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.annotation.CauseProblemsApi
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
@@ -181,7 +180,6 @@ class DialogBuilder<VB : ViewBinding>(val context: Context, private val bindingC
fun cancel() = dialogInstance?.cancel()
/** 显示对话框 */
@CauseProblemsApi
fun show() = runInSafe {
/** 若当前自定义 View 的对话框没有调用 [binding] 将会对其手动调用一次以确保显示布局 */
if (bindingClass != null) binding

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,13 +18,13 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/13.
* This file is created by fankes on 2022/3/13.
*/
@file:Suppress("unused")
package com.fankes.coloros.notify.utils.factory
import com.highcapable.yukihookapi.hook.log.loggerE
import com.highcapable.yukihookapi.hook.log.YLog
/**
* 忽略异常返回值
@@ -79,5 +79,5 @@ inline fun <T> safeOf(default: T, result: () -> T) = try {
* @param block 正常回调
*/
inline fun <T> T.runInSafe(msg: String = "", block: () -> Unit) {
runCatching(block).onFailure { if (msg.isNotBlank()) loggerE(msg = msg, e = it) }
runCatching(block).onFailure { if (msg.isNotBlank()) YLog.error(msg, it) }
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,9 +18,9 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/1/7.
* This file is created by fankes on 2022/1/7.
*/
@file:Suppress("unused", "ObsoleteSdkInt")
@file:Suppress("unused", "ObsoleteSdkInt", "DEPRECATION")
package com.fankes.coloros.notify.utils.factory
@@ -28,7 +28,11 @@ import android.app.Activity
import android.app.Notification
import android.app.Service
import android.app.WallpaperManager
import android.content.*
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
@@ -52,18 +56,22 @@ import androidx.core.app.NotificationManagerCompat
import androidx.core.content.getSystemService
import androidx.core.content.pm.PackageInfoCompat
import androidx.core.content.res.ResourcesCompat
import com.fankes.coloros.notify.BuildConfig
import androidx.core.net.toUri
import com.fankes.coloros.notify.wrapper.BuildConfigWrapper
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.factory.field
import com.highcapable.yukihookapi.hook.factory.hasClass
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.factory.toClassOrNull
import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.type.java.StringClass
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
import com.topjohnwu.superuser.Shell
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
import java.util.*
import java.util.Calendar
import java.util.Date
import java.util.Locale
/**
* 系统深色模式是否开启
@@ -126,7 +134,7 @@ inline val isNotColorOS get() = !isColorOS
val isRealmeUI
get() = safeOfFalse {
val query = appContext.contentResolver.query(
Uri.parse("content://com.oplus.customize.coreapp.configmanager.configprovider.AppFeatureProvider")
"content://com.oplus.customize.coreapp.configmanager.configprovider.AppFeatureProvider".toUri()
.buildUpon()
.appendPath("app_feature")
.build(), null, "featurename=?", arrayOf("com.android.launcher.device_rm"), null
@@ -142,6 +150,7 @@ val isRealmeUI
*/
val androidVersionCodeName
get() = when (Build.VERSION.SDK_INT) {
34 -> "U"
33 -> "T"
32 -> "S_V2"
31 -> "S"
@@ -155,7 +164,7 @@ val androidVersionCodeName
23 -> "M"
22 -> "L_MR1"
21 -> "L"
else -> ""
else -> "?"
}
/**
@@ -203,7 +212,7 @@ fun Resources.colorOf(@ColorRes resId: Int) = ResourcesCompat.getColor(this, res
* @return [PackageInfo] or null
*/
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
@Suppress("DEPRECATION")
@Suppress("DEPRECATION", "KotlinRedundantDiagnosticSuppress")
if (Build.VERSION.SDK_INT >= 33)
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
else packageManager?.getPackageInfo(packageName, flag.toInt())
@@ -416,7 +425,10 @@ fun findPropString(key: String, default: String = "") = safeOf(default) {
* 是否有 Root 权限
* @return [Boolean]
*/
val isRootAccess get() = safeOfFalse { Shell.rootAccess() }
val isRootAccess get() = safeOfFalse {
@Suppress("DEPRECATION")
Shell.rootAccess()
}
/**
* 执行命令
@@ -425,6 +437,7 @@ val isRootAccess get() = safeOfFalse { Shell.rootAccess() }
* @return [String] 执行结果
*/
fun execShell(cmd: String, isSu: Boolean = true) = safeOfNothing {
@Suppress("DEPRECATION")
(if (isSu) Shell.su(cmd) else Shell.sh(cmd)).exec().out.let {
if (it.isNotEmpty()) it[0].trim() else ""
}
@@ -434,7 +447,11 @@ fun execShell(cmd: String, isSu: Boolean = true) = safeOfNothing {
* 弹出 [Toast]
* @param msg 提示内容
*/
fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).show()
fun toast(msg: String) {
runCatching {
Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).show()
}.onFailure { YLog.warn(msg) }
}
/**
* 跳转到指定页面
@@ -469,7 +486,7 @@ fun Context.openBrowser(url: String, packageName: String = "") = runCatching {
startActivity(Intent().apply {
if (packageName.isNotBlank()) setPackage(packageName)
action = Intent.ACTION_VIEW
data = Uri.parse(url)
data = url.toUri()
/** 防止顶栈一样重叠在自己的 APP 中 */
flags = Intent.FLAG_ACTIVITY_NEW_TASK
})
@@ -541,7 +558,7 @@ fun Any?.delayedRun(ms: Long = 150, it: () -> Unit) = runInSafe {
*/
fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
packageManager?.setComponentEnabledSetting(
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home"),
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home"),
if (isShow) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
@@ -553,5 +570,5 @@ fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
*/
val Context.isLauncherIconShowing
get() = packageManager?.getComponentEnabledSetting(
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home")
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home")
) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/4/17.
* This file is created by fankes on 2023/4/17.
*/
package com.fankes.coloros.notify.utils.tool
@@ -32,9 +32,9 @@ import android.content.Intent
import android.graphics.drawable.Icon
import android.os.Build
import androidx.core.graphics.drawable.toBitmap
import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.utils.factory.appIconOf
import com.fankes.coloros.notify.wrapper.BuildConfigWrapper
/**
* 模块更新激活提醒通知工具类
@@ -42,7 +42,7 @@ import com.fankes.coloros.notify.utils.factory.appIconOf
object ActivationPromptTool {
/** 当前模块的包名 */
private const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
private const val MODULE_PACKAGE_NAME = BuildConfigWrapper.APPLICATION_ID
/** 推送通知的渠道名称 */
private const val NOTIFY_CHANNEL = "activationPromptId"
@@ -53,7 +53,7 @@ object ActivationPromptTool {
* @param packageName 当前 APP 包名
*/
fun prompt(context: Context, packageName: String) {
if (packageName != BuildConfig.APPLICATION_ID) return
if (packageName != BuildConfigWrapper.APPLICATION_ID) return
context.getSystemService(NotificationManager::class.java)?.apply {
createNotificationChannel(
NotificationChannel(
@@ -73,7 +73,7 @@ object ActivationPromptTool {
PendingIntent.getActivity(
context, packageName.hashCode(),
Intent().apply {
component = ComponentName(MODULE_PACKAGE_NAME, "${MODULE_PACKAGE_NAME}.ui.activity.MainActivity")
component = ComponentName(MODULE_PACKAGE_NAME, "$MODULE_PACKAGE_NAME.ui.activity.MainActivity")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}, if (Build.VERSION.SDK_INT < 31) PendingIntent.FLAG_UPDATE_CURRENT else PendingIntent.FLAG_IMMUTABLE
)

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,11 +18,15 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/1/28.
* This file is created by fankes on 2023/1/28.
*/
package com.fankes.coloros.notify.utils.tool
import android.graphics.*
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.drawable.AnimationDrawable
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/20.
* This file is created by fankes on 2022/3/20.
*/
package com.fankes.coloros.notify.utils.tool
@@ -27,12 +27,20 @@ import android.content.Context
import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar
import android.icu.util.TimeZone
import com.fankes.coloros.notify.utils.factory.*
import okhttp3.*
import com.fankes.coloros.notify.utils.factory.isNetWorkSuccess
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.openSelfSetting
import com.fankes.coloros.notify.utils.factory.runInSafe
import com.fankes.coloros.notify.utils.factory.showDialog
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.json.JSONObject
import java.io.IOException
import java.io.Serializable
import java.util.*
import java.util.Locale
/**
* 获取 GitHub Release 最新版本工具类
@@ -71,7 +79,7 @@ object GithubReleaseTool {
fun showUpdate() = context.showDialog {
title = "最新版本 $name"
msg = "发布于 $date\n\n" +
"更新日志\n\n" + content
"更新日志\n\n" + content
confirmButton(text = "更新") { context.openBrowser(htmlUrl) }
cancelButton()
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2023/2/3.
* This file is created by fankes on 2023/2/3.
*/
package com.fankes.coloros.notify.utils.tool
@@ -26,7 +26,7 @@ import android.content.Context
import com.fankes.coloros.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
import java.util.*
import java.util.Locale
/**
* I18n 适配警告提示工具类
@@ -46,8 +46,8 @@ object I18nWarnTool {
context.showDialog {
title = "Notice of I18n Support"
msg = "This Xposed Module is only for Chinese and the Chinese region.\n\n" +
"Currently, there will be no internationalization adaptation.\n\n" +
"There may be plans for internationalization adaptation in the future, so stay tuned."
"Currently, there will be no internationalization adaptation.\n\n" +
"There may be plans for internationalization adaptation in the future, so stay tuned."
confirmButton(text = "Got It") { saveReaded() }
noCancelable()
}

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/3/20.
* This file is created by fankes on 2022/3/20.
*/
package com.fankes.coloros.notify.utils.tool
@@ -32,10 +32,15 @@ import android.content.Intent
import android.graphics.drawable.Icon
import android.os.Build
import androidx.core.graphics.drawable.toBitmap
import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.R
import com.fankes.coloros.notify.hook.HookEntry
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.appIconOf
import com.fankes.coloros.notify.utils.factory.appNameOf
import com.fankes.coloros.notify.utils.factory.isDebugApp
import com.fankes.coloros.notify.utils.factory.isSystemApp
import com.fankes.coloros.notify.utils.factory.runInSafe
import com.fankes.coloros.notify.utils.factory.stampToDate
import com.fankes.coloros.notify.wrapper.BuildConfigWrapper
/**
* 通知图标适配推送通知类
@@ -45,7 +50,7 @@ import com.fankes.coloros.notify.utils.factory.*
object IconAdaptationTool {
/** 当前模块的包名 */
private const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
private const val MODULE_PACKAGE_NAME = BuildConfigWrapper.APPLICATION_ID
/** 推送通知的渠道名称 */
private const val NOTIFY_CHANNEL = "notifyRuleSupportId"
@@ -82,7 +87,7 @@ object IconAdaptationTool {
Intent().apply {
component = ComponentName(
MODULE_PACKAGE_NAME,
"${MODULE_PACKAGE_NAME}.ui.activity.ConfigureActivity"
"$MODULE_PACKAGE_NAME.ui.activity.ConfigureActivity"
)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}.apply {
@@ -117,7 +122,7 @@ object IconAdaptationTool {
outTimeLimits.add(nowTime)
context.startActivity(
Intent().apply {
component = ComponentName(MODULE_PACKAGE_NAME, "${MODULE_PACKAGE_NAME}.ui.activity.auto.NotifyIconRuleUpdateActivity")
component = ComponentName(MODULE_PACKAGE_NAME, "$MODULE_PACKAGE_NAME.ui.activity.auto.NotifyIconRuleUpdateActivity")
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
)

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,9 +18,9 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/2/25.
* This file is created by fankes on 2022/2/25.
*/
@file:Suppress("TrustAllX509TrustManager", "CustomX509TrustManager", "DEPRECATION", "IMPLICIT_CAST_TO_ANY")
@file:Suppress("TrustAllX509TrustManager", "CustomX509TrustManager", "IMPLICIT_CAST_TO_ANY")
package com.fankes.coloros.notify.utils.tool
@@ -45,13 +45,25 @@ import com.fankes.coloros.notify.databinding.DiaSourceFromBinding
import com.fankes.coloros.notify.databinding.DiaSourceFromStringBinding
import com.fankes.coloros.notify.param.IconPackParams
import com.fankes.coloros.notify.ui.activity.ConfigureActivity
import com.fankes.coloros.notify.utils.factory.*
import com.highcapable.yukihookapi.hook.log.loggerD
import okhttp3.*
import com.fankes.coloros.notify.utils.factory.delayedRun
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.safeOfNull
import com.fankes.coloros.notify.utils.factory.showDialog
import com.fankes.coloros.notify.utils.factory.snake
import com.highcapable.yukihookapi.hook.log.YLog
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.IOException
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
/**
* 通知图标在线规则管理类
@@ -71,7 +83,7 @@ object IconRuleManagerTool {
private const val SYNC_DIRECT_URL = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main"
/** 同步地址 - GitHub Raw (代理 - GitHub Proxy) */
private const val SYNC_PROXY_1_URL = "https://ghproxy.com/$SYNC_DIRECT_URL"
private const val SYNC_PROXY_1_URL = "https://ghp.ci/$SYNC_DIRECT_URL"
/** 同步地址 - GitHub Raw (代理 - 7ED Services) */
private const val SYNC_PROXY_2_URL = "https://raw.githubusercontentS.com/fankes/AndroidNotifyIconAdapt/main"
@@ -236,7 +248,7 @@ object IconRuleManagerTool {
notifyRefresh(context)
callback()
}
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新") else Unit)
}
}
context is AppCompatActivity ->
@@ -286,7 +298,7 @@ object IconRuleManagerTool {
notifyRefresh(context)
callback()
}
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新") else Unit)
}
context is AppCompatActivity ->
context.showDialog {
@@ -465,11 +477,11 @@ object IconRuleManagerTool {
get() = object : X509TrustManager {
override fun checkClientTrusted(chain: Array<X509Certificate?>?, authType: String?) {
loggerD(msg = "TrustX509 --> $authType")
YLog.debug("TrustX509 --> $authType")
}
override fun checkServerTrusted(chain: Array<X509Certificate?>?, authType: String?) {
loggerD(msg = "TrustX509 --> $authType")
YLog.debug("TrustX509 --> $authType")
}
override fun getAcceptedIssuers() = arrayOf<X509Certificate>()

View File

@@ -1,6 +1,6 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
@@ -18,7 +18,7 @@
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/2/8.
* This file is created by fankes on 2022/2/8.
*/
package com.fankes.coloros.notify.utils.tool
@@ -30,15 +30,19 @@ import androidx.appcompat.app.AppCompatActivity
import com.fankes.coloros.notify.const.PackageName
import com.fankes.coloros.notify.data.ConfigData
import com.fankes.coloros.notify.ui.activity.MainActivity
import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.factory.colorOSFullVersion
import com.fankes.coloros.notify.utils.factory.delayedRun
import com.fankes.coloros.notify.utils.factory.execShell
import com.fankes.coloros.notify.utils.factory.showDialog
import com.fankes.coloros.notify.utils.factory.snake
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.dataChannel
import com.highcapable.yukihookapi.hook.log.YukiHookLogger
import com.highcapable.yukihookapi.hook.log.YukiLoggerData
import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.log.data.YLogData
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData
import java.util.*
import java.util.Locale
/**
* 系统界面工具
@@ -49,7 +53,7 @@ object SystemUITool {
private val CALL_MODULE_REFRESH_RESULT = ChannelData("call_module_refresh_result", false)
/** 当前全部调试日志 */
private var debugLogs = ArrayList<YukiLoggerData>()
private var debugLogs = listOf<YLogData>()
/** 当前启动器实例 */
private var launcher: ActivityResultLauncher<String>? = null
@@ -86,17 +90,17 @@ object SystemUITool {
runCatching {
result?.let { e ->
val content = "" +
"================================================================\n" +
" Generated by ColorOSNotifyIcon\n" +
" Project Url: https://github.com/fankes/ColorOSNotifyIcon\n" +
"================================================================\n\n" +
"[Device Brand]: ${Build.BRAND}\n" +
"[Device Model]: ${Build.MODEL}\n" +
"[Display]: ${Build.DISPLAY}\n" +
"[Android Version]: ${Build.VERSION.RELEASE}\n" +
"[Android API Level]: ${Build.VERSION.SDK_INT}\n" +
"[ColorOS Version]: $colorOSFullVersion\n" +
"[System Locale]: ${Locale.getDefault()}\n\n" + YukiHookLogger.contents(debugLogs).trim()
"================================================================\n" +
" Generated by ColorOSNotifyIcon\n" +
" Project Url: https://github.com/fankes/ColorOSNotifyIcon\n" +
"================================================================\n\n" +
"[Device Brand]: ${Build.BRAND}\n" +
"[Device Model]: ${Build.MODEL}\n" +
"[Display]: ${Build.DISPLAY}\n" +
"[Android Version]: ${Build.VERSION.RELEASE}\n" +
"[Android API Level]: ${Build.VERSION.SDK_INT}\n" +
"[ColorOS Version]: $colorOSFullVersion\n" +
"[System Locale]: ${Locale.getDefault()}\n\n" + YLog.contents(debugLogs).trim()
activity.contentResolver?.openOutputStream(e)?.apply { write(content.toByteArray()) }?.close()
activity.snake(msg = "导出完成")
} ?: activity.snake(msg = "已取消操作")
@@ -123,9 +127,9 @@ object SystemUITool {
context.showDialog {
title = "导出全部调试日志"
msg = "调试日志中会包含当前系统推送的全部通知内容,其中可能包含你的个人隐私," +
"你可以在导出后的日志文件中选择将这些敏感信息模糊化处理再进行共享," +
"开发者使用并查看你导出的调试日志仅为排查与修复问题,并且在之后会及时销毁这些日志。\n\n" +
"继续导出即代表你已阅读并知悉上述内容。"
"你可以在导出后的日志文件中选择将这些敏感信息模糊化处理再进行共享," +
"开发者使用并查看你导出的调试日志仅为排查与修复问题,并且在之后会及时销毁这些日志。\n\n" +
"继续导出即代表你已阅读并知悉上述内容。"
confirmButton(text = "继续") { doExport() }
cancelButton()
}
@@ -145,15 +149,15 @@ object SystemUITool {
context.showDialog {
title = "获取 Root 权限失败"
msg = "当前无法获取 Root 权限,请确认你的设备已经被 Root 且同意授予 Root 权限。\n" +
"如果你正在使用 Magisk 并安装了 Shamiko 模块," +
"请确认当前是否正处于白名单模式。 (白名单模式将导致无法申请 Root 权限)"
"如果你正在使用 Magisk 并安装了 Shamiko 模块," +
"请确认当前是否正处于白名单模式。 (白名单模式将导致无法申请 Root 权限)"
confirmButton(text = "我知道了")
}
context.showDialog {
title = "重启系统界面"
msg = "你确定要立即重启系统界面吗?\n\n" +
"重启过程会黑屏并等待进入锁屏重新解锁。" + (if (isDynamicAvailable)
"\n\n你也可以选择“立即生效”来动态刷新系统界面并生效当前模块设置。" else "")
"重启过程会黑屏并等待进入锁屏重新解锁。" + (if (isDynamicAvailable)
"\n\n你也可以选择“立即生效”来动态刷新系统界面并生效当前模块设置。" else "")
confirmButton {
execShell(cmd = "pgrep systemui").also { pid ->
if (pid.isNotBlank())

View File

@@ -1,60 +0,0 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/5/30.
*/
package com.fankes.coloros.notify.utils.tool
import android.content.Context
import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.utils.factory.openBrowser
import com.fankes.coloros.notify.utils.factory.showDialog
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.prefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
/**
* [YukiHookAPI] 的自动推广工具类
*/
object YukiPromoteTool {
/** 推广已读存储键值 */
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed_${BuildConfig.VERSION_NAME}", false)
/**
* 显示推广对话框
* @param context 实例
*/
fun promote(context: Context) {
fun saveReaded() = context.prefs().edit { put(YUKI_PROMOTE_READED, value = true) }
if (context.prefs().get(YUKI_PROMOTE_READED).not())
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 构建的高效 Hook API 与 Xposed 模块解决方案,助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()
}
cancelButton(text = "我不是开发者") { saveReaded() }
noCancelable()
}
}
}

View File

@@ -0,0 +1,37 @@
/*
* ColorOSNotifyIcon - Optimize notification icons for ColorOS and adapt to native notification icon specifications.
* Copyright (C) 20174 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/ColorOSNotifyIcon
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2023/9/17.
*/
@file:Suppress("unused")
package com.fankes.coloros.notify.wrapper
import com.fankes.coloros.notify.BuildConfig
/**
* 对 [BuildConfig] 的包装
*/
object BuildConfigWrapper {
const val APPLICATION_ID = BuildConfig.APPLICATION_ID
const val VERSION_NAME = BuildConfig.VERSION_NAME
const val VERSION_CODE = BuildConfig.VERSION_CODE
val isDebug = BuildConfig.DEBUG
}

View File

@@ -1213,7 +1213,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:lineSpacingExtra="10dp"
android:text="Q.哪些是已知问题?\nA.以下是问题描述列表:\n(1) 由于机型有限,仅对 ColorOS 12、12.1、13 测试正常运行,根据酷友的需要云调试修复 ColorOS 11 的问题,其它版本情况未知,请自行进行测试。\n(2) OxygenOS 只支持 12、12.1、13 版本,其它类 ColorOS 魔改的 UI 理论没有问题,请自行测试。\n(3) 动态刷新系统界面为实验性功能,若动态地改变了系统深色模式,调节了分辨率和字体大小,状态栏、通知栏中的通知图标会还原或直接不起作用,或在刷新时发生图标黑白块问题,发生类似这种情况请手动重启一次系统界面即可解决。\n(4) 部分机型的 ColorOS 12、12.1 版本概率性出现通知栏的通知图标黑白块问题,属于系统强制重新设置图标问题,无法修复,建议可以更新到 ColorOS 13 的机型更新系统解决,不再负责修复这个问题。"
android:text="Q.哪些是已知问题?\nA.以下是问题描述列表:\n(1) 由于机型有限,仅对 ColorOS 12、12.1、13 测试正常运行,根据酷友的需要云调试修复 ColorOS 11 的问题,其它版本情况未知,请自行进行测试。\n(2) OxygenOS 只支持 12、12.1、13 版本,其它类 ColorOS 魔改的 UI 理论没有问题,请自行测试。\n(3) 动态刷新系统界面为实验性功能,若动态地改变了系统深色模式,调节了分辨率和字体大小,状态栏、通知栏中的通知图标会还原或直接不起作用,或在刷新时发生图标黑白块问题,发生类似这种情况请手动重启一次系统界面即可解决。\n(4) 部分机型的 ColorOS 12、12.1 版本概率性出现通知栏的通知图标黑白块问题,属于系统强制重新设置图标问题,无法修复,建议可以更新到 ColorOS 13 的机型更新系统解决,不再负责修复这个问题。\n(5) 由于 ColorOS 15 版本的系统性通知图标行为变更,系统强制在通知图标初始化阶段就将图标强制替换为 APP 彩色图标进行破坏,所以目前加入了 “系统框架” 作用域如果在模块安装后没有自动勾选此作用域请手动进行勾选并重新启动系统以修复此破坏行为ColorOS 15 以下版本的系统无需勾选。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
@@ -1263,7 +1263,8 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/bg_qr_pay" />
android:adjustViewBounds="true"
android:src="@mipmap/bg_payment_code" />
</androidx.cardview.widget.CardView>
<TextView
@@ -1301,7 +1302,36 @@
android:ellipsize="end"
android:lineSpacingExtra="6dp"
android:maxLines="2"
android:text="此模块使用 YukiHookAPI 构建。\n了解更多 https://github.com/fankes/YukiHookAPI"
android:text="此模块使用 YukiHookAPI 构建。\n了解更多 https://github.com/HighCapable/YukiHookAPI"
android:textColor="@color/colorTextGray"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="10dp"
android:background="@drawable/bg_permotion_round"
android:gravity="center|start"
android:orientation="horizontal"
android:padding="10dp">
<ImageView
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="10dp"
android:src="@mipmap/ic_kavaref" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:ellipsize="end"
android:lineSpacingExtra="6dp"
android:maxLines="2"
android:text="此模块使用 KavaRef 强力驱动。\n了解更多 https://github.com/HighCapable/KavaRef"
android:textColor="@color/colorTextGray"
android:textSize="11sp" />
</LinearLayout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="module_scope">
<item>android</item>
<item>com.android.systemui</item>
</string-array>
</resources>

View File

@@ -1,26 +0,0 @@
plugins {
id 'com.android.application' version '7.4.1' apply false
id 'com.android.library' version '7.4.1' apply false
id 'org.jetbrains.kotlin.android' version '1.8.20' apply false
id 'com.google.devtools.ksp' version '1.8.20-1.0.10' apply false
}
ext {
android = [
compileSdk: 33,
minSdk : 29,
targetSdk : 33
]
app = [
versionName : '1.100',
versionCode : 23,
signingConfigs: [
secretConfigsDirPath : "${projectDir.getAbsolutePath()}/.secret",
secretConfigsFileName: "key_store_secret.json"
]
]
}
task clean(type: Delete) {
delete rootProject.buildDir
}

21
build.gradle.kts Normal file
View File

@@ -0,0 +1,21 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
plugins {
autowire(libs.plugins.android.application) apply false
autowire(libs.plugins.kotlin.android) apply false
autowire(libs.plugins.kotlin.ksp) apply false
}
allprojects {
tasks.withType<KotlinJvmCompile>().configureEach {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
freeCompilerArgs.addAll(
"-Xno-param-assertions",
"-Xno-call-assertions",
"-Xno-receiver-assertions"
)
}
}
}

View File

@@ -1,25 +1,17 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-XX:+UseParallelGC
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
# Compiler Configuration
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
# Incremental
kotlin.incremental.useClasspathSnapshot=true
kotlin.code.style=official
# Project Configuration
project.name=ColorOSNotifyIcon
project.android.compileSdk=36
project.android.minSdk=29
project.android.targetSdk=36
project.app.packageName=com.fankes.coloros.notify
project.app.versionName="1.100"
project.app.versionCode=23
project.app.signing.keyAlias=public
project.app.signing.keyPassword="123456"
project.app.signing.storePassword="123456"
project.app.signing.storeFilePath=.secret/universal.p12

View File

@@ -0,0 +1,84 @@
preferences:
autowire-on-sync-mode: UPDATE_OPTIONAL_DEPENDENCIES
repositories-mode: FAIL_ON_PROJECT_REPOS
repositories:
gradle-plugin-portal:
scope: PLUGINS
google:
maven-central:
jit-pack:
sonatype-oss-releases:
rovo89-xposed-api:
scope: LIBRARIES
url: https://api.xposed.info/
content:
include:
group:
de.robv.android.xposed
fankes-maven-releases:
url: https://raw.githubusercontent.com/fankes/maven-repository/main/repository/releases
plugins:
com.android.application:
alias: android-application
version: 8.12.1
org.jetbrains.kotlin.android:
alias: kotlin-android
version: 2.2.10
com.google.devtools.ksp:
alias: kotlin-ksp
version: 2.2.10-2.0.2
libraries:
com.fankes.projectpromote:
project-promote:
version: 1.0.0
repositories:
fankes-maven-releases
de.robv.android.xposed:
api:
version: 82
repositories:
rovo89-xposed-api
com.highcapable.yukihookapi:
api:
version: 1.3.0
ksp-xposed:
version-ref: <this>::api
com.highcapable.kavaref:
kavaref-core:
version: 1.0.1
kavaref-extension:
version: 1.0.1
com.github.topjohnwu.libsu:
core:
version: 5.2.2
auto-update: false
com.github.duanhong169:
drawabletoolbox:
version: 1.0.7
com.squareup.okhttp3:
okhttp:
version: 5.1.0
androidx.core:
core-ktx:
version: 1.17.0
androidx.appcompat:
appcompat:
version: 1.7.1
com.google.android.material:
material:
version: 1.12.0
androidx.constraintlayout:
constraintlayout:
version: 2.2.1
androidx.test.ext:
junit:
version: 1.3.0
androidx.test.espresso:
espresso-core:
version: 3.7.0
junit:
junit:
version: 4.13.2

View File

@@ -1,6 +1,5 @@
#Wed May 25 04:24:55 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStoreBase=GRADLE_USER_HOME

BIN
img-src/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -1,19 +0,0 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
maven { url "https://api.xposed.info/" }
maven { url "https://www.jitpack.io" }
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
mavenCentral()
}
}
rootProject.name = "ColorOSNotifyIcon"
include ':app'

27
settings.gradle.kts Normal file
View File

@@ -0,0 +1,27 @@
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
plugins {
id("com.highcapable.sweetdependency") version "1.0.4"
id("com.highcapable.sweetproperty") version "1.0.8"
}
sweetProperty {
global {
all {
permanentKeyValues("GITHUB_CI_COMMIT_ID" to "")
generateFrom(ROOT_PROJECT, SYSTEM_ENV)
}
sourcesCode {
includeKeys("GITHUB_CI_COMMIT_ID")
// 关闭类型自动转换功能,防止一些特殊 "COMMIT ID" 被生成为数值
isEnableTypeAutoConversion = false
}
}
rootProject { all { isEnable = false } }
}
rootProject.name = "ColorOSNotifyIcon"
include(":app")