34 Commits
1.53 ... 1.76

Author SHA1 Message Date
117b37b5cf Update version to 1.76 2022-05-09 01:20:51 +08:00
967186bd00 Update misc 2022-05-09 01:16:53 +08:00
eea7b6d897 更新文案 2022-05-09 01:16:46 +08:00
dd75a13970 尝试修复通知面板透明功能在 ColorOS 12 不生效的问题 2022-05-09 01:11:09 +08:00
66ed43f5ad Fix Activity destroy non-null unregister bug 2022-05-09 00:57:37 +08:00
399cfafd29 Make SystemUIHooker singleton 2022-05-08 15:08:05 +08:00
6ae1d3e726 Update YukiHookAPI 2022-05-06 15:09:25 +08:00
384e6b657e Update version to 1.75 2022-05-05 15:17:04 +08:00
08b7feeede 优化通知面板背景透明度功能设置界面,添加实验性文案说明 2022-05-05 15:11:23 +08:00
e7fc0bbcd0 默认关闭通知面板背景透明度功能 2022-05-05 15:10:58 +08:00
1f8022fd7c 修复通知面板折叠通知背景异常问题,优化二级通知的背景 2022-05-05 15:10:46 +08:00
Fankesyooni
b404543f47 Merge pull request #16 from NextAlone/master
fix: notification summary background
2022-05-05 12:34:40 +08:00
NextAlone
ad195d93ea fix: notification summary background 2022-05-05 05:19:49 +08:00
15e7490808 Update YukiHookAPI 2022-05-04 14:03:55 +08:00
7c906cd2a0 Update YukiHookAPI 2022-05-04 10:15:55 +08:00
0da5875d64 Update YukiHookAPI 2022-05-04 09:32:30 +08:00
947ec809e7 Update version to 1.7 2022-05-04 06:49:38 +08:00
c07f3e99a1 新增通知面板背景透明度调节功能 2022-05-04 06:06:10 +08:00
ebba4d2345 Update YukiHookAPI 2022-05-04 05:22:56 +08:00
e60fc6ae7c Update YukiHookAPI 2022-05-01 12:08:02 +08:00
7688dbb5ca Update README.md/PRIVACY.md 2022-04-26 00:41:55 +08:00
e703237a6d Merge code 2022-04-25 02:47:34 +08:00
01494e8467 Update YukiHookAPI 2022-04-18 03:14:39 +08:00
e08081ae42 Update YukiHookAPI 2022-04-15 15:26:52 +08:00
758f80d1c1 Update YukiHookAPI 2022-04-15 05:22:20 +08:00
b06ecaa5e0 Update version to 1.6 2022-04-14 03:20:22 +08:00
df5090faac 更换通知刷新方案,彻底解决系统界面卡死问题 2022-04-14 03:03:27 +08:00
ffb706864a Update YukiHookAPI 2022-04-13 05:03:30 +08:00
70eadb83e8 Merge code 2022-04-11 23:08:21 +08:00
6d7d7290e2 Update YukiHookAPI 2022-04-10 03:05:13 +08:00
1191c77986 Update YukiHookAPI 2022-04-09 02:35:08 +08:00
2f4539d8f6 Update README.md 2022-04-09 01:53:45 +08:00
030a1590ae Update README.md 2022-04-05 22:45:54 +08:00
52820c0b07 加入新安装应用的通知图标优化适配通知忽略 DEBUG 版本的 APP 2022-04-05 22:03:09 +08:00
17 changed files with 745 additions and 176 deletions

2
.idea/misc.xml generated
View File

@@ -11,7 +11,7 @@
<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.335" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.31170825335892516" />
<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" />

359
PRIVACY.md Normal file
View File

@@ -0,0 +1,359 @@
### ColorOS 通知图标增强 隐私政策
> 简体中文
版本1.0
修订与生效日期2022年4月25日
#### 前言
为帮助您使用 ColorOS 通知图标增强产品(以下简称“本产品”)或服务,我们可能收集与提供服务相关的设备信息或申请设备权限,您有权拒绝或撤回授权;
我们采取了互联网业内标准的技术措施和数据安全措施来保护您的设备信息安全;
除非再次征得您的同意,我们不会将您的设备信息用于本政策未载明的其他目的;
在阅读本协议前,请确认您已年满 18 岁,否则请在父母的陪同下阅读本协议。
#### 目录
```
1. 引言
2. 本产品处理设备信息的法律依据
3. 我们如何收集和使用您的设备信息
3.1 向您提供本产品和/或服务的核心业务功能
3.2 征得授权同意的例外
4. 我们如何转让、公开披露您的设备信息
4.1 转让您的设备信息
4.2 公开披露
4.3 共享、转让、公开披露设备信息授权同意的例外
5. 您管理设备信息的权利
5.1 设备权限调用
6. 如何更新与修改本政策
7. 争议解决
8. 名词解释
```
1. 引言
【特别提示】
请您在使用我们的各项产品和/或服务前,仔细阅读并充分理解本政策。一旦您使用或继续使用本产品/服务,即表示您同意我们按照本政策处理您的相关信息。
2. 本产品处理设备信息的法律依据
如果您是中华人民共和国大陆地区的用户,我们将依据《中华人民共和国网络安全法》、《信息安全技术 个人信息安全规范》GB/T 35273-2017以及其他相关法律法规收集和使用您的设备信息或申请设备权限为您提供本产品或服务。 我们通常只会在征得您同意的情况下收集您的设备信息。
3. 我们如何收集和使用您的设备信息
我们会遵循正当、合法、必要的原则,出于本政策所述的以下目的,收集和使用您在使用服务过程中主动提供或因使用本产品和/或服务而产生的设备信息。如果我们要将您的设备信息用于本政策未载明的其它用途,或基于特定目的将收集而来的信息用于其他目的,我们将以合理的方式向您告知,并在使用前再次征得您的同意。
3.1 向您提供本产品和/或服务的核心业务功能
为实现 本产品的核心业务功能,我们可能需要向您收集设备信息。以下将详细列出 本产品的核心业务功能及为实现该功能所需收集的设备信息,若您拒绝收集,则无法使用该服务。
查看设备中的所有应用信息。 本产品会读取您的设备应用列表;
搜索功能。 当您使用 本产品提供的搜索功能时,我们可能会使用应用数据缓存,收集您设备上的信息并进行本地存储。 该信息通常无法单独识别您的个人身份。
3.2 征得授权同意的例外
根据相关法律法规的规定,在以下情形中,我们可以在不征得您的授权同意的情况下收集、使用一些必要的设备信息:
```
a. 与国家安全、国防安全直接相关的;
b. 与公共安全、公共卫生、重大公共利益直接相关的;
c. 与犯罪侦查、起诉、审判和判决执行等直接相关的;
d. 出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
e. 所收集的设备信息是您自行向社会公众公开的;
f. 从合法公开披露的信息中收集到您的设备信息,如从合法的新闻报道、政府信息公开等渠道;
g. 根据您的要求签订和履行合同所必需的;
h. 用于维护 本产品的产品和/或服务的安全稳定运行所必需的,例如发现、处置产品或服务的故障;
i. 法律法规规定的其他情形。
```
4. 我们如何共享、转让、公开披露您的设备信息
4.1 转让您的设备信息
除非获取您的明确同意,我们不会将您的设备信息转让给任何公司、组织或个人。
4.2 公开披露
除非获取您的明确同意,我们不会公开披露您的设备信息。
4.3 共享、转让、公开披露设备信息授权同意的例外
根据相关法律法规的规定,在以下情形中,我们可以在不征得您的授权同意的情况下共享、转让、公开披露您的设备信息:
```
A. 与国家安全、国防安全有关的;
B. 与公共安全、公共卫生、重大公共利益有关的;
C. 与犯罪侦查、起诉、审判和判决执行等有关的;
D. 出于维护您或其他个人的生命、财产等重大合法权益但又很难得到本人同意的;
E. 您自行向社会公众公开的设备信息;
F. 从合法公开披露的信息中收集到的设备信息的,如合法的新闻报道、政府信息公开等渠道。
G. 法律法规规定的其他情形。
```
根据法律规定,共享、转让经去标识化处理的设备信息,且确保数据接收方无法复原并重新识别设备信息主体的,不属于设备信息的对外共享、转让及公开披露行为,对此类数据的保存及处理将无需另行向您通知并征得您的同意。
5. 您管理设备信息的权利
5.1 设备权限调用
我们在提供服务的过程中,可能需要您开通一些设备权限,例如网络连接、查看设备应用列表等访问权限。 您也可以在设备的【设置】功能中随时选择关闭部分或者全部权限,从而拒绝我们收集您相应的设备信息。在不同设备中,权限显示方式及关闭方式可能有所不同,具体请参考设备及系统开发方说明或指引。
6. 如何更新与修改本政策
6.1 本政策为本产品的重要组成部分。 本产品保留不时更新或修改本政策的权利。
6.2 未经您明确同意,我们不会削减您按照本政策所应享有的权利。我们会通过 App 客户端推送通知、弹窗形式等合理方式通知您,以便您能及时了解本政策所做的任何变更。
6.3 对于重大变更,视具体情况我们 可能还会提供更为显著的通知 说明本政策的具体变更内容。 重大变更包括但不限于:
```
A. 我们的服务模式发生重大变化。如处理设备信息的目的、处理的设备信息类型、设备信息的使用方式等;
B. 我们在所有权结构、组织架构等方面发生重大变化。如业务调整、破产并购等引起的所有者变更等;
C. 设备信息共享、转让或公开披露的主要对象发生变化;
D. 您参与设备信息处理方面的权利及其行使方式发生重大变化;
E. 我们负责处理设备信息安全的责任部门、联络方式及投诉渠道发生变化;
F. 设备信息安全影响评估报告表明存在高风险时。
```
6.4 若您不同意修改后的隐私政策,您有权并应立即停止使用 本产品的服务。如果您继续使用 本产品的服务,则视为您接受 本产品对本政策相关条款所做的修改。
7. 争议解决
7.1 如果您认为我们的设备信息处理行为损害了您的合法权益,您也可向有关政府部门进行反映。
8. 名词解释
本隐私政策中使用到的名词,在通常意义中有如下定义:
设备信息: 设备信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别设备身份的各种信息,包括但不限于设备的品牌、型号、系统版本、 唯一设备标识符、 网络 IP 地址、Cookie等
设备: 设备是指可用于访问本产品和/或服务的装置,例如台式计算机、笔记本电脑、平板电脑或智能手机。 唯一设备标识符: 唯一设备标识符(专属 ID 或 UUID是指由设备制造商编入到设备中的一串字符可用于以独有方式标识相应设备例如手机的 IMEI
号)。唯一设备标识符有多种用途,其中可在不能使用 Cookie例如在移动应用程序中时用以提供广告。
IP 地址: 每台上网的设备都会指定一个编号,称为互联网协议 ( IP ) 地址。这些编号通常都是根据地理区域指定的。IP 地址通常可用于识别设备连接至互联网时所在的位置。
信息收集技术: 我们在《ColorOS 通知图标增强 隐私政策》中所述的“自动收集”包括以下方式: A. Cookie曲奇档案 Cookie 是您浏览网页时,网站服务器放在客户端(您的计算机、移动电话或其他智能终端内)里面的一个小小的文本文件,当您再次访问相应网站时,网站就可通过
Cookie 识别您的浏览器。Cookie 可能会存储用户偏好及其他信息。您可以将浏览器配置为拒绝所有 Cookie 或在网站发送 Cookie 时显示提示。不过,如果没有 Cookie某些网站功能或服务可能无法正常工作。 B. Web beacon网络信标 Web beacon
是装嵌在网站或电邮内的电子图像文件案或其他技术,可用于计算访客数目、记录您是否及何时阅览电邮或网站,或用以使用某些 Cookie。 C. Log files日志文件 Log files 储存自动收集的若干数据。该等数据包括互联网协议( IP )地址、浏览器类型、互联网服务提供商(
ISP )、引用/退出页面、操作系统、日期/时间戳和点击流数据等。 D. ET Tag实体标签 ET Tag 是在互联网浏览器与互联网服务器之间背后传送的 HTTP 协议标头,可代替 Cookie用以追踪个别使用者使我们可更深入地了解和改善我们的服务。 E. JavaScript
JavaScript 是一种编程语言用于制作更具互动性和动态的网页。JavaScript 可以设定 Cookie、阅读 Cookie 及删除 Cookie。
算法: 计算机在执行解题运算时遵循的流程或一系列规则。
应用数据缓存: 应用数据缓存是指设备上的一种数据存储机制。使用它有很多好处,例如,可让网络应用在未连接互联网的情况下运行,以及可通过提高内容加载速度来改善相关应用的性能。
非个人身份信息: 记录的与用户相关的信息,但实际上不可直接或间接识别您身份的信息,包括经过去标识化、匿名化处理或化名方式提供的设备信息。
去标识化: 指通过对设备信息的技术处理,使其在不借助额外信息的情况下,无法识别设备信息主体的过程。
匿名化: 指通过对设备信息的技术处理,使得设备信息主体无法被识别,且处理后的信息不能被复原的过程。
服务器日志: 与大多数网站一样,我们的服务器会自动记录您在访问网站时所发出的网页请求。这些“服务器日志”通常包括您的网络请求、互联网协议地址、浏览器类型、浏览器语言、请求的日期和时间及可以唯一识别您的浏览器的一个或多个 Cookie。
### ColorOSNotifyIcon Privacy Policy
> English
Version: 1.0
Amendment and effective date: April 25, 2022
#### Preface
In order to help you use ColorOSNotifyIcon products (hereinafter referred to as "this product") or services, we may collect device information
related to the provision of services or apply for device permissions, and you have the right to refuse or withdraw authorization;
We have adopted technical measures and data security measures that are standard in the Internet industry to protect the security of your device
information;
Unless we obtain your consent again, we will not use your device information for other purposes not specified in this policy;
Before reading this agreement, please confirm that you are at least 18 years old, otherwise please read this agreement with your parents.
#### content
````
1 Introduction
2. Legal basis for this product to process device information
3. How we collect and use your device information
3.1 Provide you with the core business functions of this product and/or service
3.2 Exceptions to Authorized Consent
4. How we transfer and publicly disclose your device information
4.1 Transfer your device information
4.2 Public disclosure
4.3 Exceptions to Authorization and Consent for Sharing, Transfer, and Public Disclosure of Device Information
5. Your Right to Manage Device Information
5.1 Device permission call
6. How to update and modify this policy
7. Dispute Resolution
8. Glossary
````
1 Introduction
【Special Note】
Please read and fully understand this policy before using our products and/or services. Once you use or continue to use this product/service, you
agree that we will process your relevant information in accordance with this policy.
2. Legal basis for this product to process device information
If you are a user in the mainland of the People's Republic of China, we will collect and use your Device information or apply for device
permissions to provide you with this product or service. We generally only collect your device information with your consent.
3. How we collect and use your device information
We will follow the principles of legitimacy, lawfulness, and necessity, and for the following purposes described in this policy, to collect and
use the device information that you actively provide during the use of the service or that arises from the use of this product and/or service. If
we want to use your device information for other purposes not specified in this policy, or use the collected information for other purposes based
on a specific purpose, we will inform you in a reasonable manner and ask again before use with your consent.
3.1 Provide you with the core business functions of this product and/or service
In order to implement the core business functions of this product, we may need to collect device information from you. The following will list in
detail the core business functions of this product and the device information that needs to be collected to achieve this function. If you refuse
to collect, you cannot use the service.
View all app information on the device. This product will read your device application list;
searching feature. When you use the search function provided by this product, we may use application data cache, collect information on your
device and store it locally. This information generally does not individually identify you as an individual.
3.2 Exceptions to Authorized Consent
According to relevant laws and regulations, we may collect and use some necessary device information without your authorization and consent under
the following circumstances:
````
a. Directly related to national security and national defense security;
b. Directly related to public safety, public health, and major public interests;
c. Directly related to criminal investigation, prosecution, trial and execution of judgments;
d. In order to protect your or other personal life, property and other major legitimate rights and interests, but it is difficult to obtain my consent;
e. The collected device information is disclosed to the public by you;
f. Your device information is collected from legally publicly disclosed information, such as legal news reports, government information disclosure and other channels;
g. Necessary to enter into and perform a contract at your request;
h. Necessary to maintain the safe and stable operation of the products and/or services of this product, such as finding and disposing of faults in the products or services;
i. Other situations stipulated by laws and regulations.
````
4. How we share, transfer, and publicly disclose your device information
4.1 Transfer your device information
We will not transfer your device information to any company, organization or individual without your express consent.
4.2 Public disclosure
We will not publicly disclose your device information without your express consent.
4.3 Exceptions to Authorization and Consent for Sharing, Transfer, and Public Disclosure of Device Information
According to relevant laws and regulations, we may share, transfer and publicly disclose your device information without your authorization and
consent in the following circumstances:
````
A. Related to national security and national defense security;
B. Related to public safety, public health, and major public interests;
C. Related to criminal investigation, prosecution, trial and execution of judgments;
D. In order to protect your or other personal life, property and other major legitimate rights and interests, but it is difficult to obtain my consent;
E. The device information that you disclose to the public by yourself;
F. Device information collected from legally publicly disclosed information, such as legal news reports, government information disclosure and other channels.
G. Other situations stipulated by laws and regulations.
````
According to the law, sharing and transferring de-identified device information and ensuring that the data recipient cannot restore and
re-identify the subject of the device information is not an act of external sharing, transfer and public disclosure of device information.
Storage and processing will not be required to notify you and obtain your consent.
5. Your Right to Manage Device Information
5.1 Device permission call
In the process of providing services, we may require you to activate some device permissions, such as network connection, viewing device
application list and other access permissions. You can also choose to turn off some or all permissions at any time in the [Settings] function of
the device, thereby refusing us to collect your corresponding device information. In different devices, the display method and closing method of
permissions may be different. For details, please refer to the instructions or guidelines of the device and system developers.
6. How to update and modify this policy
6.1 This policy is an important part of this product. This product reserves the right to update or modify this policy from time to time.
6.2 We will not reduce your rights under this Policy without your express consent. We will notify you through reasonable means such as app client
push notifications and pop-up windows, so that you can keep abreast of any changes to this policy.
6.3 For major changes, we may also provide a more prominent notice to explain the specific changes to this policy as the case may be. Significant
changes include, but are not limited to:
````
A. Significant changes to our service model. Such as the purpose of processing device information, the type of device information processed, the way of using device information, etc.;
B. We have made significant changes in our ownership structure, organizational structure, etc. Such as changes in owners caused by business adjustments, bankruptcy mergers and acquisitions, etc.;
C. The main object of equipment information sharing, transfer or public disclosure has changed;
D. Significant changes in your rights to participate in the processing of device information and the way you exercise it;
E. The responsible department, contact information and complaint channel that we are responsible for handling equipment information security have changed;
F. When the equipment information security impact assessment report indicates that there is a high risk.
````
6.4 If you do not agree with the revised Privacy Policy, you have the right and should immediately stop using the services of this product. If
you continue to use the services of this product, it is deemed that you accept the modifications made by this product to the relevant terms of
this policy.
7. Dispute Resolution
7.1 If you believe that our device information processing has damaged your legitimate rights and interests, you can also report to the relevant
government departments.
8. Glossary
Terms used in this Privacy Policy have the following definitions in their usual meanings:
Device information: Device information refers to various information recorded electronically or in other ways that can identify the identity of
the device alone or in combination with other information, including but not limited to the brand, model, system version, unique device
identifier, network IP address of the device , Cookies, etc.;
Device: A device is a device that can be used to access the Product and/or Service, such as a desktop computer, laptop, tablet or smartphone.
Unique Device Identifier: A Unique Device Identifier (Unique ID or UUID) is a string of characters programmed into a device by the device
manufacturer that can be used to uniquely identify the device (such as the IMEI of a mobile phone)
No). Unique device identifiers are used for a variety of purposes, including serving advertisements when cookies cannot be used, such as in
mobile applications.
IP Address: Every device that goes online is assigned a number called an Internet Protocol (IP) address. These numbers are usually assigned by
geographic area. An IP address can often be used to identify where a device is connected to the Internet.
Information collection technology: The "automatic collection" described in the "ColorOSNotifyIcon Privacy Policy" includes the following methods:
A. Cookie (cookie file) Cookie is when you browse the web, the website server places it on the client (your A small text file in a computer,
mobile phone or other intelligent terminal), when you visit the corresponding website again, the website can pass Cookies identify your browser.
Cookies may store user preferences and other information. You can configure your browser to refuse all cookies or to display a prompt when a
website sends a cookie. However, some website features or services may not function properly without cookies. B. Web beacon (web beacon)
Web beacon An electronic image file or other technology embedded in a website or email that can be used to count visitors, record whether and
when you view an email or website, or to use certain cookies. C. Log files Log files store certain data collected automatically. This data
includes Internet Protocol (IP) address, browser type, Internet Service Provider (
ISP), referring/exit pages, operating system, date/time stamp and clickstream data, etc. D. ET Tag (Entity Tag) ET Tag is an HTTP protocol header
transmitted behind the Internet browser and Internet server, which can replace cookies to track individual users, so that we can better
understand and improve our Serve. E. JavaScript JavaScript is a programming language used to make more interactive and dynamic web pages.
JavaScript can set cookies, read cookies and delete cookies.
Algorithm: A process or set of rules that a computer follows when performing a problem-solving operation.
App data cache: App data cache refers to a data storage mechanism on the device. There are many benefits to using it, such as allowing web
applications to run without an internet connection, and improving the performance of related applications by increasing the speed of content
loading.
Non-Personally Identifiable Information: Information that is recorded about a user but does not actually identify you directly or indirectly,
including device information that has been de-identified, anonymized, or provided under a pseudonym.
De-identification: refers to the process of technical processing of device information to make it impossible to identify the subject of device
information without the aid of additional information.
Anonymization: refers to the process in which the subject of the device information cannot be identified and the processed information cannot be
recovered through the technical processing of the device information.
Server Logs: Like most websites, our servers automatically log the web page requests you make while visiting the website. These "server logs"
typically include your web request, internet protocol address, browser type, browser language, date and time of the request, and one or more
cookies that uniquely identify your browser.

View File

@@ -2,50 +2,59 @@
[![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.53-green)](https://github.com/fankes/ColorOSNotifyIcon/releases)
[![Blank](https://img.shields.io/badge/version-v1.76-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/static/v1?label=Telegram&message=交流讨论&color=0088cc)](https://t.me/XiaofangInternet)
[![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" width = "100" height = "100"/>
<br/>
Optimize notification icons for ColorOS and adapt to native notification icon specifications.<br/>
Optimize notification icons for ColorOS and adapt to native notification icon specifications.
为 ColorOS 优化通知图标以及适配原生通知图标规范,理论支持 OxygenOS 和 RealmeUI。
# Developer
## Developer
[酷安 @星夜不荟](http://www.coolapk.com/u/876977)
# 适配说明
## 适配说明
- 此模块仅支持 <b>LSPosed</b>(作用域“系统界面”)、<b>~~EdXposed(随时停止支持)~~</b>、不支持<b>太极、无极</b>
- 目前仅在 ColorOS 12 for OnePlus 上测试通过,如有问题请提交 `issues`
- 建议在不低于 ColorOS 11 的版本上使用
# 请勿用于非法用途
## 请勿用于非法用途
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.coloros.notify/releases)、
[Release](https://github.com/fankes/ColorOSNotifyIcon/releases)
及 [蓝奏云](https://fankes.lanzouy.com/b030rvjyf),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
[Release](https://github.com/fankes/ColorOSNotifyIcon/releases)、[蓝奏云](https://fankes.lanzouy.com/b030rvjyf) 及**酷安应用市场**
,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
# 贡献通知图标优化名单
## 贡献通知图标优化名单
此项目是 `AndroidNotifyIconAdapt` 项目的一部分,详情请参考下方。<br/>
此项目是 `AndroidNotifyIconAdapt` 项目的一部分,详情请参考下方。
- [Android 通知图标规范适配计划](https://github.com/fankes/AndroidNotifyIconAdapt)
# 历史背景
## 历史背景
继 MIUI 之后的第二大系统 ColorOS 虽然支持原生通知图标,但是第三方推送五颜六色的图标系统并没有做适配,甚至系统自己的图标都是彩色的,极其不友好。
继 MIUI 之后的第二大系统 ColorOS 虽然支持原生通知图标,但是第三方推送五颜六色的图标系统并没有做适配,甚至系统自己的图标都是彩色的,极其不友好。<br/>
而且从 ColorOS 12 开始,原生图标丢失了着色属性,这也是一种对原生 Android 生态的破坏。
# 捐赠支持
## 捐赠支持
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<br/><br/>
<img src="https://github.com/fankes/YuKiHookAPI/blob/master/img-src/wechat_code.jpg" width = "200" height = "200"/>
# 许可证
## 隐私政策
- [PRIVACY](https://github.com/fankes/ColorOSNotifyIcon/blob/master/PRIVACY.md)
## 许可证
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
@@ -66,5 +75,6 @@ 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/>.
```
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)<br/><br/>
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)
版权所有 © 2019-2022 Fankes Studio(qzmmcn@163.com)

View File

@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'com.google.devtools.ksp' version '1.6.10-1.0.4'
id 'com.google.devtools.ksp' version '1.6.21-1.0.5'
}
android {
@@ -25,20 +25,12 @@ android {
versionCode rootProject.ext.appVersionCode
versionName rootProject.ext.appVersionName
kotlinOptions {
freeCompilerArgs = [
'-Xno-param-assertions',
'-Xno-call-assertions',
'-Xno-receiver-assertions'
]
}
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled true
minifyEnabled rootProject.ext.enableR8
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
@@ -49,6 +41,11 @@ android {
}
kotlinOptions {
jvmTarget = '11'
freeCompilerArgs = [
'-Xno-param-assertions',
'-Xno-call-assertions',
'-Xno-receiver-assertions'
]
}
buildFeatures {
viewBinding true
@@ -72,9 +69,8 @@ tasks.whenTaskAdded {
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.71'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.71'
implementation 'com.github.tiann:FreeReflection:3.1.0'
implementation 'com.highcapable.yukihookapi:api:1.0.86'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.86'
implementation "com.github.topjohnwu.libsu:core:3.1.2"
implementation 'androidx.annotation:annotation:1.3.0'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
@@ -82,7 +78,7 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.google.android.material:material:1.6.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'

View File

@@ -20,7 +20,6 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-dontwarn
-ignorewarnings
-optimizationpasses 10
-dontusemixedcaseclassnames
@@ -35,15 +34,6 @@
-renamesourcefileattribute P
-keepattributes SourceFile,LineNumberTable
-keep class me.weishu**{*;}
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
public static *** throwUninitializedProperty(...);
public static *** throwUninitializedPropertyAccessException(...);

View File

@@ -24,32 +24,13 @@
package com.fankes.coloros.notify.application
import android.app.Application
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import me.weishu.reflection.Reflection
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication
class CNNApplication : Application() {
companion object {
/** 全局静态实例 */
private var context: CNNApplication? = null
/** 调用全局静态实例 */
val appContext get() = context ?: error("App is death")
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
/** 解锁隐藏 API */
Reflection.unseal(base)
}
class CNNApplication : ModuleApplication() {
override fun onCreate() {
super.onCreate()
/** 设置静态实例 */
context = this
/** 跟随系统夜间模式 */
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}

View File

@@ -41,7 +41,7 @@ object Const {
const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE
/** 当前模块的版本校验 */
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202204042319"
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202205090117"
/** 当前模块的版本校验标签 */
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"

View File

@@ -38,6 +38,8 @@ object DataConst {
val REMOVE_CHANGECP_NOTIFY = PrefsData("_remove_charge_complete_notify", false)
val REMOVE_DNDALERT_NOTIFY = PrefsData("_remove_dndalert_notify", false)
val ENABLE_NOTIFY_ICON_FIX_AUTO = PrefsData("_enable_notify_icon_fix_auto", true)
val ENABLE_NOTIFY_PANEL_ALPHA = PrefsData("_enable_notify_panel_alpha", false)
val NOTIFY_PANEL_ALPHA = PrefsData("_notify_panel_alpha", 185)
val NOTIFY_ICON_DATAS = PrefsData("_notify_icon_datas", "")
val NOTIFY_ICON_FIX_AUTO_TIME = PrefsData("_notify_icon_fix_auto_time", "07:00")

View File

@@ -30,10 +30,10 @@ 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.xposed.proxy.YukiHookXposedInitProxy
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed
class HookEntry : YukiHookXposedInitProxy {
class HookEntry : IYukiHookXposedInit {
override fun onInit() = configs {
debugTag = "ColorOSNotify"
@@ -47,7 +47,7 @@ class HookEntry : YukiHookXposedInitProxy {
/** Hook 被手动关闭停止 Hook */
prefs.get(DataConst.ENABLE_MODULE).not() -> loggerW(msg = "Aborted Hook -> Hook Closed")
/** 开始 Hook */
else -> loadApp(SYSTEMUI_PACKAGE_NAME, SystemUIHooker())
else -> loadApp(SYSTEMUI_PACKAGE_NAME, SystemUIHooker)
}
}
}

View File

@@ -20,6 +20,8 @@
*
* This file is Created by fankes on 2022/3/25.
*/
@file:Suppress("StaticFieldLeak")
package com.fankes.coloros.notify.hook.entity
import android.app.WallpaperManager
@@ -36,7 +38,6 @@ import android.graphics.drawable.Icon
import android.graphics.drawable.VectorDrawable
import android.service.notification.StatusBarNotification
import android.util.ArrayMap
import android.util.ArraySet
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
@@ -56,7 +57,9 @@ import com.fankes.coloros.notify.utils.factory.*
import com.fankes.coloros.notify.utils.tool.IconAdaptationTool
import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.field
import com.highcapable.yukihookapi.hook.factory.hasMethod
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerE
@@ -70,98 +73,108 @@ import com.highcapable.yukihookapi.hook.type.java.LongType
/**
* 系统界面核心 Hook 类
*/
class SystemUIHooker : YukiBaseHooker() {
object SystemUIHooker : YukiBaseHooker() {
companion object {
/** 原生存在的类 */
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
/** 原生存在的类 */
private const val ContrastColorUtilClass = "com.android.internal.util.ContrastColorUtil"
/** 原生存在的类 */
private const val NotificationUtilsClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtils"
/** 原生存在的类 */
private const val NotificationUtilsClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationUtils"
/** 原生存在的类 */
private const val NotificationEntryClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.collection.NotificationEntry"
/** 原生存在的类 */
private const val NotificationEntryClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.collection.NotificationEntry"
/** 原生存在的类 */
private const val StatusBarIconClass = "com.android.internal.statusbar.StatusBarIcon"
/** 原生存在的类 */
private const val StatusBarIconClass = "com.android.internal.statusbar.StatusBarIcon"
/** 原生存在的类 */
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
/** 原生存在的类 */
private const val StatusBarIconViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.StatusBarIconView"
/** 原生存在的类 */
private const val IconBuilderClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconBuilder"
/** 原生存在的类 */
private const val IconBuilderClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconBuilder"
/** 原生存在的类 */
private const val IconManagerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconManager"
/** 原生存在的类 */
private const val IconManagerClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.icon.IconManager"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusContrastColorUtilClass = "com.oplusos.util.OplusContrastColorUtil"
/** 原生存在的类 */
private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** 原生存在的类 */
private const val PluginManagerImplClass = "$SYSTEMUI_PACKAGE_NAME.shared.plugins.PluginManagerImpl"
/** 原生存在的类 */
private const val NotificationBackgroundViewClass = "$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.NotificationBackgroundView"
/** 根据多个版本存在不同的包名相同的类 */
private val OplusNotificationIconAreaControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.policy.OplusNotificationIconAreaController",
"com.coloros.systemui.statusbar.policy.ColorNotificationIconAreaController"
)
/** ColorOS 存在的类 - 旧版本不存在 */
private const val OplusNotificationBackgroundViewClass =
"com.oplusos.systemui.statusbar.notification.row.OplusNotificationBackgroundView"
/** 根据多个版本存在不同的包名相同的类 */
private val SystemPromptControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.policy.SystemPromptController",
"com.coloros.systemui.statusbar.policy.ColorSystemPromptController"
)
/** 根据多个版本存在不同的包名相同的类 */
private val OplusNotificationIconAreaControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.phone.OplusNotificationIconAreaController",
"com.oplusos.systemui.statusbar.policy.OplusNotificationIconAreaController",
"com.coloros.systemui.statusbar.policy.ColorNotificationIconAreaController"
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtilClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil"
)
/** 根据多个版本存在不同的包名相同的类 */
private val SystemPromptControllerClass = VariousClass(
"com.oplusos.systemui.statusbar.policy.SystemPromptController",
"com.coloros.systemui.statusbar.policy.ColorSystemPromptController"
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtil_CompanionClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion",
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion"
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtilClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil",
"com.coloros.systemui.notification.util.RoundRectDrawableUtil"
)
/** 根据多个版本存在不同的包名相同的类 */
private val DndAlertHelperClass = VariousClass(
"com.oplusos.systemui.notification.helper.DndAlertHelper",
"com.coloros.systemui.notification.helper.DndAlertHelper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val RoundRectDrawableUtil_CompanionClass = VariousClass(
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion",
"com.oplusos.systemui.notification.util.RoundRectDrawableUtil\$Companion"
)
/** 根据多个版本存在不同的包名相同的类 */
private val OplusPowerNotificationWarningsClass = VariousClass(
"com.oplusos.systemui.notification.power.OplusPowerNotificationWarnings",
"com.coloros.systemui.notification.power.ColorosPowerNotificationWarnings"
)
/** 根据多个版本存在不同的包名相同的类 */
private val DndAlertHelperClass = VariousClass(
"com.oplusos.systemui.notification.helper.DndAlertHelper",
"com.coloros.systemui.notification.helper.DndAlertHelper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val AbstractReceiverClass = VariousClass(
"com.oplusos.systemui.common.receiver.AbstractReceiver",
"com.coloros.systemui.common.receiver.AbstractReceiver"
)
/** 根据多个版本存在不同的包名相同的类 */
private val OplusPowerNotificationWarningsClass = VariousClass(
"com.oplusos.systemui.notification.power.OplusPowerNotificationWarnings",
"com.coloros.systemui.notification.power.ColorosPowerNotificationWarnings"
)
/** 根据多个版本存在不同的包名相同的类 */
private val ExpandableNotificationRowClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.ExpandableNotificationRow",
"$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
)
/** 根据多个版本存在不同的包名相同的类 */
private val AbstractReceiverClass = VariousClass(
"com.oplusos.systemui.common.receiver.AbstractReceiver",
"com.coloros.systemui.common.receiver.AbstractReceiver"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationViewWrapperClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val StatusBarNotificationPresenterClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.phone.StatusBarNotificationPresenter",
"$SYSTEMUI_PACKAGE_NAME.statusbar.phone.StatusBar"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationHeaderViewWrapperClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationHeaderViewWrapper"
)
}
/** 根据多个版本存在不同的包名相同的类 */
private val ExpandableNotificationRowClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.ExpandableNotificationRow",
"$SYSTEMUI_PACKAGE_NAME.statusbar.ExpandableNotificationRow"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationViewWrapperClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationViewWrapper"
)
/** 根据多个版本存在不同的包名相同的类 */
private val NotificationHeaderViewWrapperClass = VariousClass(
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper",
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.NotificationHeaderViewWrapper"
)
/** 缓存的彩色 APP 图标 */
private var appIcons = ArrayMap<String, Drawable>()
@@ -175,8 +188,8 @@ class SystemUIHooker : YukiBaseHooker() {
/** 状态栏通知图标数组 */
private var notificationIconInstances = ArrayList<View>()
/** 缓存的通知小图标包装纸实例 */
private var notificationViewWrappers = ArraySet<Any>()
/** 通知栏通知控制器 */
private var notificationPresenter: Any? = null
/** 仅监听一次主题壁纸颜色变化 */
private var isWallpaperColorListenerSetUp = false
@@ -257,6 +270,18 @@ class SystemUIHooker : YukiBaseHooker() {
*/
private val StatusBarNotification.isOplusPush get() = opPkg == ANDROID_PACKAGE_NAME && opPkg != packageName
/**
* 判断通知背景是否为旧版本
* @return [Boolean]
*/
private val isOldNotificationBackground
get() = safeOfFalse {
NotificationBackgroundViewClass.clazz.hasMethod {
name = "drawCustom"
paramCount = 2
}
}
/**
* 打印日志
* @param tag 标识
@@ -334,8 +359,11 @@ class SystemUIHooker : YukiBaseHooker() {
/** 刷新通知小图标 */
private fun refreshNotificationIcons() = runInSafe {
NotificationHeaderViewWrapperClass.clazz.method { name = "resolveHeaderViews" }.also { result ->
notificationViewWrappers.takeIf { it.isNotEmpty() }?.forEach { result.get(it).call() }
notificationPresenter?.current {
method {
name = "updateNotificationsOnDensityOrFontScaleChanged"
emptyParam()
}.call()
}
}
@@ -503,6 +531,24 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
/**
* 设置通知面板背景透明度
* @param view 背景 View 实例
* @param drawable 背景实例
*/
private fun modifyNotifyPanelAlpha(view: View?, drawable: Drawable?) {
prefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA).also { isEnabled ->
/** 设置通知面板背景透明度 */
when {
isEnabled.not() -> drawable?.alpha = 255
view?.parent?.parent?.javaClass?.name?.contains(other = "ChildrenContainer") == true -> drawable?.alpha = 0
else -> drawable?.alpha = prefs.get(DataConst.NOTIFY_PANEL_ALPHA)
}
/** 移除阴影效果 */
if (isEnabled) view?.elevation = 0f
}
}
/** 缓存图标数据 */
private fun cachingIconDatas() {
iconDatas.clear()
@@ -549,7 +595,7 @@ class SystemUIHooker : YukiBaseHooker() {
}
beforeHook {
/** 是否移除 */
if (args().int() == 7 && prefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)) resultNull()
if (args().first().int() == 7 && prefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)) resultNull()
}
}
}
@@ -573,7 +619,7 @@ class SystemUIHooker : YukiBaseHooker() {
name = "isGrayscaleOplus"
param(ImageViewClass, OplusContrastColorUtilClass)
}
replaceAny { firstArgs<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } }
replaceAny { args().first().cast<ImageView>()?.let { isGrayscaleIcon(it.context, it.drawable) } }
}.ignoredHookingFailure()
}
/** 替换状态栏图标 */
@@ -588,7 +634,7 @@ class SystemUIHooker : YukiBaseHooker() {
.get(field { name = "iconBuilder" }.get(instance).cast()).cast<Context>()?.also { context ->
NotificationEntryClass.clazz.method {
name = "getSbn"
}.get(firstArgs).invoke<StatusBarNotification>()?.also { nf ->
}.get(args().first().any()).invoke<StatusBarNotification>()?.also { nf ->
nf.notification.smallIcon.loadDrawable(context).also { iconDrawable ->
compatStatusIcon(
context = context,
@@ -620,7 +666,7 @@ class SystemUIHooker : YukiBaseHooker() {
param(StatusBarNotificationClass)
}
afterHook {
if (firstArgs != null) instance<ImageView>().also {
if (args().first().any() != null) instance<ImageView>().also {
/** 注册壁纸颜色监听 */
registerWallpaperColorChanged(it)
/** 注册广播 */
@@ -629,6 +675,13 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
}
/** 注入通知控制器实例 */
StatusBarNotificationPresenterClass.hook {
injectMember {
allConstructors()
afterHook { notificationPresenter = instance }
}
}
/** 注入状态栏通知图标容器实例 */
OplusNotificationIconAreaControllerClass.hook {
injectMember {
@@ -651,6 +704,59 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
}
/** 替换通知面板背景 - 新版本 */
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>()) }
}
}.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>()) }
}
}.by { isOldNotificationBackground }
/** 替换通知面板背景 - 避免折叠展开通知二次修改通知面板背景 */
ExpandableNotificationRowClass.hook {
injectMember {
method {
name = "updateBackgroundForGroupState"
emptyParam()
}
beforeHook {
if (prefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA))
field { name = "mShowGroupBackgroundWhenExpanded" }.get(instance).setTrue()
}
}
}
/** 替换通知图标和样式 */
NotificationHeaderViewWrapperClass.hook {
injectMember {
@@ -684,11 +790,6 @@ class SystemUIHooker : YukiBaseHooker() {
}
}
}
/** 记录实例 */
injectMember {
constructor { param(ContextClass, ViewClass, ExpandableNotificationRowClass) }
afterHook { notificationViewWrappers.add(instance) }
}
}
/** 发送适配新的 APP 图标通知 */
PluginManagerImplClass.hook {
@@ -698,7 +799,7 @@ class SystemUIHooker : YukiBaseHooker() {
param(ContextClass, IntentClass)
}
afterHook {
if (isEnableHookColorNotifyIcon()) (lastArgs as? Intent)?.also {
if (isEnableHookColorNotifyIcon()) args().last().cast<Intent>()?.also {
if (it.action.equals(Intent.ACTION_PACKAGE_REPLACED).not() &&
it.getBooleanExtra(Intent.EXTRA_REPLACING, false)
) return@also
@@ -708,11 +809,11 @@ class SystemUIHooker : YukiBaseHooker() {
if (iconDatas.takeIf { e -> e.isNotEmpty() }
?.filter { e -> e.packageName == newPkgName }
.isNullOrEmpty()
) IconAdaptationTool.pushNewAppSupportNotify(firstArgs()!!, newPkgName)
) IconAdaptationTool.pushNewAppSupportNotify(args().first().cast()!!, newPkgName)
}
Intent.ACTION_PACKAGE_REMOVED ->
IconAdaptationTool.removeNewAppSupportNotify(
context = firstArgs()!!,
context = args().first().cast()!!,
packageName = it.data?.schemeSpecificPart ?: ""
)
}
@@ -728,7 +829,7 @@ class SystemUIHooker : YukiBaseHooker() {
param(ContextClass, IntentClass)
}
afterHook {
firstArgs<Context>()?.also {
args().first().cast<Context>()?.also {
/** 注册广播 */
registerReceiver(it)
/** 注册定时监听 */

View File

@@ -26,6 +26,8 @@ package com.fankes.coloros.notify.ui.activity
import android.content.ComponentName
import android.content.pm.PackageManager
import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener
import androidx.core.view.isVisible
import com.fankes.coloros.notify.BuildConfig
import com.fankes.coloros.notify.R
@@ -123,6 +125,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.notifyIconFixNotifyItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconAutoSyncItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconAutoSyncChildItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
binding.notifyPanelConfigSeekbar.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigTextPanel.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.devNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DEV_NOTIFY)
binding.crcpNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_CHANGECP_NOTIFY)
binding.dndNotifyConfigSwitch.isChecked = modulePrefs.get(DataConst.REMOVE_DNDALERT_NOTIFY)
@@ -133,6 +137,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.notifyIconFixSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
binding.notifyIconFixNotifySwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY)
binding.notifyIconAutoSyncSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
binding.notifyPanelConfigSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigSeekbar.progress = modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA)
binding.notifyPanelConfigText.text = modulePrefs.get(DataConst.NOTIFY_PANEL_ALPHA).toString()
binding.notifyIconAutoSyncText.text = notifyIconAutoSyncTime
binding.moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
@@ -190,12 +197,31 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
modulePrefs.put(DataConst.ENABLE_ANDROID12_STYLE, b)
SystemUITool.refreshSystemUI(context = this)
}
binding.notifyPanelConfigSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_PANEL_ALPHA, b)
binding.notifyPanelConfigTextPanel.isVisible = b
binding.notifyPanelConfigSeekbar.isVisible = b
SystemUITool.refreshSystemUI(context = this)
}
binding.notifyIconAutoSyncSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO, b)
binding.notifyIconAutoSyncChildItem.isVisible = b
SystemUITool.refreshSystemUI(context = this, isRefreshCacheOnly = true)
}
binding.notifyPanelConfigSeekbar.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
binding.notifyPanelConfigText.text = progress.toString()
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
modulePrefs.put(DataConst.NOTIFY_PANEL_ALPHA, seekBar.progress)
SystemUITool.refreshSystemUI(context = this@MainActivity)
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
})
/** 通知图标优化名单按钮点击事件 */
binding.notifyIconFixButton.setOnClickListener { navigate<ConfigureActivity>() }
/** 自动更新在线规则修改时间按钮点击事件 */

View File

@@ -28,11 +28,11 @@ import android.app.Activity
import android.os.Bundle
import android.view.View
import android.view.WindowManager
import com.fankes.coloros.notify.application.CNNApplication.Companion.appContext
import com.fankes.coloros.notify.ui.activity.base.BaseActivity
import com.fankes.coloros.notify.utils.factory.delayedRun
import com.fankes.coloros.notify.utils.tool.IconRuleManagerTool
import com.fankes.coloros.notify.utils.tool.SystemUITool
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
class NotifyIconRuleUpdateActivity : Activity() {
@@ -43,13 +43,13 @@ class NotifyIconRuleUpdateActivity : Activity() {
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window?.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
/** 注册 */
SystemUITool.register(context = this)
/** 检测运行状态 */
if (BaseActivity.isMainThreadRunning) {
finish()
return
}
/** 注册 */
SystemUITool.register(context = this)
/** 拉取云端数据 */
IconRuleManagerTool.sync(appContext) {
/** 刷新系统界面 */

View File

@@ -33,6 +33,7 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
@@ -49,13 +50,13 @@ import android.util.Base64
import android.widget.Toast
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.getSystemService
import com.fankes.coloros.notify.application.CNNApplication.Companion.appContext
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.factory.classOf
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.type.java.StringType
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
import com.topjohnwu.superuser.Shell
import java.io.ByteArrayOutputStream
import java.text.SimpleDateFormat
@@ -193,6 +194,14 @@ fun Context.findAppName(name: String) =
fun Context.findAppIcon(name: String) =
safeOfNull { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadIcon(packageManager) }
/**
* 获取 APP 是否为 DEBUG 版本
* @param name APP 包名
* @return [Boolean]
*/
fun Context.isAppDebuggable(name: String) =
safeOfFalse { (packageManager?.getPackageInfo(name, 0)?.applicationInfo?.flags?.and(ApplicationInfo.FLAG_DEBUGGABLE) ?: 0) != 0 }
/**
* 对数值自动补零
* @return [String]
@@ -320,12 +329,19 @@ fun findPropString(key: String, default: String = "") = safeOf(default) {
}
/**
* 执行命令 - su
* 是否有 Root 权限
* @return [Boolean]
*/
val isRootAccess get() = safeOfFalse { Shell.rootAccess() }
/**
* 执行命令
* @param cmd 命令
* @param isSu 是否使用 Root 权限执行 - 默认:是
* @return [String] 执行结果
*/
fun execShellSu(cmd: String) = safeOfNothing {
Shell.su(cmd).exec().out.let {
fun execShell(cmd: String, isSu: Boolean = true) = safeOfNothing {
(if (isSu) Shell.su(cmd) else Shell.sh(cmd)).exec().out.let {
if (it.isNotEmpty()) it[0].trim() else ""
}
}

View File

@@ -116,6 +116,7 @@ object IconAdaptationTool {
* @param packageName 安装的 APP 包名
*/
fun pushNewAppSupportNotify(context: Context, packageName: String) {
if (context.isAppDebuggable(packageName)) return
context.getSystemService(NotificationManager::class.java)?.apply {
createNotificationChannel(
NotificationChannel(

View File

@@ -26,11 +26,11 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.fankes.coloros.notify.application.CNNApplication.Companion.appContext
import com.fankes.coloros.notify.const.Const
import com.fankes.coloros.notify.utils.factory.*
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
/**
* 系统界面工具
@@ -47,7 +47,7 @@ object SystemUITool {
* 注册广播
* @param context 实例
*/
fun register(context: Context) {
fun register(context: Context) = runInSafe {
/** 注册广播检查模块激活状态 */
context.registerReceiver(moduleHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_HANDLER_RECEIVER) })
/** 注册广播通知系统界面改变 */
@@ -58,7 +58,7 @@ object SystemUITool {
* 取消注册广播
* @param context 实例
*/
fun unregister(context: Context) {
fun unregister(context: Context) = runInSafe {
context.unregisterReceiver(moduleHandlerReceiver)
context.unregisterReceiver(remindHandlerReceiver)
}
@@ -86,9 +86,9 @@ object SystemUITool {
msg = "你确定要立即重启系统界面吗?\n\n" +
"重启过程会黑屏并等待进入锁屏重新解锁。"
confirmButton {
execShellSu(cmd = "pgrep systemui").also { pid ->
execShell(cmd = "pgrep systemui").also { pid ->
if (pid.isNotBlank())
execShellSu(cmd = "kill -9 $pid")
execShell(cmd = "kill -9 $pid")
else toast(msg = "ROOT 权限获取失败")
}
}

View File

@@ -372,14 +372,14 @@
android:elevation="0dp"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="15dp"
android:paddingTop="15dp"
android:paddingRight="15dp">
android:paddingTop="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center|start">
android:gravity="center|start"
android:paddingLeft="15dp"
android:paddingRight="15dp">
<ImageView
android:layout_width="15dp"
@@ -402,6 +402,8 @@
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="启用 Android 12 通知栏风格"
android:textAllCaps="false"
android:textColor="@color/colorTextGray"
@@ -413,9 +415,93 @@
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="无论任何版本,开启后都将使用 Android 12 原生通知图标方式为通知栏推送的通知图标增加外部圆形轮廓。\n目标为 Android 12 的系统将自动使用系统主题色着色。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
<com.fankes.coloros.notify.ui.view.MaterialSwitch
android:id="@+id/notify_panel_config_switch"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="5dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="自定义通知面板背景透明度"
android:textAllCaps="false"
android:textColor="@color/colorTextGray"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatSeekBar
android:id="@+id/notify_panel_config_seekbar"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:max="255"
android:min="0" />
<LinearLayout
android:id="@+id/notify_panel_config_text_panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:paddingTop="5dp"
android:paddingBottom="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.75"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="当前值"
android:textColor="@color/colorTextGray"
android:textSize="13.5sp" />
<TextView
android:id="@+id/notify_panel_config_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center"
android:maxWidth="100dp"
android:singleLine="true"
android:text="%1"
android:textColor="@color/colorTextGray"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="开启自定义功能后你可以拖拽滑动条来调整通知面板的透明度0 为全透明255 为不透明。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:text="此功能为实验性功能,后期不一定继续维护,且仅在 ColorOS 12.1 测试通过,不能保证可以在任何系统版本中生效,以及和各种通知栏主题模块配合使用,如有冲突请关闭此功能或禁用相关重复功能的主题模块。\n已知问题悬浮通知也会被透明在透明度较低的时候下拉会有阴影光晕后期看需求再解决。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout

View File

@@ -1,12 +1,13 @@
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
ext {
appVersionName = "1.53"
appVersionCode = 10
appVersionName = "1.76"
appVersionCode = 14
enableR8 = true
}
task clean(type: Delete) {