mirror of
https://github.com/fankes/MIUINativeNotifyIcon.git
synced 2025-09-07 03:05:51 +08:00
Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
d14b2cb551
|
|||
a864d4aa32
|
|||
12029cf550
|
|||
ac4544e992
|
|||
7f0597f034
|
|||
a7c02467de
|
|||
107569607d
|
|||
5d099d2ec6
|
|||
45da218cc8
|
|||
9a8cc9378c
|
|||
d7620f62b1
|
|||
cf9f81be23
|
|||
2e1929f36e
|
|||
cb6cbf0398
|
|||
dbdd0fc514
|
|||
21f4ff9ad3
|
|||
1bc79056a9
|
|||
41cb741dff
|
|||
6578027a34
|
|||
01cb647f0c
|
|||
171cd6a6d1
|
|||
02f8852ab0
|
|||
826805c552 | |||
627697d586 | |||
f5615ff89f | |||
dd45e57b00 | |||
d73239de73 | |||
deb0ca794f | |||
84b3648626 | |||
ae8fb6514c | |||
197f427adb | |||
58a23b4537 | |||
72bbdb69a8 | |||
679ae26462 | |||
eefa7ee9e7 | |||
217d5d9bc3 | |||
4d1e383ef5 |
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -23,7 +23,7 @@
|
|||||||
<entry key="app/src/main/res/layout-w936dp/dia_status_icon_cout.xml" value="0.935546875" />
|
<entry key="app/src/main/res/layout-w936dp/dia_status_icon_cout.xml" value="0.935546875" />
|
||||||
<entry key="app/src/main/res/layout/activity_config.xml" value="0.42168674698795183" />
|
<entry key="app/src/main/res/layout/activity_config.xml" value="0.42168674698795183" />
|
||||||
<entry key="app/src/main/res/layout/activity_login.xml" value="0.4375" />
|
<entry key="app/src/main/res/layout/activity_login.xml" value="0.4375" />
|
||||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.32507739938080493" />
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.30387540746106484" />
|
||||||
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.375" />
|
<entry key="app/src/main/res/layout/adapter_config.xml" value="0.375" />
|
||||||
<entry key="app/src/main/res/layout/dia_icon_filter.xml" value="0.4307692307692308" />
|
<entry key="app/src/main/res/layout/dia_icon_filter.xml" value="0.4307692307692308" />
|
||||||
<entry key="app/src/main/res/layout/dia_icon_search.xml" value="0.4307692307692308" />
|
<entry key="app/src/main/res/layout/dia_icon_search.xml" value="0.4307692307692308" />
|
||||||
|
359
PRIVACY.md
Normal file
359
PRIVACY.md
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
### MIUI 原生通知图标 隐私政策
|
||||||
|
|
||||||
|
> 简体中文
|
||||||
|
|
||||||
|
版本:1.0
|
||||||
|
|
||||||
|
修订与生效日期:2022年4月25日
|
||||||
|
|
||||||
|
#### 前言
|
||||||
|
|
||||||
|
为帮助您使用 MIUI 原生通知图标产品(以下简称“本产品”)或服务,我们可能收集与提供服务相关的设备信息或申请设备权限,您有权拒绝或撤回授权;
|
||||||
|
|
||||||
|
我们采取了互联网业内标准的技术措施和数据安全措施来保护您的设备信息安全;
|
||||||
|
|
||||||
|
除非再次征得您的同意,我们不会将您的设备信息用于本政策未载明的其他目的;
|
||||||
|
|
||||||
|
在阅读本协议前,请确认您已年满 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 地址通常可用于识别设备连接至互联网时所在的位置。
|
||||||
|
|
||||||
|
信息收集技术: 我们在《MIUI 原生通知图标 隐私政策》中所述的“自动收集”包括以下方式: 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。
|
||||||
|
|
||||||
|
### MIUINativeNotifyIcon Privacy Policy
|
||||||
|
|
||||||
|
> English
|
||||||
|
|
||||||
|
Version: 1.0
|
||||||
|
|
||||||
|
Amendment and effective date: April 25, 2022
|
||||||
|
|
||||||
|
#### Preface
|
||||||
|
|
||||||
|
In order to help you use MIUINativeNotifyIcon 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 "MIUINativeNotifyIcon 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.
|
10
README.md
10
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[](https://github.com/fankes/MIUINativeNotifyIcon)
|
[](https://github.com/fankes/MIUINativeNotifyIcon)
|
||||||
[](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/LICENSE)
|
[](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/LICENSE)
|
||||||
[](https://github.com/fankes/MIUINativeNotifyIcon/releases)
|
[](https://github.com/fankes/MIUINativeNotifyIcon/releases)
|
||||||
[](https://github.com/fankes/MIUINativeNotifyIcon/releases)
|
[](https://github.com/fankes/MIUINativeNotifyIcon/releases)
|
||||||
[](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)
|
[](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)
|
||||||
[](https://t.me/XiaofangInternet)
|
[](https://t.me/XiaofangInternet)
|
||||||
@@ -33,8 +33,8 @@ Fix the native notification bar icon function abandoned by the MIUI development
|
|||||||
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
||||||
|
|
||||||
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)、
|
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.miui.notify/releases)、
|
||||||
[Release](https://github.com/fankes/MIUINativeNotifyIcon/releases)
|
[Release](https://github.com/fankes/MIUINativeNotifyIcon/releases)、[蓝奏云](https://fankes.lanzouy.com/b030o2e8h) 及**酷安应用市场**
|
||||||
及 [蓝奏云](https://fankes.lanzouy.com/b030o2e8h),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
||||||
|
|
||||||
## 贡献通知图标优化名单
|
## 贡献通知图标优化名单
|
||||||
|
|
||||||
@@ -106,6 +106,10 @@ MIUI 再不重写,怕是永远会变成安卓之光。雷军,金凡!!
|
|||||||
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<br/><br/>
|
- 工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。<br/><br/>
|
||||||
<img src="https://github.com/fankes/YuKiHookAPI/blob/master/img-src/wechat_code.jpg" width = "200" height = "200"/>
|
<img src="https://github.com/fankes/YuKiHookAPI/blob/master/img-src/wechat_code.jpg" width = "200" height = "200"/>
|
||||||
|
|
||||||
|
## 隐私政策
|
||||||
|
|
||||||
|
- [PRIVACY](https://github.com/fankes/MIUINativeNotifyIcon/blob/master/PRIVACY.md)
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
|
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'kotlin-android'
|
id '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 {
|
android {
|
||||||
@@ -25,20 +25,14 @@ android {
|
|||||||
versionCode rootProject.ext.appVersionCode
|
versionCode rootProject.ext.appVersionCode
|
||||||
versionName rootProject.ext.appVersionName
|
versionName rootProject.ext.appVersionName
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
freeCompilerArgs = [
|
|
||||||
'-Xno-param-assertions',
|
|
||||||
'-Xno-call-assertions',
|
|
||||||
'-Xno-receiver-assertions'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled rootProject.ext.enableR8
|
minifyEnabled rootProject.ext.enableR8
|
||||||
|
shrinkResources rootProject.ext.enableR8
|
||||||
|
zipAlignEnabled rootProject.ext.enableR8
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
@@ -49,40 +43,31 @@ android {
|
|||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '11'
|
jvmTarget = '11'
|
||||||
|
freeCompilerArgs = [
|
||||||
|
'-Xno-param-assertions',
|
||||||
|
'-Xno-call-assertions',
|
||||||
|
'-Xno-receiver-assertions'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
}
|
lintOptions {
|
||||||
|
checkReleaseBuilds false
|
||||||
/** 移除无效耗时 lint Task */
|
}
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly 'de.robv.android.xposed:api:82'
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
implementation 'com.highcapable.yukihookapi:api:1.0.75'
|
implementation 'com.highcapable.yukihookapi:api:1.0.92'
|
||||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.75'
|
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
|
||||||
implementation "com.github.topjohnwu.libsu:core:3.1.2"
|
implementation "com.github.topjohnwu.libsu:core:3.1.2"
|
||||||
implementation 'androidx.annotation:annotation:1.3.0'
|
implementation 'androidx.annotation:annotation:1.3.0'
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
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'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
8
app/proguard-rules.pro
vendored
8
app/proguard-rules.pro
vendored
@@ -20,7 +20,6 @@
|
|||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
-dontwarn
|
|
||||||
-ignorewarnings
|
-ignorewarnings
|
||||||
-optimizationpasses 10
|
-optimizationpasses 10
|
||||||
-dontusemixedcaseclassnames
|
-dontusemixedcaseclassnames
|
||||||
@@ -35,13 +34,6 @@
|
|||||||
-renamesourcefileattribute P
|
-renamesourcefileattribute P
|
||||||
-keepattributes SourceFile,LineNumberTable
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
-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 {
|
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
||||||
public static *** throwUninitializedProperty(...);
|
public static *** throwUninitializedProperty(...);
|
||||||
public static *** throwUninitializedPropertyAccessException(...);
|
public static *** throwUninitializedPropertyAccessException(...);
|
||||||
|
@@ -24,24 +24,13 @@
|
|||||||
|
|
||||||
package com.fankes.miui.notify.application
|
package com.fankes.miui.notify.application
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication
|
||||||
|
|
||||||
class MNNApplication : Application() {
|
class MNNApplication : ModuleApplication() {
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/** 全局静态实例 */
|
|
||||||
private var context: MNNApplication? = null
|
|
||||||
|
|
||||||
/** 调用全局静态实例 */
|
|
||||||
val appContext get() = context ?: error("App is death")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
/** 设置静态实例 */
|
|
||||||
context = this
|
|
||||||
/** 跟随系统夜间模式 */
|
/** 跟随系统夜间模式 */
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
}
|
}
|
||||||
|
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
|
||||||
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
|
||||||
* https://github.com/fankes/MIUINativeNotifyIcon
|
|
||||||
*
|
|
||||||
* 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/3/24.
|
|
||||||
*/
|
|
||||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
|
|
||||||
package com.fankes.miui.notify.const
|
|
||||||
|
|
||||||
import com.fankes.miui.notify.BuildConfig
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 存储一些静态编译后的值
|
|
||||||
*/
|
|
||||||
object Const {
|
|
||||||
|
|
||||||
/** 当前模块的包名 */
|
|
||||||
const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
|
|
||||||
|
|
||||||
/** 当前模块的版本名称 */
|
|
||||||
const val MODULE_VERSION_NAME = BuildConfig.VERSION_NAME
|
|
||||||
|
|
||||||
/** 当前模块的版本号 */
|
|
||||||
const val MODULE_VERSION_CODE = BuildConfig.VERSION_CODE
|
|
||||||
|
|
||||||
/** 当前模块的版本校验 */
|
|
||||||
const val MODULE_VERSION_VERIFY = "${MODULE_VERSION_NAME}_${MODULE_VERSION_CODE}_202204140309"
|
|
||||||
|
|
||||||
/** 当前模块的版本校验标签 */
|
|
||||||
const val MODULE_VERSION_VERIFY_TAG = "module_version_verify"
|
|
||||||
|
|
||||||
/** 发送通讯广播号标签 - 模块激活状态 */
|
|
||||||
const val ACTION_MODULE_CHECKING_RECEIVER = "mnn_module_checking_action"
|
|
||||||
|
|
||||||
/** 接收通讯广播号标签 - 模块激活状态 */
|
|
||||||
const val ACTION_MODULE_HANDLER_RECEIVER = "mnn_module_handler_action"
|
|
||||||
|
|
||||||
/** 发送通讯广播号标签 - 通知系统界面刷新 */
|
|
||||||
const val ACTION_REMIND_CHECKING_RECEIVER = "mnn_remind_checking_action"
|
|
||||||
|
|
||||||
/** 接收通讯广播号标签 - 通知系统界面刷新 */
|
|
||||||
const val ACTION_REMIND_HANDLER_RECEIVER = "mnn_remind_handler_action"
|
|
||||||
}
|
|
@@ -32,13 +32,17 @@ object DataConst {
|
|||||||
val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false)
|
val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false)
|
||||||
val ENABLE_COLOR_ICON_COMPAT = PrefsData("_color_icon_compat", false)
|
val ENABLE_COLOR_ICON_COMPAT = PrefsData("_color_icon_compat", false)
|
||||||
val ENABLE_NOTIFY_ICON_FIX = PrefsData("_notify_icon_fix", true)
|
val ENABLE_NOTIFY_ICON_FIX = PrefsData("_notify_icon_fix", true)
|
||||||
|
val ENABLE_NOTIFY_ICON_FORCE_APP_ICON = PrefsData("_notify_icon_force_app_icon", false)
|
||||||
val ENABLE_NOTIFY_ICON_FIX_NOTIFY = PrefsData("_notify_icon_fix_notify", true)
|
val ENABLE_NOTIFY_ICON_FIX_NOTIFY = PrefsData("_notify_icon_fix_notify", true)
|
||||||
val ENABLE_HOOK_STATUS_ICON_COUNT = PrefsData("_enable_hook_status_icon_count", true)
|
val ENABLE_HOOK_STATUS_ICON_COUNT = PrefsData("_enable_hook_status_icon_count", true)
|
||||||
val ENABLE_NOTIFY_ICON_FIX_AUTO = PrefsData("_enable_notify_icon_fix_auto", true)
|
val ENABLE_NOTIFY_ICON_FIX_AUTO = PrefsData("_enable_notify_icon_fix_auto", true)
|
||||||
|
val NOTIFY_ICON_CORNER = PrefsData("_notify_icon_corner", 15)
|
||||||
val NOTIFY_ICON_DATAS = PrefsData("_notify_icon_datas", "")
|
val NOTIFY_ICON_DATAS = PrefsData("_notify_icon_datas", "")
|
||||||
val NOTIFY_ICON_FIX_AUTO_TIME = PrefsData("_notify_icon_fix_auto_time", "07:00")
|
val NOTIFY_ICON_FIX_AUTO_TIME = PrefsData("_notify_icon_fix_auto_time", "07:00")
|
||||||
val HOOK_STATUS_ICON_COUNT = PrefsData("_hook_status_icon_count", 5)
|
val HOOK_STATUS_ICON_COUNT = PrefsData("_hook_status_icon_count", 5)
|
||||||
|
|
||||||
|
val IGNORED_ANDROID_VERSION_TO_LOW = PrefsData("_ignored_android_version_to_low", false)
|
||||||
|
|
||||||
val SOURCE_SYNC_WAY = PrefsData("_rule_source_sync_way", HookConst.TYPE_SOURCE_SYNC_WAY_1)
|
val SOURCE_SYNC_WAY = PrefsData("_rule_source_sync_way", HookConst.TYPE_SOURCE_SYNC_WAY_1)
|
||||||
val SOURCE_SYNC_WAY_CUSTOM_URL = PrefsData("_rule_source_sync_way_custom_url", "")
|
val SOURCE_SYNC_WAY_CUSTOM_URL = PrefsData("_rule_source_sync_way_custom_url", "")
|
||||||
}
|
}
|
@@ -33,10 +33,10 @@ import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
|||||||
import com.highcapable.yukihookapi.hook.factory.configs
|
import com.highcapable.yukihookapi.hook.factory.configs
|
||||||
import com.highcapable.yukihookapi.hook.factory.encase
|
import com.highcapable.yukihookapi.hook.factory.encase
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||||
|
|
||||||
@InjectYukiHookWithXposed
|
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||||
class HookEntry : YukiHookXposedInitProxy {
|
class HookEntry : IYukiHookXposedInit {
|
||||||
|
|
||||||
override fun onInit() = configs {
|
override fun onInit() = configs {
|
||||||
debugTag = "MIUINativeNotifyIcon"
|
debugTag = "MIUINativeNotifyIcon"
|
||||||
@@ -44,6 +44,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onHook() = encase {
|
override fun onHook() = encase {
|
||||||
|
loadApp(SYSTEMUI_PACKAGE_NAME) {
|
||||||
when {
|
when {
|
||||||
/** 不是 MIUI 系统停止 Hook */
|
/** 不是 MIUI 系统停止 Hook */
|
||||||
isNotMIUI -> loggerW(msg = "Aborted Hook -> This System is not MIUI")
|
isNotMIUI -> loggerW(msg = "Aborted Hook -> This System is not MIUI")
|
||||||
@@ -54,7 +55,8 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
/** Hook 被手动关闭停止 Hook */
|
/** Hook 被手动关闭停止 Hook */
|
||||||
prefs.get(DataConst.ENABLE_MODULE).not() -> loggerW(msg = "Aborted Hook -> Hook Closed")
|
prefs.get(DataConst.ENABLE_MODULE).not() -> loggerW(msg = "Aborted Hook -> Hook Closed")
|
||||||
/** 开始 Hook */
|
/** 开始 Hook */
|
||||||
else -> loadApp(SYSTEMUI_PACKAGE_NAME, SystemUIHooker())
|
else -> loadHooker(SystemUIHooker)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -20,14 +20,14 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/3/25.
|
* This file is Created by fankes on 2022/3/25.
|
||||||
*/
|
*/
|
||||||
|
@file:Suppress("StaticFieldLeak")
|
||||||
|
|
||||||
package com.fankes.miui.notify.hook.entity
|
package com.fankes.miui.notify.hook.entity
|
||||||
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.WallpaperManager
|
import android.app.WallpaperManager
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Outline
|
import android.graphics.Outline
|
||||||
@@ -35,6 +35,7 @@ import android.graphics.drawable.BitmapDrawable
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.SystemClock
|
||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -43,7 +44,6 @@ import android.widget.ImageView
|
|||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import com.fankes.miui.notify.bean.IconDataBean
|
import com.fankes.miui.notify.bean.IconDataBean
|
||||||
import com.fankes.miui.notify.const.Const
|
|
||||||
import com.fankes.miui.notify.data.DataConst
|
import com.fankes.miui.notify.data.DataConst
|
||||||
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
||||||
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
import com.fankes.miui.notify.hook.factory.isAppNotifyHookAllOf
|
||||||
@@ -53,6 +53,7 @@ import com.fankes.miui.notify.utils.drawable.drawabletoolbox.DrawableBuilder
|
|||||||
import com.fankes.miui.notify.utils.factory.*
|
import com.fankes.miui.notify.utils.factory.*
|
||||||
import com.fankes.miui.notify.utils.tool.BitmapCompatTool
|
import com.fankes.miui.notify.utils.tool.BitmapCompatTool
|
||||||
import com.fankes.miui.notify.utils.tool.IconAdaptationTool
|
import com.fankes.miui.notify.utils.tool.IconAdaptationTool
|
||||||
|
import com.fankes.miui.notify.utils.tool.SystemUITool
|
||||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||||
import com.highcapable.yukihookapi.hook.factory.*
|
import com.highcapable.yukihookapi.hook.factory.*
|
||||||
@@ -65,9 +66,7 @@ import com.highcapable.yukihookapi.hook.type.java.IntType
|
|||||||
/**
|
/**
|
||||||
* 系统界面核心 Hook 类
|
* 系统界面核心 Hook 类
|
||||||
*/
|
*/
|
||||||
class SystemUIHooker : YukiBaseHooker() {
|
object SystemUIHooker : YukiBaseHooker() {
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/** MIUI 新版本存在的类 */
|
/** MIUI 新版本存在的类 */
|
||||||
private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
|
private const val SystemUIApplicationClass = "$SYSTEMUI_PACKAGE_NAME.SystemUIApplication"
|
||||||
@@ -141,7 +140,6 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification",
|
"$SYSTEMUI_PACKAGE_NAME.statusbar.notification.ExpandedNotification",
|
||||||
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.ExpandedNotification"
|
"$SYSTEMUI_PACKAGE_NAME.miui.statusbar.ExpandedNotification"
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
/** 缓存的通知图标优化数组 */
|
/** 缓存的通知图标优化数组 */
|
||||||
private var iconDatas = ArrayList<IconDataBean>()
|
private var iconDatas = ArrayList<IconDataBean>()
|
||||||
@@ -161,65 +159,6 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
/** 仅监听一次主题壁纸颜色变化 */
|
/** 仅监听一次主题壁纸颜色变化 */
|
||||||
private var isWallpaperColorListenerSetUp = false
|
private var isWallpaperColorListenerSetUp = false
|
||||||
|
|
||||||
/** 是否已经注册广播 */
|
|
||||||
private var isRegisterReceiver = false
|
|
||||||
|
|
||||||
/** 用户解锁屏幕广播接收器 */
|
|
||||||
private val userPresentReceiver by lazy {
|
|
||||||
object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
|
|
||||||
if (isUsingCachingMethod) refreshStatusBarIcons()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 模块广播接收器 */
|
|
||||||
private val moduleCheckingReceiver by lazy {
|
|
||||||
object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
context?.sendBroadcast(Intent().apply {
|
|
||||||
action = Const.ACTION_MODULE_HANDLER_RECEIVER
|
|
||||||
putExtra("isRegular", true)
|
|
||||||
putExtra("isValied", intent?.isValiedModule)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通知广播接收器 */
|
|
||||||
private val remindCheckingReceiver by lazy {
|
|
||||||
object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) = delayedRun(ms = 300) {
|
|
||||||
if (intent?.isValiedModule == true)
|
|
||||||
recachingPrefs(intent.getBooleanExtra("isRefreshCacheOnly", false))
|
|
||||||
context?.sendBroadcast(Intent().apply {
|
|
||||||
action = Const.ACTION_REMIND_HANDLER_RECEIVER
|
|
||||||
putExtra("isGrasp", true)
|
|
||||||
putExtra("isValied", intent?.isValiedModule)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断模块和宿主版本是否一致
|
|
||||||
* @return [Boolean]
|
|
||||||
*/
|
|
||||||
private val Intent.isValiedModule get() = getStringExtra(Const.MODULE_VERSION_VERIFY_TAG) == Const.MODULE_VERSION_VERIFY
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 注册广播接收器
|
|
||||||
* @param context 实例
|
|
||||||
*/
|
|
||||||
private fun registerReceiver(context: Context) {
|
|
||||||
if (isRegisterReceiver) return
|
|
||||||
context.registerReceiver(userPresentReceiver, IntentFilter().apply { addAction(Intent.ACTION_USER_PRESENT) })
|
|
||||||
context.registerReceiver(moduleCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_CHECKING_RECEIVER) })
|
|
||||||
context.registerReceiver(remindCheckingReceiver, IntentFilter().apply { addAction(Const.ACTION_REMIND_CHECKING_RECEIVER) })
|
|
||||||
isRegisterReceiver = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否启用通知图标优化功能
|
* 是否启用通知图标优化功能
|
||||||
* @param isHooking 是否判断启用通知功能 - 默认:是
|
* @param isHooking 是否判断启用通知功能 - 默认:是
|
||||||
@@ -461,6 +400,35 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
isExpanded: Boolean = true,
|
isExpanded: Boolean = true,
|
||||||
isUseAndroid12Style: Boolean = isUpperOfAndroidS,
|
isUseAndroid12Style: Boolean = isUpperOfAndroidS,
|
||||||
) = runInSafe(msg = "compatNotifyIcon") {
|
) = runInSafe(msg = "compatNotifyIcon") {
|
||||||
|
/**
|
||||||
|
* 设置默认通知图标
|
||||||
|
* @param drawable 通知图标
|
||||||
|
*/
|
||||||
|
fun setDefaultNotifyIcon(drawable: Drawable?) {
|
||||||
|
iconImageView.apply {
|
||||||
|
/** 重新设置图标 */
|
||||||
|
setImageDrawable(drawable)
|
||||||
|
/** 设置裁切到边界 */
|
||||||
|
clipToOutline = true
|
||||||
|
/** 设置一个圆角轮廓裁切 */
|
||||||
|
outlineProvider = object : ViewOutlineProvider() {
|
||||||
|
override fun getOutline(view: View, out: Outline) {
|
||||||
|
out.setRoundRect(
|
||||||
|
0, 0,
|
||||||
|
view.width, view.height, 5.dpFloat(context)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isUseAndroid12Style) {
|
||||||
|
/** 清除原生的背景边距 */
|
||||||
|
setPadding(0, 0, 0, 0)
|
||||||
|
/** 清除原生的主题色背景圆圈颜色 */
|
||||||
|
background = null
|
||||||
|
}
|
||||||
|
/** 清除遮罩颜色 */
|
||||||
|
colorFilter = null
|
||||||
|
}
|
||||||
|
}
|
||||||
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
/** 获取通知对象 - 由于 MIUI 的版本迭代不规范性可能是空的 */
|
||||||
expandedNf?.let { notifyInstance ->
|
expandedNf?.let { notifyInstance ->
|
||||||
|
|
||||||
@@ -470,6 +438,9 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
/** 旧版风格反色 */
|
/** 旧版风格反色 */
|
||||||
val oldStyle = if (context.isNotSystemInDarkMode) 0xFF707070.toInt() else Color.WHITE
|
val oldStyle = if (context.isNotSystemInDarkMode) 0xFF707070.toInt() else Color.WHITE
|
||||||
|
|
||||||
|
/** 通知图标边框圆角大小 */
|
||||||
|
val iconCorner = prefs.get(DataConst.NOTIFY_ICON_CORNER)
|
||||||
|
|
||||||
/** 通知图标原始颜色 */
|
/** 通知图标原始颜色 */
|
||||||
val iconColor = notifyInstance.notification.color
|
val iconColor = notifyInstance.notification.color
|
||||||
|
|
||||||
@@ -504,7 +475,10 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
/** 打印日志 */
|
/** 打印日志 */
|
||||||
printLogcat(tag = "NotifyIcon", context, notifyInstance, isCustom = customIcon != null, isGrayscaleIcon)
|
printLogcat(tag = "NotifyIcon", context, notifyInstance, isCustom = customIcon != null, isGrayscaleIcon)
|
||||||
/** 处理自定义通知图标优化 */
|
/** 处理自定义通知图标优化 */
|
||||||
if (customIcon != null) iconImageView.apply {
|
when {
|
||||||
|
prefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON) && isEnableHookColorNotifyIcon(isHooking = false) ->
|
||||||
|
setDefaultNotifyIcon(context.findAppIcon(notifyInstance.nfPkgName))
|
||||||
|
customIcon != null -> iconImageView.apply {
|
||||||
/** 设置不要裁切到边界 */
|
/** 设置不要裁切到边界 */
|
||||||
clipToOutline = false
|
clipToOutline = false
|
||||||
/** 设置自定义小图标 */
|
/** 设置自定义小图标 */
|
||||||
@@ -514,12 +488,14 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
/** Android 12 设置图标外圈颜色 */
|
/** Android 12 设置图标外圈颜色 */
|
||||||
if (isUseAndroid12Style && customIconColor != 0)
|
if (isUseAndroid12Style && customIconColor != 0)
|
||||||
background = DrawableBuilder()
|
background = DrawableBuilder()
|
||||||
.rounded()
|
.rectangle()
|
||||||
|
.cornerRadius(iconCorner.dp(context))
|
||||||
.solidColor(if (context.isSystemInDarkMode) customIconColor.brighter else customIconColor)
|
.solidColor(if (context.isSystemInDarkMode) customIconColor.brighter else customIconColor)
|
||||||
.build()
|
.build()
|
||||||
/** 设置原生的背景边距 */
|
/** 设置原生的背景边距 */
|
||||||
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
|
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
|
||||||
} else {
|
}
|
||||||
|
else -> {
|
||||||
/** 重新设置图标 - 防止系统更改它 */
|
/** 重新设置图标 - 防止系统更改它 */
|
||||||
iconImageView.setImageDrawable(iconDrawable)
|
iconImageView.setImageDrawable(iconDrawable)
|
||||||
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
/** 判断如果是灰度图标就给他设置一个白色颜色遮罩 */
|
||||||
@@ -532,34 +508,14 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
(if (hasIconColor) iconColor else context.systemAccentColor).also {
|
(if (hasIconColor) iconColor else context.systemAccentColor).also {
|
||||||
if (isUseAndroid12Style)
|
if (isUseAndroid12Style)
|
||||||
background = DrawableBuilder()
|
background = DrawableBuilder()
|
||||||
.rounded()
|
.rectangle()
|
||||||
|
.cornerRadius(iconCorner.dp(context))
|
||||||
.solidColor(if (context.isSystemInDarkMode) it.brighter else it)
|
.solidColor(if (context.isSystemInDarkMode) it.brighter else it)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
/** 设置原生的背景边距 */
|
/** 设置原生的背景边距 */
|
||||||
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
|
if (isUseAndroid12Style) setPadding(4.dp(context), 4.dp(context), 4.dp(context), 4.dp(context))
|
||||||
} else iconImageView.apply {
|
} else setDefaultNotifyIcon(notifyInstance.compatPushingIcon(context, iconDrawable))
|
||||||
/** 重新设置图标 */
|
|
||||||
setImageDrawable(notifyInstance.compatPushingIcon(context, iconDrawable))
|
|
||||||
/** 设置裁切到边界 */
|
|
||||||
clipToOutline = true
|
|
||||||
/** 设置一个圆角轮廓裁切 */
|
|
||||||
outlineProvider = object : ViewOutlineProvider() {
|
|
||||||
override fun getOutline(view: View, out: Outline) {
|
|
||||||
out.setRoundRect(
|
|
||||||
0, 0,
|
|
||||||
view.width, view.height, 5.dpFloat(context)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isUseAndroid12Style) {
|
|
||||||
/** 清除原生的背景边距 */
|
|
||||||
setPadding(0, 0, 0, 0)
|
|
||||||
/** 清除原生的主题色背景圆圈颜色 */
|
|
||||||
background = null
|
|
||||||
}
|
|
||||||
/** 清除遮罩颜色 */
|
|
||||||
colorFilter = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -633,6 +589,14 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(this).self)
|
.get(NotificationViewWrapperClass.clazz.field { name = "mRow" }.get(this).self)
|
||||||
.invoke<StatusBarNotification>()
|
.invoke<StatusBarNotification>()
|
||||||
|
|
||||||
|
/** 注册 */
|
||||||
|
private fun register() {
|
||||||
|
/** 解锁后重新刷新状态栏图标防止系统重新设置它 */
|
||||||
|
onAppLifecycle { registerReceiver(Intent.ACTION_USER_PRESENT) { _, _ -> if (isUsingCachingMethod) refreshStatusBarIcons() } }
|
||||||
|
/** 刷新图标缓存 */
|
||||||
|
SystemUITool.Host.onRefreshSystemUI(param = this) { recachingPrefs(it) }
|
||||||
|
}
|
||||||
|
|
||||||
/** 缓存图标数据 */
|
/** 缓存图标数据 */
|
||||||
private fun cachingIconDatas() {
|
private fun cachingIconDatas() {
|
||||||
iconDatas.clear()
|
iconDatas.clear()
|
||||||
@@ -647,17 +611,25 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
/**
|
/**
|
||||||
* 刷新缓存数据
|
* 刷新缓存数据
|
||||||
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
|
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
|
||||||
|
* @return [Boolean] 是否成功
|
||||||
*/
|
*/
|
||||||
private fun recachingPrefs(isRefreshCacheOnly: Boolean = false) {
|
private fun recachingPrefs(isRefreshCacheOnly: Boolean = false): Boolean {
|
||||||
|
/** 必要的延迟防止 Sp 存储不刷新 */
|
||||||
|
SystemClock.sleep(100)
|
||||||
|
/** 获取可读写状态 */
|
||||||
|
return prefs.isXSharePrefsReadable.also {
|
||||||
isUsingCachingMethod = true
|
isUsingCachingMethod = true
|
||||||
prefs.clearCache()
|
prefs.clearCache()
|
||||||
cachingIconDatas()
|
cachingIconDatas()
|
||||||
if (isRefreshCacheOnly) return
|
if (isRefreshCacheOnly) return@also
|
||||||
refreshStatusBarIcons()
|
refreshStatusBarIcons()
|
||||||
refreshNotificationIcons()
|
refreshNotificationIcons()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onHook() {
|
override fun onHook() {
|
||||||
|
/** 注册 */
|
||||||
|
register()
|
||||||
/** 缓存图标数据 */
|
/** 缓存图标数据 */
|
||||||
cachingIconDatas()
|
cachingIconDatas()
|
||||||
/** 注入 MIUI 自己增加的一个工具类 */
|
/** 注入 MIUI 自己增加的一个工具类 */
|
||||||
@@ -738,12 +710,8 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
afterHook {
|
afterHook {
|
||||||
if (args[0] != null) instance<ImageView>().also {
|
|
||||||
/** 注册壁纸颜色监听 */
|
/** 注册壁纸颜色监听 */
|
||||||
registerWallpaperColorChanged(it)
|
if (args().first().any() != null) instance<ImageView>().also { registerWallpaperColorChanged(it) }
|
||||||
/** 注册广播 */
|
|
||||||
registerReceiver(it.context)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -921,8 +889,6 @@ class SystemUIHooker : YukiBaseHooker() {
|
|||||||
method { name = "updateTime" }
|
method { name = "updateTime" }
|
||||||
afterHook {
|
afterHook {
|
||||||
instance<View>().context.also {
|
instance<View>().context.also {
|
||||||
/** 注册广播 */
|
|
||||||
registerReceiver(it)
|
|
||||||
/** 注册定时监听 */
|
/** 注册定时监听 */
|
||||||
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
|
if (isEnableHookColorNotifyIcon() && prefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO))
|
||||||
IconAdaptationTool.prepareAutoUpdateIconRule(
|
IconAdaptationTool.prepareAutoUpdateIconRule(
|
||||||
|
@@ -43,7 +43,7 @@ import com.fankes.miui.notify.ui.activity.base.BaseActivity
|
|||||||
import com.fankes.miui.notify.utils.factory.*
|
import com.fankes.miui.notify.utils.factory.*
|
||||||
import com.fankes.miui.notify.utils.tool.IconRuleManagerTool
|
import com.fankes.miui.notify.utils.tool.IconRuleManagerTool
|
||||||
import com.fankes.miui.notify.utils.tool.SystemUITool
|
import com.fankes.miui.notify.utils.tool.SystemUITool
|
||||||
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
|
|
||||||
class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
|||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
/** 检查激活状态 */
|
/** 检查激活状态 */
|
||||||
if (isXposedModuleActive.not()) {
|
if (YukiHookAPI.Status.isXposedModuleActive.not()) {
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "模块没有激活"
|
title = "模块没有激活"
|
||||||
msg = "模块没有激活,你无法使用这里的功能,请先激活模块。"
|
msg = "模块没有激活,你无法使用这里的功能,请先激活模块。"
|
||||||
@@ -154,9 +154,20 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
|||||||
holder.adpAppAllSwitch.isChecked = isAppNotifyHookAllOf(it)
|
holder.adpAppAllSwitch.isChecked = isAppNotifyHookAllOf(it)
|
||||||
holder.adpAppAllSwitch.setOnCheckedChangeListener { btn, b ->
|
holder.adpAppAllSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
|
fun saveState() {
|
||||||
putAppNotifyHookAllOf(it, b)
|
putAppNotifyHookAllOf(it, b)
|
||||||
SystemUITool.refreshSystemUI(context = this@ConfigureActivity)
|
SystemUITool.refreshSystemUI(context = this@ConfigureActivity)
|
||||||
}
|
}
|
||||||
|
if (b) showDialog {
|
||||||
|
title = "全部替换"
|
||||||
|
msg = "此功能仅针对严重不遵守规范的 APP 通知图标才需要开启,例如:APP 推送通知后无法识别出现的黑白块图标。\n\n" +
|
||||||
|
"此功能在一般情况下请保持关闭并跟随在线规则的配置,并不要随意改变此配置," +
|
||||||
|
"开启后 APP 的通知图标可能会被规则破坏,你确定还要开启吗?"
|
||||||
|
confirmButton { saveState() }
|
||||||
|
cancelButton { btn.isChecked = btn.isChecked.not() }
|
||||||
|
noCancelable()
|
||||||
|
} else saveState()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return cView!!
|
return cView!!
|
||||||
}
|
}
|
||||||
@@ -176,7 +187,13 @@ class ConfigureActivity : BaseActivity<ActivityConfigBinding>() {
|
|||||||
}
|
}
|
||||||
/** 设置点击事件 */
|
/** 设置点击事件 */
|
||||||
binding.configCbrButton.setOnClickListener {
|
binding.configCbrButton.setOnClickListener {
|
||||||
openBrowser(url = "https://github.com/fankes/AndroidNotifyIconAdapt/blob/main/CONTRIBUTING.md")
|
showDialog {
|
||||||
|
title = "感谢你的贡献"
|
||||||
|
msg = "通知图标优化名单需要大家的共同维护才能得以完善,请选择你的贡献方式。"
|
||||||
|
confirmButton(text = "贡献规则") { openBrowser(url = "https://github.com/fankes/AndroidNotifyIconAdapt/blob/main/CONTRIBUTING.md") }
|
||||||
|
cancelButton(text = "请求适配") { openBrowser(url = "https://github.com/fankes/MIUINativeNotifyIcon/issues/new/choose") }
|
||||||
|
neutralButton(text = "暂时不用")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/** 装载数据 */
|
/** 装载数据 */
|
||||||
mockLocalData()
|
mockLocalData()
|
||||||
|
@@ -26,10 +26,11 @@ package com.fankes.miui.notify.ui.activity
|
|||||||
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.widget.SeekBar
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import com.fankes.miui.notify.BuildConfig
|
||||||
import com.fankes.miui.notify.R
|
import com.fankes.miui.notify.R
|
||||||
import com.fankes.miui.notify.const.Const
|
|
||||||
import com.fankes.miui.notify.data.DataConst
|
import com.fankes.miui.notify.data.DataConst
|
||||||
import com.fankes.miui.notify.databinding.ActivityMainBinding
|
import com.fankes.miui.notify.databinding.ActivityMainBinding
|
||||||
import com.fankes.miui.notify.databinding.DiaStatusIconCountBinding
|
import com.fankes.miui.notify.databinding.DiaStatusIconCountBinding
|
||||||
@@ -38,9 +39,9 @@ import com.fankes.miui.notify.ui.activity.base.BaseActivity
|
|||||||
import com.fankes.miui.notify.utils.factory.*
|
import com.fankes.miui.notify.utils.factory.*
|
||||||
import com.fankes.miui.notify.utils.tool.GithubReleaseTool
|
import com.fankes.miui.notify.utils.tool.GithubReleaseTool
|
||||||
import com.fankes.miui.notify.utils.tool.SystemUITool
|
import com.fankes.miui.notify.utils.tool.SystemUITool
|
||||||
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive
|
import com.fankes.miui.notify.utils.tool.YukiPromoteTool
|
||||||
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
internal var isActivityLive = false
|
internal var isActivityLive = false
|
||||||
|
|
||||||
/** 模块版本 */
|
/** 模块版本 */
|
||||||
private const val moduleVersion = Const.MODULE_VERSION_NAME
|
private const val moduleVersion = BuildConfig.VERSION_NAME
|
||||||
|
|
||||||
/** 预发布的版本标识 */
|
/** 预发布的版本标识 */
|
||||||
private const val pendingFlag = ""
|
private const val pendingFlag = ""
|
||||||
@@ -105,7 +106,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
noCancelable()
|
noCancelable()
|
||||||
}
|
}
|
||||||
/** 判断是否 Hook */
|
/** 判断是否 Hook */
|
||||||
isXposedModuleActive -> {
|
YukiHookAPI.Status.isXposedModuleActive -> {
|
||||||
if (IconPackParams(context = this).iconDatas.isEmpty() && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX))
|
if (IconPackParams(context = this).iconDatas.isEmpty() && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX))
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "配置通知图标优化名单"
|
title = "配置通知图标优化名单"
|
||||||
@@ -123,6 +124,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
cancelButton()
|
cancelButton()
|
||||||
noCancelable()
|
noCancelable()
|
||||||
}
|
}
|
||||||
|
if (isLowerAndroidR && modulePrefs.get(DataConst.IGNORED_ANDROID_VERSION_TO_LOW).not())
|
||||||
|
showDialog {
|
||||||
|
title = "Android 版本过低"
|
||||||
|
msg = "你当前使用的 Android 版本过低,模块的部分功能可能会发生问题," +
|
||||||
|
"由于设备有限,无法逐一调试,若有好的建议可向我们贡献代码提交适配请求,建议在 Android 11 及以上版本中使用效果最佳。"
|
||||||
|
confirmButton(text = "我知道了") { modulePrefs.put(DataConst.IGNORED_ANDROID_VERSION_TO_LOW, value = true) }
|
||||||
|
noCancelable()
|
||||||
|
}
|
||||||
|
/** 推广、恰饭 */
|
||||||
|
YukiPromoteTool.promote(context = this)
|
||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
showDialog {
|
showDialog {
|
||||||
@@ -141,6 +152,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
binding.statusIconCountItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
|
binding.statusIconCountItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
|
||||||
binding.notifyIconConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
|
binding.notifyIconConfigItem.isVisible = modulePrefs.get(DataConst.ENABLE_MODULE)
|
||||||
binding.notifyIconFixButton.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
binding.notifyIconFixButton.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
||||||
|
binding.notifyIconCustomCornerItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX) &&
|
||||||
|
modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON).not()
|
||||||
|
binding.notifyIconForceAppIconItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
||||||
binding.notifyIconFixNotifyItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
binding.notifyIconFixNotifyItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
||||||
binding.notifyIconAutoSyncItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
binding.notifyIconAutoSyncItem.isVisible = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
||||||
binding.statusIconCountSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HOOK_STATUS_ICON_COUNT)
|
binding.statusIconCountSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HOOK_STATUS_ICON_COUNT)
|
||||||
@@ -151,8 +165,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON)
|
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON)
|
||||||
binding.colorIconCompatSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_COLOR_ICON_COMPAT)
|
binding.colorIconCompatSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_COLOR_ICON_COMPAT)
|
||||||
binding.notifyIconFixSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
binding.notifyIconFixSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX)
|
||||||
|
binding.notifyIconForceAppIconSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON)
|
||||||
binding.notifyIconFixNotifySwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY)
|
binding.notifyIconFixNotifySwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY)
|
||||||
binding.notifyIconAutoSyncSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
|
binding.notifyIconAutoSyncSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FIX_AUTO)
|
||||||
|
binding.notifyIconCustomCornerSeekbar.progress = modulePrefs.get(DataConst.NOTIFY_ICON_CORNER)
|
||||||
|
binding.notifyIconCustomCornerText.text = "${modulePrefs.get(DataConst.NOTIFY_ICON_CORNER)} dp"
|
||||||
binding.statusIconCountText.text = statusBarIconCount.toString()
|
binding.statusIconCountText.text = statusBarIconCount.toString()
|
||||||
binding.notifyIconAutoSyncText.text = notifyIconAutoSyncTime
|
binding.notifyIconAutoSyncText.text = notifyIconAutoSyncTime
|
||||||
binding.moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.moduleEnableSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
@@ -193,10 +210,29 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX, b)
|
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX, b)
|
||||||
binding.notifyIconFixButton.isVisible = b
|
binding.notifyIconFixButton.isVisible = b
|
||||||
|
binding.notifyIconCustomCornerItem.isVisible = b && modulePrefs.get(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON).not()
|
||||||
|
binding.notifyIconForceAppIconItem.isVisible = b
|
||||||
binding.notifyIconFixNotifyItem.isVisible = b
|
binding.notifyIconFixNotifyItem.isVisible = b
|
||||||
binding.notifyIconAutoSyncItem.isVisible = b
|
binding.notifyIconAutoSyncItem.isVisible = b
|
||||||
SystemUITool.refreshSystemUI(context = this)
|
SystemUITool.refreshSystemUI(context = this)
|
||||||
}
|
}
|
||||||
|
binding.notifyIconForceAppIconSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
|
fun saveState() {
|
||||||
|
binding.notifyIconCustomCornerItem.isVisible = b.not()
|
||||||
|
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FORCE_APP_ICON, b)
|
||||||
|
SystemUITool.refreshSystemUI(context = this)
|
||||||
|
}
|
||||||
|
if (b) showDialog {
|
||||||
|
title = "破坏性功能警告"
|
||||||
|
msg = "开启这个功能后,任何通知栏中的通知图标都会被强制替换为当前推送通知的 APP 的图标," +
|
||||||
|
"某些系统级别的 APP 通知图标可能会显示异常或发生图标丢失。\n\n" +
|
||||||
|
"此功能仅面向一些追求图标美观度的用户,我们不推荐开启这个功能,且发生任何 BUG 都不会去修复,仍然继续开启吗?"
|
||||||
|
confirmButton { saveState() }
|
||||||
|
cancelButton { btn.isChecked = btn.isChecked.not() }
|
||||||
|
noCancelable()
|
||||||
|
} else saveState()
|
||||||
|
}
|
||||||
binding.notifyIconFixNotifySwitch.setOnCheckedChangeListener { btn, b ->
|
binding.notifyIconFixNotifySwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY, b)
|
modulePrefs.put(DataConst.ENABLE_NOTIFY_ICON_FIX_NOTIFY, b)
|
||||||
@@ -208,6 +244,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
binding.notifyIconAutoSyncChildItem.isVisible = b
|
binding.notifyIconAutoSyncChildItem.isVisible = b
|
||||||
SystemUITool.refreshSystemUI(context = this, isRefreshCacheOnly = true)
|
SystemUITool.refreshSystemUI(context = this, isRefreshCacheOnly = true)
|
||||||
}
|
}
|
||||||
|
binding.notifyIconCustomCornerSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||||
|
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||||
|
binding.notifyIconCustomCornerText.text = "$progress dp"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||||
|
modulePrefs.put(DataConst.NOTIFY_ICON_CORNER, seekBar.progress)
|
||||||
|
SystemUITool.refreshSystemUI(context = this@MainActivity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
|
||||||
|
})
|
||||||
/** 通知图标优化名单按钮点击事件 */
|
/** 通知图标优化名单按钮点击事件 */
|
||||||
binding.notifyIconFixButton.setOnClickListener { navigate<ConfigureActivity>() }
|
binding.notifyIconFixButton.setOnClickListener { navigate<ConfigureActivity>() }
|
||||||
/** 设置警告 */
|
/** 设置警告 */
|
||||||
@@ -274,36 +322,36 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
private fun refreshModuleStatus() {
|
private fun refreshModuleStatus() {
|
||||||
binding.mainLinStatus.setBackgroundResource(
|
binding.mainLinStatus.setBackgroundResource(
|
||||||
when {
|
when {
|
||||||
isXposedModuleActive && (isModuleRegular.not() || isModuleValied.not()) -> R.drawable.bg_yellow_round
|
YukiHookAPI.Status.isXposedModuleActive && (isModuleRegular.not() || isModuleValied.not()) -> R.drawable.bg_yellow_round
|
||||||
isXposedModuleActive -> R.drawable.bg_green_round
|
YukiHookAPI.Status.isXposedModuleActive -> R.drawable.bg_green_round
|
||||||
else -> R.drawable.bg_dark_round
|
else -> R.drawable.bg_dark_round
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
binding.mainImgStatus.setImageResource(
|
binding.mainImgStatus.setImageResource(
|
||||||
when {
|
when {
|
||||||
isXposedModuleActive -> R.mipmap.ic_success
|
YukiHookAPI.Status.isXposedModuleActive -> R.mipmap.ic_success
|
||||||
else -> R.mipmap.ic_warn
|
else -> R.mipmap.ic_warn
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
binding.mainTextStatus.text =
|
binding.mainTextStatus.text =
|
||||||
when {
|
when {
|
||||||
isXposedModuleActive && isModuleRegular.not() && modulePrefs.get(DataConst.ENABLE_MODULE).not() -> "模块已停用"
|
YukiHookAPI.Status.isXposedModuleActive && isModuleRegular.not() && modulePrefs.get(DataConst.ENABLE_MODULE).not() -> "模块已停用"
|
||||||
isXposedModuleActive && isModuleRegular.not() -> "模块已激活,请重启系统界面"
|
YukiHookAPI.Status.isXposedModuleActive && isModuleRegular.not() -> "模块已激活,请重启系统界面"
|
||||||
isXposedModuleActive && isModuleValied.not() -> "模块已更新,请重启系统界面"
|
YukiHookAPI.Status.isXposedModuleActive && isModuleValied.not() -> "模块已更新,请重启系统界面"
|
||||||
isXposedModuleActive -> "模块已激活"
|
YukiHookAPI.Status.isXposedModuleActive -> "模块已激活"
|
||||||
else -> "模块未激活"
|
else -> "模块未激活"
|
||||||
}
|
}
|
||||||
binding.mainTextApiWay.isVisible = isXposedModuleActive
|
binding.mainTextApiWay.isVisible = YukiHookAPI.Status.isXposedModuleActive
|
||||||
binding.mainTextApiWay.text = "Activated by ${YukiHookModuleStatus.executorName} API ${YukiHookModuleStatus.executorVersion}"
|
binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
/** 刷新模块状态 */
|
/** 刷新模块状态 */
|
||||||
refreshModuleStatus()
|
refreshModuleStatus()
|
||||||
/** 发送广播检查模块激活状态 */
|
/** 检查模块激活状态 */
|
||||||
SystemUITool.checkingActivated(context = this) { isRegular, isValied ->
|
SystemUITool.checkingActivated(context = this) { isValied ->
|
||||||
isModuleRegular = isRegular
|
isModuleRegular = true
|
||||||
isModuleValied = isValied
|
isModuleValied = isValied
|
||||||
refreshModuleStatus()
|
refreshModuleStatus()
|
||||||
}
|
}
|
||||||
|
@@ -28,11 +28,11 @@ import android.app.Activity
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
|
||||||
import com.fankes.miui.notify.ui.activity.base.BaseActivity
|
import com.fankes.miui.notify.ui.activity.base.BaseActivity
|
||||||
import com.fankes.miui.notify.utils.factory.delayedRun
|
import com.fankes.miui.notify.utils.factory.delayedRun
|
||||||
import com.fankes.miui.notify.utils.tool.IconRuleManagerTool
|
import com.fankes.miui.notify.utils.tool.IconRuleManagerTool
|
||||||
import com.fankes.miui.notify.utils.tool.SystemUITool
|
import com.fankes.miui.notify.utils.tool.SystemUITool
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
|
||||||
|
|
||||||
class NotifyIconRuleUpdateActivity : Activity() {
|
class NotifyIconRuleUpdateActivity : Activity() {
|
||||||
|
|
||||||
@@ -48,8 +48,6 @@ class NotifyIconRuleUpdateActivity : Activity() {
|
|||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/** 注册 */
|
|
||||||
SystemUITool.register(context = this)
|
|
||||||
/** 拉取云端数据 */
|
/** 拉取云端数据 */
|
||||||
IconRuleManagerTool.sync(appContext) {
|
IconRuleManagerTool.sync(appContext) {
|
||||||
/** 刷新系统界面 */
|
/** 刷新系统界面 */
|
||||||
@@ -60,10 +58,4 @@ class NotifyIconRuleUpdateActivity : Activity() {
|
|||||||
/** 切换到后台 */
|
/** 切换到后台 */
|
||||||
moveTaskToBack(true)
|
moveTaskToBack(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
/** 解除注册 */
|
|
||||||
SystemUITool.unregister(context = this)
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -26,11 +26,11 @@ package com.fankes.miui.notify.ui.activity.base
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.fankes.miui.notify.R
|
import com.fankes.miui.notify.R
|
||||||
import com.fankes.miui.notify.utils.factory.isNotSystemInDarkMode
|
import com.fankes.miui.notify.utils.factory.isNotSystemInDarkMode
|
||||||
import com.fankes.miui.notify.utils.tool.SystemUITool
|
|
||||||
import com.gyf.immersionbar.ktx.immersionBar
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.method
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
@@ -61,26 +61,19 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
|||||||
/** 隐藏系统的标题栏 */
|
/** 隐藏系统的标题栏 */
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
/** 初始化沉浸状态栏 */
|
/** 初始化沉浸状态栏 */
|
||||||
immersionBar {
|
ViewCompat.getWindowInsetsController(window.decorView)?.apply {
|
||||||
statusBarColor(R.color.colorThemeBackground)
|
isAppearanceLightStatusBars = isNotSystemInDarkMode
|
||||||
autoDarkModeEnable(true)
|
isAppearanceLightNavigationBars = isNotSystemInDarkMode
|
||||||
statusBarDarkFont(isNotSystemInDarkMode)
|
}
|
||||||
navigationBarColor(R.color.colorThemeBackground)
|
ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
|
||||||
navigationBarDarkIcon(isNotSystemInDarkMode)
|
window?.statusBarColor = it
|
||||||
fitsSystemWindows(true)
|
window?.navigationBarColor = it
|
||||||
|
window?.navigationBarDividerColor = it
|
||||||
}
|
}
|
||||||
/** 注册 */
|
|
||||||
SystemUITool.register(context = this)
|
|
||||||
/** 装载子类 */
|
/** 装载子类 */
|
||||||
onCreate()
|
onCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 回调 [onCreate] 方法 */
|
/** 回调 [onCreate] 方法 */
|
||||||
abstract fun onCreate()
|
abstract fun onCreate()
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
/** 解除注册 */
|
|
||||||
SystemUITool.unregister(context = this)
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -46,18 +46,18 @@ import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
|||||||
/**
|
/**
|
||||||
* 构造对话框
|
* 构造对话框
|
||||||
* @param isUseBlackTheme 是否使用深色主题
|
* @param isUseBlackTheme 是否使用深色主题
|
||||||
* @param it 对话框方法体
|
* @param initiate 对话框方法体
|
||||||
*/
|
*/
|
||||||
fun Context.showDialog(isUseBlackTheme: Boolean = false, it: DialogBuilder.() -> Unit) =
|
fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder.() -> Unit) =
|
||||||
DialogBuilder(this, isUseBlackTheme).apply(it).show()
|
DialogBuilder(context = this, isUseBlackTheme).apply(initiate).show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示时间选择对话框
|
* 显示时间选择对话框
|
||||||
* @param timeSet 当前时间 - 不写将使用当前时间格式:HH:mm
|
* @param timeSet 当前时间 - 不写将使用当前时间格式:HH:mm
|
||||||
* @param it 回调 - 小时与分钟 HH:mm
|
* @param result 回调 - 小时与分钟 HH:mm
|
||||||
*/
|
*/
|
||||||
fun Context.showTimePicker(timeSet: String = "", it: (String) -> Unit) =
|
fun Context.showTimePicker(timeSet: String = "", result: (String) -> Unit) =
|
||||||
TimePickerDialog(this, { _, h, m -> it("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show()
|
TimePickerDialog(this, { _, h, m -> result("${h.autoZero}:${m.autoZero}") }, timeSet.hour, timeSet.minute, true).show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对话框构造器
|
* 对话框构造器
|
||||||
@@ -150,34 +150,34 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
|
|||||||
/**
|
/**
|
||||||
* 设置对话框确定按钮
|
* 设置对话框确定按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun confirmButton(text: String = "确定", it: () -> Unit = {}) {
|
fun confirmButton(text: String = "确定", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置对话框取消按钮
|
* 设置对话框取消按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun cancelButton(text: String = "取消", it: () -> Unit = {}) {
|
fun cancelButton(text: String = "取消", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置对话框第三个按钮
|
* 设置对话框第三个按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun neutralButton(text: String = "更多", it: () -> Unit = {}) {
|
fun neutralButton(text: String = "更多", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 取消对话框 */
|
/** 取消对话框 */
|
||||||
|
@@ -47,12 +47,12 @@ import android.util.Base64
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||||
import com.highcapable.yukihookapi.hook.factory.method
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
import com.highcapable.yukihookapi.hook.type.java.StringType
|
import com.highcapable.yukihookapi.hook.type.java.StringType
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@@ -95,6 +95,12 @@ inline val isUpperOfAndroidS get() = Build.VERSION.SDK_INT > Build.VERSION_CODES
|
|||||||
*/
|
*/
|
||||||
inline val isLowerAndroidP get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.P
|
inline val isLowerAndroidP get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.P
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统版本是否低于 Android 11
|
||||||
|
* @return [Boolean] 是否符合条件
|
||||||
|
*/
|
||||||
|
inline val isLowerAndroidR get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前设备是否是 MIUI 定制 Android 系统
|
* 当前设备是否是 MIUI 定制 Android 系统
|
||||||
* @return [Boolean] 是否符合条件
|
* @return [Boolean] 是否符合条件
|
||||||
@@ -440,28 +446,24 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
|
|||||||
*
|
*
|
||||||
* [T] 为指定的 [Activity]
|
* [T] 为指定的 [Activity]
|
||||||
*/
|
*/
|
||||||
inline fun <reified T : Activity> Context.navigate() = runInSafe { startActivity(Intent(this, T::class.java)) }
|
inline fun <reified T : Activity> Context.navigate() = runInSafe {
|
||||||
|
startActivity(Intent(if (this is Service) applicationContext else this, T::class.java).apply {
|
||||||
/**
|
if (this@navigate !is Activity) flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
* 跳转到指定页面
|
})
|
||||||
*
|
}
|
||||||
* [T] 为指定的 [Activity]
|
|
||||||
*/
|
|
||||||
inline fun <reified T : Activity> Service.navigate() =
|
|
||||||
runInSafe { startActivity(Intent(this, T::class.java).apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK }) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹出 [Snackbar]
|
* 弹出 [Snackbar]
|
||||||
* @param msg 提示内容
|
* @param msg 提示内容
|
||||||
* @param actionText 按钮文本 - 不写默认取消按钮
|
* @param actionText 按钮文本 - 不写默认取消按钮
|
||||||
* @param it 按钮事件回调
|
* @param callback 按钮事件回调
|
||||||
*/
|
*/
|
||||||
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {}) =
|
||||||
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG)
|
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG)
|
||||||
.apply {
|
.apply {
|
||||||
if (actionText.isBlank()) return@apply
|
if (actionText.isBlank()) return@apply
|
||||||
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
|
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
|
||||||
setAction(actionText) { it() }
|
setAction(actionText) { callback() }
|
||||||
}.show()
|
}.show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -45,9 +45,9 @@ object GithubReleaseTool {
|
|||||||
* 获取最新版本信息
|
* 获取最新版本信息
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param version 当前版本
|
* @param version 当前版本
|
||||||
* @param it 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
|
* @param result 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
|
||||||
*/
|
*/
|
||||||
fun checkingForUpdate(context: Context, version: String, it: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
|
fun checkingForUpdate(context: Context, version: String, result: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
|
||||||
OkHttpClient().newBuilder().build().newCall(
|
OkHttpClient().newBuilder().build().newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
|
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
|
||||||
@@ -73,7 +73,7 @@ object GithubReleaseTool {
|
|||||||
}
|
}
|
||||||
if (name != version) (context as? Activity?)?.runOnUiThread {
|
if (name != version) (context as? Activity?)?.runOnUiThread {
|
||||||
showUpdate()
|
showUpdate()
|
||||||
it(name) { showUpdate() }
|
result(name) { showUpdate() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,9 +84,9 @@ object GithubReleaseTool {
|
|||||||
/**
|
/**
|
||||||
* 检查网络连接情况
|
* 检查网络连接情况
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 已连接回调
|
* @param callback 已连接回调
|
||||||
*/
|
*/
|
||||||
private fun checkingInternetConnect(context: Context, it: () -> Unit) = runInSafe {
|
private fun checkingInternetConnect(context: Context, callback: () -> Unit) = runInSafe {
|
||||||
if (isNetWorkSuccess)
|
if (isNetWorkSuccess)
|
||||||
OkHttpClient().newBuilder().build().newCall(
|
OkHttpClient().newBuilder().build().newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
@@ -107,7 +107,7 @@ object GithubReleaseTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) = runInSafe {
|
override fun onResponse(call: Call, response: Response) = runInSafe {
|
||||||
(context as? Activity?)?.runOnUiThread { runInSafe { it() } }
|
(context as? Activity?)?.runOnUiThread { runInSafe { callback() } }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,7 @@ import android.graphics.Bitmap
|
|||||||
import android.graphics.drawable.Icon
|
import android.graphics.drawable.Icon
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import com.fankes.miui.notify.const.Const
|
import com.fankes.miui.notify.BuildConfig
|
||||||
import com.fankes.miui.notify.hook.HookEntry
|
import com.fankes.miui.notify.hook.HookEntry
|
||||||
import com.fankes.miui.notify.utils.factory.*
|
import com.fankes.miui.notify.utils.factory.*
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ import com.fankes.miui.notify.utils.factory.*
|
|||||||
*/
|
*/
|
||||||
object IconAdaptationTool {
|
object IconAdaptationTool {
|
||||||
|
|
||||||
|
/** 当前模块的包名 */
|
||||||
|
private const val MODULE_PACKAGE_NAME = BuildConfig.APPLICATION_ID
|
||||||
|
|
||||||
/** 推送通知的渠道名称 */
|
/** 推送通知的渠道名称 */
|
||||||
private const val NOTIFY_CHANNEL = "notifyRuleSupportId"
|
private const val NOTIFY_CHANNEL = "notifyRuleSupportId"
|
||||||
|
|
||||||
@@ -137,8 +140,8 @@ object IconAdaptationTool {
|
|||||||
context, packageName.hashCode(),
|
context, packageName.hashCode(),
|
||||||
Intent().apply {
|
Intent().apply {
|
||||||
component = ComponentName(
|
component = ComponentName(
|
||||||
Const.MODULE_PACKAGE_NAME,
|
MODULE_PACKAGE_NAME,
|
||||||
"${Const.MODULE_PACKAGE_NAME}.ui.activity.ConfigureActivity"
|
"${MODULE_PACKAGE_NAME}.ui.activity.ConfigureActivity"
|
||||||
)
|
)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}.apply {
|
}.apply {
|
||||||
@@ -177,8 +180,8 @@ object IconAdaptationTool {
|
|||||||
context.startActivity(
|
context.startActivity(
|
||||||
Intent().apply {
|
Intent().apply {
|
||||||
component = ComponentName(
|
component = ComponentName(
|
||||||
Const.MODULE_PACKAGE_NAME,
|
MODULE_PACKAGE_NAME,
|
||||||
"${Const.MODULE_PACKAGE_NAME}.ui.activity.auto.NotifyIconRuleUpdateActivity"
|
"${MODULE_PACKAGE_NAME}.ui.activity.auto.NotifyIconRuleUpdateActivity"
|
||||||
)
|
)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
|
@@ -75,9 +75,9 @@ object IconRuleManagerTool {
|
|||||||
/**
|
/**
|
||||||
* 从在线地址手动同步规则
|
* 从在线地址手动同步规则
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 成功后回调
|
* @param callback 成功后回调
|
||||||
*/
|
*/
|
||||||
fun syncByHand(context: Context, it: () -> Unit) =
|
fun syncByHand(context: Context, callback: () -> Unit) =
|
||||||
context.showDialog {
|
context.showDialog {
|
||||||
title = "同步列表"
|
title = "同步列表"
|
||||||
var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY)
|
var sourceType = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY)
|
||||||
@@ -116,7 +116,7 @@ object IconRuleManagerTool {
|
|||||||
confirmButton {
|
confirmButton {
|
||||||
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType)
|
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY, sourceType)
|
||||||
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL, customUrl)
|
context.modulePrefs.put(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL, customUrl)
|
||||||
sync(context, sourceType, customUrl, it)
|
sync(context, sourceType, customUrl, callback)
|
||||||
}
|
}
|
||||||
cancelButton()
|
cancelButton()
|
||||||
neutralButton(text = "自定义规则") {
|
neutralButton(text = "自定义规则") {
|
||||||
@@ -139,7 +139,7 @@ object IconRuleManagerTool {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
notifyRefresh(context)
|
notifyRefresh(context)
|
||||||
it()
|
callback()
|
||||||
}
|
}
|
||||||
else -> context.snake(msg = "请输入有效内容")
|
else -> context.snake(msg = "请输入有效内容")
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ object IconRuleManagerTool {
|
|||||||
jsonString.isNotBlank() -> {
|
jsonString.isNotBlank() -> {
|
||||||
params.save(dataJson = jsonString.takeIf { params.isJsonArray(it) } ?: "[$jsonString]")
|
params.save(dataJson = jsonString.takeIf { params.isJsonArray(it) } ?: "[$jsonString]")
|
||||||
notifyRefresh(context)
|
notifyRefresh(context)
|
||||||
it()
|
callback()
|
||||||
}
|
}
|
||||||
else -> context.snake(msg = "请输入有效内容")
|
else -> context.snake(msg = "请输入有效内容")
|
||||||
}
|
}
|
||||||
@@ -169,23 +169,23 @@ object IconRuleManagerTool {
|
|||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param sourceType 同步地址类型 - 默认自动获取已存储的键值
|
* @param sourceType 同步地址类型 - 默认自动获取已存储的键值
|
||||||
* @param customUrl 自定义同步地址 - 默认自动获取已存储的键值
|
* @param customUrl 自定义同步地址 - 默认自动获取已存储的键值
|
||||||
* @param it 成功后回调
|
* @param callback 成功后回调
|
||||||
*/
|
*/
|
||||||
fun sync(
|
fun sync(
|
||||||
context: Context,
|
context: Context,
|
||||||
sourceType: Int = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY),
|
sourceType: Int = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY),
|
||||||
customUrl: String = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL),
|
customUrl: String = context.modulePrefs.get(DataConst.SOURCE_SYNC_WAY_CUSTOM_URL),
|
||||||
it: () -> Unit
|
callback: () -> Unit
|
||||||
) {
|
) {
|
||||||
when (sourceType) {
|
when (sourceType) {
|
||||||
TYPE_SOURCE_SYNC_WAY_1 ->
|
TYPE_SOURCE_SYNC_WAY_1 ->
|
||||||
onRefreshing(context, url = "https://raw.fastgit.org/fankes/AndroidNotifyIconAdapt/main", it)
|
onRefreshing(context, url = "https://raw.fastgit.org/fankes/AndroidNotifyIconAdapt/main", callback)
|
||||||
TYPE_SOURCE_SYNC_WAY_2 ->
|
TYPE_SOURCE_SYNC_WAY_2 ->
|
||||||
onRefreshing(context, url = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main", it)
|
onRefreshing(context, url = "https://raw.githubusercontent.com/fankes/AndroidNotifyIconAdapt/main", callback)
|
||||||
TYPE_SOURCE_SYNC_WAY_3 ->
|
TYPE_SOURCE_SYNC_WAY_3 ->
|
||||||
if (customUrl.isNotBlank())
|
if (customUrl.isNotBlank())
|
||||||
if (customUrl.startsWith("http://") || customUrl.startsWith("https://"))
|
if (customUrl.startsWith("http://") || customUrl.startsWith("https://"))
|
||||||
onRefreshingCustom(context, customUrl, it)
|
onRefreshingCustom(context, customUrl, callback)
|
||||||
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不是一个合法的 URL")
|
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不是一个合法的 URL")
|
||||||
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不能为空")
|
else context.snakeOrNotify(title = "同步失败", msg = "同步地址不能为空")
|
||||||
else -> context.snakeOrNotify(title = "同步异常", msg = "同步类型错误")
|
else -> context.snakeOrNotify(title = "同步异常", msg = "同步类型错误")
|
||||||
@@ -196,14 +196,14 @@ object IconRuleManagerTool {
|
|||||||
* 开始更新数据
|
* 开始更新数据
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param url
|
* @param url
|
||||||
* @param it 成功后回调
|
* @param callback 成功后回调
|
||||||
*/
|
*/
|
||||||
private fun onRefreshing(context: Context, url: String, it: () -> Unit) = checkingInternetConnect(context) {
|
private fun onRefreshing(context: Context, url: String, callback: () -> Unit) = checkingInternetConnect(context) {
|
||||||
fun doParse(callback: (Boolean) -> Unit = {}) {
|
fun doParse(result: (Boolean) -> Unit = {}) {
|
||||||
wait(context, url = "$url/OS/$OS_TAG/NotifyIconsSupportConfig.json") { isDone1, ctOS ->
|
wait(context, url = "$url/OS/$OS_TAG/NotifyIconsSupportConfig.json") { isDone1, ctOS ->
|
||||||
callback(true)
|
result(true)
|
||||||
wait(context, url = "$url/APP/NotifyIconsSupportConfig.json") { isDone2, ctAPP ->
|
wait(context, url = "$url/APP/NotifyIconsSupportConfig.json") { isDone2, ctAPP ->
|
||||||
callback(false)
|
result(false)
|
||||||
IconPackParams(context).also { params ->
|
IconPackParams(context).also { params ->
|
||||||
when {
|
when {
|
||||||
isDone1 && isDone2 -> params.splicingJsonArray(ctOS, ctAPP).also {
|
isDone1 && isDone2 -> params.splicingJsonArray(ctOS, ctAPP).also {
|
||||||
@@ -216,7 +216,7 @@ object IconRuleManagerTool {
|
|||||||
params.save(it)
|
params.save(it)
|
||||||
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
|
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
|
||||||
notifyRefresh(context)
|
notifyRefresh(context)
|
||||||
it()
|
callback()
|
||||||
}
|
}
|
||||||
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
|
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
|
||||||
}
|
}
|
||||||
@@ -225,7 +225,7 @@ object IconRuleManagerTool {
|
|||||||
context.showDialog {
|
context.showDialog {
|
||||||
title = "连接失败"
|
title = "连接失败"
|
||||||
msg = "连接失败,错误如下:\n${if (isDone1.not()) ctOS else ctAPP}"
|
msg = "连接失败,错误如下:\n${if (isDone1.not()) ctOS else ctAPP}"
|
||||||
confirmButton(text = "再试一次") { syncByHand(context, it) }
|
confirmButton(text = "再试一次") { syncByHand(context, callback) }
|
||||||
cancelButton()
|
cancelButton()
|
||||||
}
|
}
|
||||||
else -> pushNotify(context, title = "同步地址不可用", msg = if (isDone1.not()) ctOS else ctAPP)
|
else -> pushNotify(context, title = "同步地址不可用", msg = if (isDone1.not()) ctOS else ctAPP)
|
||||||
@@ -248,12 +248,12 @@ object IconRuleManagerTool {
|
|||||||
* 开始更新数据
|
* 开始更新数据
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param url
|
* @param url
|
||||||
* @param it 成功后回调
|
* @param callback 成功后回调
|
||||||
*/
|
*/
|
||||||
private fun onRefreshingCustom(context: Context, url: String, it: () -> Unit) = checkingInternetConnect(context) {
|
private fun onRefreshingCustom(context: Context, url: String, callback: () -> Unit) = checkingInternetConnect(context) {
|
||||||
fun doParse(callback: () -> Unit = {}) {
|
fun doParse(result: () -> Unit = {}) {
|
||||||
wait(context, url) { isDone, content ->
|
wait(context, url) { isDone, content ->
|
||||||
callback()
|
result()
|
||||||
IconPackParams(context).also { params ->
|
IconPackParams(context).also { params ->
|
||||||
when {
|
when {
|
||||||
isDone -> when {
|
isDone -> when {
|
||||||
@@ -265,7 +265,7 @@ object IconRuleManagerTool {
|
|||||||
params.save(content)
|
params.save(content)
|
||||||
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
|
pushNotify(context, title = "同步完成", msg = "已更新通知图标优化名单,点击查看")
|
||||||
notifyRefresh(context)
|
notifyRefresh(context)
|
||||||
it()
|
callback()
|
||||||
}
|
}
|
||||||
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
|
else -> (if (context is AppCompatActivity) context.snake(msg = "列表数据已是最新"))
|
||||||
}
|
}
|
||||||
@@ -293,16 +293,16 @@ object IconRuleManagerTool {
|
|||||||
/**
|
/**
|
||||||
* 检查网络连接情况
|
* 检查网络连接情况
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 已连接回调
|
* @param callback 已连接回调
|
||||||
*/
|
*/
|
||||||
private fun checkingInternetConnect(context: Context, it: () -> Unit) =
|
private fun checkingInternetConnect(context: Context, callback: () -> Unit) =
|
||||||
if (context is AppCompatActivity) context.showDialog {
|
if (context is AppCompatActivity) context.showDialog {
|
||||||
title = "准备中"
|
title = "准备中"
|
||||||
progressContent = "正在检查网络连接情况"
|
progressContent = "正在检查网络连接情况"
|
||||||
noCancelable()
|
noCancelable()
|
||||||
baseCheckingInternetConnect(context) { isDone ->
|
baseCheckingInternetConnect(context) { isDone ->
|
||||||
cancel()
|
cancel()
|
||||||
if (isDone) it() else
|
if (isDone) callback() else
|
||||||
context.showDialog {
|
context.showDialog {
|
||||||
title = "网络不可用"
|
title = "网络不可用"
|
||||||
msg = "无法连接到互联网,请检查你当前的设备是否可以上网,且没有在手机管家中禁用本模块的联网权限。"
|
msg = "无法连接到互联网,请检查你当前的设备是否可以上网,且没有在手机管家中禁用本模块的联网权限。"
|
||||||
@@ -319,24 +319,24 @@ object IconRuleManagerTool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else baseCheckingInternetConnect(context) { isDone ->
|
} else baseCheckingInternetConnect(context) { isDone ->
|
||||||
if (isDone) it() else pushNotify(context, title = "网络不可用", msg = "无法连接到互联网,无法更新通知图标规则")
|
if (isDone) callback() else pushNotify(context, title = "网络不可用", msg = "无法连接到互联网,无法更新通知图标规则")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查网络连接情况
|
* 检查网络连接情况
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 已连接回调
|
* @param result 已连接回调
|
||||||
*/
|
*/
|
||||||
private fun baseCheckingInternetConnect(context: Context, it: (Boolean) -> Unit) =
|
private fun baseCheckingInternetConnect(context: Context, result: (Boolean) -> Unit) =
|
||||||
wait(context, url = "https://www.baidu.com") { isDone, _ -> it(isDone) }
|
wait(context, url = "https://www.baidu.com") { isDone, _ -> result(isDone) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送 GET 请求内容并等待
|
* 发送 GET 请求内容并等待
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param url 请求地址
|
* @param url 请求地址
|
||||||
* @param it 回调 - ([Boolean] 是否成功,[String] 成功的内容或失败消息)
|
* @param result 回调 - ([Boolean] 是否成功,[String] 成功的内容或失败消息)
|
||||||
*/
|
*/
|
||||||
private fun wait(context: Context, url: String, it: (Boolean, String) -> Unit) = runCatching {
|
private fun wait(context: Context, url: String, result: (Boolean, String) -> Unit) = runCatching {
|
||||||
OkHttpClient().newBuilder().apply {
|
OkHttpClient().newBuilder().apply {
|
||||||
SSLSocketClient.sSLSocketFactory?.let { sslSocketFactory(it, SSLSocketClient.trustManager) }
|
SSLSocketClient.sSLSocketFactory?.let { sslSocketFactory(it, SSLSocketClient.trustManager) }
|
||||||
hostnameVerifier(SSLSocketClient.hostnameVerifier)
|
hostnameVerifier(SSLSocketClient.hostnameVerifier)
|
||||||
@@ -347,15 +347,15 @@ object IconRuleManagerTool {
|
|||||||
.build()
|
.build()
|
||||||
).enqueue(object : Callback {
|
).enqueue(object : Callback {
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
(context as? Activity?)?.runOnUiThread { it(false, e.toString()) } ?: it(false, e.toString())
|
(context as? Activity?)?.runOnUiThread { result(false, e.toString()) } ?: result(false, e.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
override fun onResponse(call: Call, response: Response) {
|
||||||
val bodyString = response.body?.string() ?: ""
|
val bodyString = response.body?.string() ?: ""
|
||||||
(context as? Activity?)?.runOnUiThread { it(true, bodyString) } ?: it(true, bodyString)
|
(context as? Activity?)?.runOnUiThread { result(true, bodyString) } ?: result(true, bodyString)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}.onFailure { it(false, "URL 无效") }
|
}.onFailure { result(false, "URL 无效") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 推送通知图标更新通知
|
* 推送通知图标更新通知
|
||||||
|
@@ -22,59 +22,44 @@
|
|||||||
*/
|
*/
|
||||||
package com.fankes.miui.notify.utils.tool
|
package com.fankes.miui.notify.utils.tool
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import com.fankes.miui.notify.hook.HookConst.SYSTEMUI_PACKAGE_NAME
|
||||||
import android.content.IntentFilter
|
|
||||||
import com.fankes.miui.notify.application.MNNApplication.Companion.appContext
|
|
||||||
import com.fankes.miui.notify.const.Const
|
|
||||||
import com.fankes.miui.notify.utils.factory.*
|
import com.fankes.miui.notify.utils.factory.*
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.highcapable.yukihookapi.hook.factory.isXposedModuleActive
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.dataChannel
|
||||||
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.channel.data.ChannelData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统界面工具
|
* 系统界面工具
|
||||||
*/
|
*/
|
||||||
object SystemUITool {
|
object SystemUITool {
|
||||||
|
|
||||||
/** 宿主广播回调 */
|
private val CALL_HOST_REFRESH_CACHING = ChannelData("call_host_refresh_caching", false)
|
||||||
private var moduleHandlerCallback: ((Boolean, Boolean) -> Unit)? = null
|
private val CALL_MODULE_REFRESH_RESULT = ChannelData("call_module_refresh_result", false)
|
||||||
|
|
||||||
/** 通知广播回调 */
|
|
||||||
private var remindHandlerCallback: ((Boolean, Boolean) -> Unit)? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册广播
|
* 宿主注册监听
|
||||||
* @param context 实例
|
|
||||||
*/
|
*/
|
||||||
fun register(context: Context) {
|
object Host {
|
||||||
/** 注册广播检查模块激活状态 */
|
|
||||||
context.registerReceiver(moduleHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_MODULE_HANDLER_RECEIVER) })
|
/**
|
||||||
/** 注册广播通知系统界面改变 */
|
* 监听系统界面刷新改变
|
||||||
context.registerReceiver(remindHandlerReceiver, IntentFilter().apply { addAction(Const.ACTION_REMIND_HANDLER_RECEIVER) })
|
* @param param 实例
|
||||||
|
* @param result 回调 - ([Boolean] 是否成功)
|
||||||
|
*/
|
||||||
|
fun onRefreshSystemUI(param: PackageParam, result: (Boolean) -> Boolean) {
|
||||||
|
param.dataChannel.with { wait(CALL_HOST_REFRESH_CACHING) { put(CALL_MODULE_REFRESH_RESULT, result(it)) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 取消注册广播
|
|
||||||
* @param context 实例
|
|
||||||
*/
|
|
||||||
fun unregister(context: Context) {
|
|
||||||
context.unregisterReceiver(moduleHandlerReceiver)
|
|
||||||
context.unregisterReceiver(remindHandlerReceiver)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查模块是否激活
|
* 检查模块是否激活
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 成功后回调 - ([Boolean] 是否激活,[Boolean] 是否有效)
|
* @param result 成功后回调
|
||||||
*/
|
*/
|
||||||
fun checkingActivated(context: Context, it: (Boolean, Boolean) -> Unit) {
|
fun checkingActivated(context: Context, result: (Boolean) -> Unit) = context.dataChannel(SYSTEMUI_PACKAGE_NAME).checkingVersionEquals(result)
|
||||||
moduleHandlerCallback = it
|
|
||||||
context.sendBroadcast(Intent().apply {
|
|
||||||
action = Const.ACTION_MODULE_CHECKING_RECEIVER
|
|
||||||
putExtra(Const.MODULE_VERSION_VERIFY_TAG, Const.MODULE_VERSION_VERIFY)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重启系统界面
|
* 重启系统界面
|
||||||
@@ -100,17 +85,10 @@ object SystemUITool {
|
|||||||
* 刷新系统界面状态栏与通知图标
|
* 刷新系统界面状态栏与通知图标
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
|
* @param isRefreshCacheOnly 仅刷新缓存不刷新图标和通知改变 - 默认:否
|
||||||
* @param it 成功后回调
|
* @param callback 成功后回调
|
||||||
*/
|
*/
|
||||||
fun refreshSystemUI(context: Context? = null, isRefreshCacheOnly: Boolean = false, it: () -> Unit = {}) = runInSafe {
|
fun refreshSystemUI(context: Context? = null, isRefreshCacheOnly: Boolean = false, callback: () -> Unit = {}) = runInSafe {
|
||||||
fun sendMessage() {
|
if (YukiHookAPI.Status.isXposedModuleActive)
|
||||||
(context ?: appContext).sendBroadcast(Intent().apply {
|
|
||||||
action = Const.ACTION_REMIND_CHECKING_RECEIVER
|
|
||||||
putExtra("isRefreshCacheOnly", isRefreshCacheOnly)
|
|
||||||
putExtra(Const.MODULE_VERSION_VERIFY_TAG, Const.MODULE_VERSION_VERIFY)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (isXposedModuleActive)
|
|
||||||
context?.showDialog {
|
context?.showDialog {
|
||||||
title = "请稍后"
|
title = "请稍后"
|
||||||
progressContent = "正在等待系统界面刷新"
|
progressContent = "正在等待系统界面刷新"
|
||||||
@@ -119,23 +97,29 @@ object SystemUITool {
|
|||||||
/** 设置等待延迟 */
|
/** 设置等待延迟 */
|
||||||
delayedRun(ms = 5000) {
|
delayedRun(ms = 5000) {
|
||||||
if (isWaited) return@delayedRun
|
if (isWaited) return@delayedRun
|
||||||
remindHandlerCallback = null
|
|
||||||
cancel()
|
cancel()
|
||||||
context.snake(msg = "预计响应超时,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) }
|
context.snake(msg = "预计响应超时,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
}
|
}
|
||||||
remindHandlerCallback = { isGrasp, isValied ->
|
checkingActivated(context) { isValied ->
|
||||||
remindHandlerCallback = null
|
when {
|
||||||
|
isValied.not() -> {
|
||||||
cancel()
|
cancel()
|
||||||
isWaited = true
|
isWaited = true
|
||||||
when {
|
|
||||||
isGrasp && !isValied ->
|
|
||||||
context.snake(msg = "请重启系统界面以生效模块更新", actionText = "立即重启") { restartSystemUI(context) }
|
context.snake(msg = "请重启系统界面以生效模块更新", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
else -> it()
|
}
|
||||||
|
else -> context.dataChannel(SYSTEMUI_PACKAGE_NAME).with {
|
||||||
|
wait(CALL_MODULE_REFRESH_RESULT) {
|
||||||
|
cancel()
|
||||||
|
isWaited = true
|
||||||
|
callback()
|
||||||
|
if (it.not()) context.snake(msg = "刷新失败,建议重启系统界面", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
|
}
|
||||||
|
put(CALL_HOST_REFRESH_CACHING, isRefreshCacheOnly)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendMessage()
|
|
||||||
noCancelable()
|
noCancelable()
|
||||||
} ?: sendMessage()
|
}
|
||||||
else context?.snake(msg = "模块没有激活,更改不会生效")
|
else context?.snake(msg = "模块没有激活,更改不会生效")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,29 +128,7 @@ object SystemUITool {
|
|||||||
* @param context 实例
|
* @param context 实例
|
||||||
*/
|
*/
|
||||||
fun showNeedRestartSnake(context: Context) =
|
fun showNeedRestartSnake(context: Context) =
|
||||||
if (isXposedModuleActive)
|
if (YukiHookAPI.Status.isXposedModuleActive)
|
||||||
context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) }
|
context.snake(msg = "设置需要重启系统界面才能生效", actionText = "立即重启") { restartSystemUI(context) }
|
||||||
else context.snake(msg = "模块没有激活,更改不会生效")
|
else context.snake(msg = "模块没有激活,更改不会生效")
|
||||||
|
|
||||||
/** 宿主广播接收器 */
|
|
||||||
private val moduleHandlerReceiver by lazy {
|
|
||||||
object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
val isRegular = intent?.getBooleanExtra("isRegular", false) ?: false
|
|
||||||
val isValied = intent?.getBooleanExtra("isValied", false) ?: false
|
|
||||||
moduleHandlerCallback?.invoke(isRegular, isValied)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 通知广播接收器 */
|
|
||||||
private val remindHandlerReceiver by lazy {
|
|
||||||
object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
val isGrasp = intent?.getBooleanExtra("isGrasp", false) ?: false
|
|
||||||
val isValied = intent?.getBooleanExtra("isValied", false) ?: false
|
|
||||||
remindHandlerCallback?.invoke(isGrasp, isValied)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* MIUINativeNotifyIcon - Fix the native notification bar icon function abandoned by the MIUI development team.
|
||||||
|
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||||
|
* https://github.com/fankes/MIUINativeNotifyIcon
|
||||||
|
*
|
||||||
|
* 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.miui.notify.utils.tool
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.fankes.miui.notify.utils.factory.openBrowser
|
||||||
|
import com.fankes.miui.notify.utils.factory.showDialog
|
||||||
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [YukiHookAPI] 的自动推广工具类
|
||||||
|
*/
|
||||||
|
object YukiPromoteTool {
|
||||||
|
|
||||||
|
/** 推广已读存储键值 */
|
||||||
|
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed", false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示推广对话框
|
||||||
|
* @param context 实例
|
||||||
|
*/
|
||||||
|
fun promote(context: Context) {
|
||||||
|
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true)
|
||||||
|
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not())
|
||||||
|
context.showDialog {
|
||||||
|
title = "面向开发者的推广"
|
||||||
|
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
|
||||||
|
"快来体验 YukiHookAPI,这是一个使用 Kotlin 重新构建的高效 Xposed Hook API,助你的开发变得更轻松。"
|
||||||
|
confirmButton(text = "去看看") {
|
||||||
|
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
|
||||||
|
saveReaded()
|
||||||
|
}
|
||||||
|
cancelButton(text = "我不是开发者") { saveReaded() }
|
||||||
|
noCancelable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -465,15 +465,13 @@
|
|||||||
android:elevation="0dp"
|
android:elevation="0dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingLeft="10dp"
|
android:paddingTop="15dp">
|
||||||
android:paddingTop="15dp"
|
|
||||||
android:paddingRight="10dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:gravity="center|start">
|
android:gravity="center|start">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -496,8 +494,8 @@
|
|||||||
android:id="@+id/notify_icon_fix_switch"
|
android:id="@+id/notify_icon_fix_switch"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:text="启用通知图标优化"
|
android:text="启用通知图标优化"
|
||||||
android:textColor="@color/colorTextGray"
|
android:textColor="@color/colorTextGray"
|
||||||
android:textSize="15sp" />
|
android:textSize="15sp" />
|
||||||
@@ -506,8 +504,8 @@
|
|||||||
android:id="@+id/notify_icon_fix_button"
|
android:id="@+id/notify_icon_fix_button"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="3dp"
|
android:layout_marginLeft="13dp"
|
||||||
android:layout_marginRight="3dp"
|
android:layout_marginRight="13dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:background="@drawable/bg_button_round"
|
android:background="@drawable/bg_button_round"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
@@ -520,8 +518,8 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
@@ -532,8 +530,8 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
android:alpha="0.6"
|
android:alpha="0.6"
|
||||||
android:lineSpacingExtra="6dp"
|
android:lineSpacingExtra="6dp"
|
||||||
@@ -541,12 +539,119 @@
|
|||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/notify_icon_custom_corner_item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginLeft="15dp"
|
||||||
|
android:layout_marginRight="15dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:gravity="center|start"
|
||||||
|
android:text="调整通知栏中的图标边框圆角大小"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:textColor="@color/colorTextGray"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatSeekBar
|
||||||
|
android:id="@+id/notify_icon_custom_corner_seekbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:max="15"
|
||||||
|
android:min="0"
|
||||||
|
android:paddingLeft="5dp"
|
||||||
|
android:paddingRight="5dp"
|
||||||
|
android:progress="15" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="15dp"
|
||||||
|
android:layout_marginRight="15dp"
|
||||||
|
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_icon_custom_corner_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="15 dp"
|
||||||
|
android:textColor="@color/colorTextGray"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="15dp"
|
||||||
|
android:layout_marginRight="15dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:lineSpacingExtra="6dp"
|
||||||
|
android:text="你可以拖拽滑动条来调整通知栏中图标的边框圆角大小,仅支持 Android 12 风格以及 MIUI 经典样式的通知图标。"
|
||||||
|
android:textColor="@color/colorTextDark"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/notify_icon_force_app_icon_item"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="15dp"
|
||||||
|
android:layout_marginRight="15dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.fankes.miui.notify.ui.view.MaterialSwitch
|
||||||
|
android:id="@+id/notify_icon_force_app_icon_switch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:text="通知栏中的图标强制为 APP 图标"
|
||||||
|
android:textColor="@color/colorTextGray"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:lineSpacingExtra="6dp"
|
||||||
|
android:text="此选项默认关闭,开启后下拉通知栏中的通知图标将会被替换为 APP 自身图标,但是不会更改状态栏中的通知图标,这是一个破坏原生通知图标的行为,仅针对部分有需要的用户而添加,我们不推荐开启这个功能,请根据个人偏好进行选择是否需要开启。"
|
||||||
|
android:textColor="@color/colorTextDark"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/notify_icon_fix_notify_item"
|
android:id="@+id/notify_icon_fix_notify_item"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.fankes.miui.notify.ui.view.MaterialSwitch
|
<com.fankes.miui.notify.ui.view.MaterialSwitch
|
||||||
@@ -573,8 +678,8 @@
|
|||||||
android:id="@+id/notify_icon_auto_sync_item"
|
android:id="@+id/notify_icon_auto_sync_item"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="5dp"
|
android:layout_marginLeft="15dp"
|
||||||
android:layout_marginRight="5dp"
|
android:layout_marginRight="15dp"
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
10
build.gradle
10
build.gradle
@@ -1,12 +1,12 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '7.1.3' apply false
|
id 'com.android.application' version '7.2.0' apply false
|
||||||
id 'com.android.library' version '7.1.3' apply false
|
id 'com.android.library' version '7.2.0' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
|
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "2.5"
|
appVersionName = "2.7"
|
||||||
appVersionCode = 30
|
appVersionCode = 32
|
||||||
enableR8 = true
|
enableR8 = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Tue Feb 15 02:09:05 CST 2022
|
#Wed May 25 04:36:53 CST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
Reference in New Issue
Block a user