├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── ic_launcher-playstore.png
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ ├── ic_launcher_round.png
│ │ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable
│ │ │ │ ├── ic_applist.xml
│ │ │ │ ├── gradient_color.xml
│ │ │ │ ├── gradient_color_dark.xml
│ │ │ │ ├── ic_warning.xml
│ │ │ │ ├── ic_success_fill.xml
│ │ │ │ ├── ic_error_fill.xml
│ │ │ │ ├── ic_question_fill.xml
│ │ │ │ ├── ic_log.xml
│ │ │ │ ├── ic_save.xml
│ │ │ │ ├── ic_trash.xml
│ │ │ │ ├── ic_check_circle.xml
│ │ │ │ ├── ic_settings.xml
│ │ │ │ ├── ic_assignment.xml
│ │ │ │ ├── ic_info.xml
│ │ │ │ ├── ic_icon.xml
│ │ │ │ ├── ic_rocket_fill.xml
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── themes.xml
│ │ │ │ └── strings.xml
│ │ │ ├── menu
│ │ │ │ ├── menu_run_log.xml
│ │ │ │ ├── menu_settings.xml
│ │ │ │ └── menu_show_app_list.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── activity_settings.xml
│ │ │ │ ├── toolbar.xml
│ │ │ │ ├── tips_layout.xml
│ │ │ │ ├── activity_application_list.xml
│ │ │ │ ├── activity_doze_run_log.xml
│ │ │ │ ├── activity_splash.xml
│ │ │ │ ├── application_unit_layout.xml
│ │ │ │ └── dialog_about.xml
│ │ │ ├── xml
│ │ │ │ ├── settings_preferences.xml
│ │ │ │ └── shortcuts.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ └── values-zh-rCN
│ │ │ │ └── strings.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── github
│ │ │ │ └── hwwwwwlemon
│ │ │ │ └── dozeconfig
│ │ │ │ ├── activity
│ │ │ │ ├── base
│ │ │ │ │ └── BaseActivity.kt
│ │ │ │ ├── shortcuts
│ │ │ │ │ └── RefreshDozeWhitelist.kt
│ │ │ │ ├── SplashActivity.kt
│ │ │ │ ├── DozeRunLogActivity.kt
│ │ │ │ ├── SettingsActivity.kt
│ │ │ │ └── ApplicationsListActivity.kt
│ │ │ │ ├── utils
│ │ │ │ ├── ToastUtil.kt
│ │ │ │ ├── MyPreferences.kt
│ │ │ │ ├── Utils.kt
│ │ │ │ └── DozeFileUtil.kt
│ │ │ │ ├── DozeManager.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── adapter
│ │ │ │ └── ApplicationAdapter.kt
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── github
│ │ │ └── hwwwwwlemon
│ │ │ └── dozeconfig
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── github
│ │ └── hwwwwwlemon
│ │ └── dozeconfig
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── build.gradle
├── dozewhitelist
├── META-INF
│ └── com
│ │ └── google
│ │ └── android
│ │ ├── updater-script
│ │ └── update-binary
├── doze.conf
├── log.sh
├── module.prop
├── whitelist.sh
├── service.sh
├── customize.sh
└── doze.sh
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── README.md
├── LICENSE
├── settings.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/dozewhitelist/META-INF/com/google/android/updater-script:
--------------------------------------------------------------------------------
1 | #MAGISK
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/dozewhitelist/doze.conf:
--------------------------------------------------------------------------------
1 | whitelist="
2 | +com.tencent.mm
3 | +com.tencent.qq
4 | +com.tencent.tim
5 | +com.netease.cloudmusic
6 | "
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hwwwww-dev/DozeConfig/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/dozewhitelist/log.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | export TZ=Asia/Shanghai
3 | Log() {
4 | txt="/sdcard/Android/doze.log"
5 | echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >>$txt
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | /.idea/
17 | /app/release/
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## DozeConfig
2 |
3 | + 本APP配合我的深度Doze模块食用,更加简单方便添加白名单应用
4 |
5 | ### 使用条件
6 |
7 | + 必须刷了深度Doze模块,如果没有先刷一下模块哦(Magisk模块)
8 | + 必须给予读取应用列表和存储读写权限
9 | + 非必须授予Root权限,Root权限只是为了直接应用新的白名单
10 |
11 | ### 说明
12 |
13 | 1. 安卓开发新手,有不足可以指出
14 | 2. 要忙毕设了,有bug提交issues或者酷安私信和我说,会尽快修复
15 | 3. 参考了许多大佬的开源项目,非常感谢
16 |
17 | ### License
18 |
19 | 本项目基于[MIT]
20 |
21 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) Hwwwww 2021 https://github.com/HwwwwwLemon/DozeConfig All Rights Reserved.
3 | #
4 |
5 | #Mon May 10 11:36:30 CST 2021
6 | distributionBase=GRADLE_USER_HOME
7 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip
8 | distributionPath=wrapper/dists
9 | zipStorePath=wrapper/dists
10 | zipStoreBase=GRADLE_USER_HOME
11 |
--------------------------------------------------------------------------------
/dozewhitelist/module.prop:
--------------------------------------------------------------------------------
1 | id=dozewhitelist
2 | name=深度Doze&清理电池优化白名单
3 | version=2021.05.18
4 | versionCode=3
5 | author=酷安ID:Hwwwww
6 | description=❗️在/sdcard/Android路径下doze.conf白名单配置文件,没有则不优化,如果没有请到Doze配置APP内生成。❗️❗️扫描时间定为8s,不生效或者开屏联网过慢请到service.sh修改,暂时不打算做并行扫描,得不偿失。❗️❗️❗️如果真的睡死了尝试使用温和一点的代码,doze.sh里修改,然后你得把不温和的注释掉。❗️❗️❗️❗️有问题可以留言但最好先看看楼里有没有解答或者去看看之前的版本下有没有相关的问题,实在没有私信或者Github提交issues。v3更新:1、去除Toast提示(之后也只会有一个版本)。2、加入白名单控制APP(详细见APP👉关于)3、一些优化
--------------------------------------------------------------------------------
/dozewhitelist/whitelist.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | source /data/adb/modules/dozewhitelist/log.sh
3 |
4 | #执行移出电池优化名单
5 |
6 | if [ -f "/sdcard/Android/doze.conf" ]; then
7 | source /sdcard/Android/doze.conf
8 | noDozes=$(pm list packages -e | sed "s/package:/-/g")$whitelist
9 | dumpsys deviceidle whitelist $noDozes
10 | check=$?
11 | Log "执行清理电池优化名单,应用白名单 code:$check"
12 | if [[ $check == 0 ]]; then
13 | Log "清理电池优化名单成功!"
14 | else
15 | Log "清理电池优化名单成功!"
16 | fi
17 | else
18 | Log "未找到doze.conf,Doze白名单优化未执行,请到APP生成白名单或者自行创建白名单。"
19 | fi
20 |
--------------------------------------------------------------------------------
/dozewhitelist/service.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | # Please don't hardcode /magisk/modname/... ; instead, please use $MODDIR/...
3 | # This will make your scripts compatible even if Magisk change its mount point in the future
4 |
5 | until [ $(getprop init.svc.bootanim) = "stopped" ]; do
6 | sleep 2s
7 | done
8 | source /data/adb/modules/dozewhitelist/log.sh
9 |
10 | #扫描时间隔建议小于等于10s,不可以小于0,修改后重启生效,建议为8s
11 | scanInterval=8s
12 |
13 | sleep 20s
14 |
15 | echo "" >/sdcard/Android/doze.log
16 |
17 | Log "⚒开始执行doze.sh⚒"
18 |
19 | Log "👉开机首次刷新白名单"
20 | #首次刷新白名单
21 | sh /data/adb/modules/dozewhitelist/whitelist.sh
22 |
23 | while :; do
24 | sh /data/adb/modules/dozewhitelist/doze.sh
25 | sleep $scanInterval
26 | done
27 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/dozewhitelist/customize.sh:
--------------------------------------------------------------------------------
1 | SKIPUNZIP=0
2 | REPLACE="
3 | "
4 | if [[ $(find /data/app -name "com.github.hwwwwwlemon.dozeconfig*" -type d) ]]; then
5 | echo " * 已存在Toast依赖"
6 | rm -rf $MODPATH/dozeconfig.apk
7 | else
8 | echo "正在安装DozeConfig"
9 | echo "酷安@Hwwwww"
10 | pm install -r -g $MODPATH/dozeconfig.apk >/dev/null 2>&1
11 | if [[ $? == 0 ]]; then
12 | echo " * 安裝成功"
13 | else
14 | echo " * 安裝失败"
15 | fi
16 | rm -rf $MODPATH/dozeconfig.apk
17 | fi
18 |
19 | echo ""
20 | echo " 正在创建白名单 "
21 | echo "Path:/Android/doze.conf"
22 | cat $MODPATH/doze.conf >/storage/emulated/0/Android/doze.conf
23 |
24 | if [[ $? == 0 ]]; then
25 | echo "******************"
26 | echo " 安装完成 "
27 | echo "******************"
28 | else
29 | echo "******************"
30 | echo " 安装失败 "
31 | echo "******************"
32 | fi
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_applist.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT License (MIT)
3 |
4 | Copyright © 2021 Hwwwww
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | associated documentation files (the “Software”), to deal in the Software without restriction,
8 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all copies or substantial
13 | portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 |
21 |
--------------------------------------------------------------------------------
/dozewhitelist/doze.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | export TZ=Asia/Shanghai
3 | source /data/adb/modules/dozewhitelist/log.sh
4 |
5 | #识别屏幕状态
6 | screen=$(dumpsys window policy | grep "mInputRestricted" | cut -d= -f2)
7 |
8 | #Log "运行状态: $screen,DEEP:$(dumpsys deviceidle get deep),FORCE: $(dumpsys deviceidle get force)"
9 |
10 | dumpsys deviceidle | grep -q Enabled=true
11 | check=$?
12 |
13 | if [[ $screen == true ]]; then
14 | if [[ $check == 1 ]]; then
15 | #执行移出电池优化名单
16 | sh /data/adb/modules/dozewhitelist/whitelist.sh
17 | sleep 3s
18 | #level 1 dumpsys deviceidle enable
19 | #level 2 dumpsys deviceidle enable deep
20 | #默认开启level 3
21 | dumpsys deviceidle enable deep
22 | dumpsys deviceidle force-idle deep
23 |
24 | #修改记得注释掉
25 | Log "😴熄灭屏幕进入深度 Doze😴"
26 | #日志
27 | Log "运行状态: $screen,DEEP:$(dumpsys deviceidle get deep),FORCE: $(dumpsys deviceidle get force)"
28 | fi
29 | else
30 | if [[ $check == 0 ]]; then
31 |
32 | dumpsys deviceidle disable all
33 | dumpsys deviceidle unforce
34 |
35 | Log "🥱点亮屏幕退出深度 Doze🥱"
36 | #日志
37 | Log "运行状态: $screen,DEEP:$(dumpsys deviceidle get deep),FORCE: $(dumpsys deviceidle get force)"
38 | fi
39 | fi
40 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | include ':app'
24 | rootProject.name = "DozeConfig"
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 | 16dp
26 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) Hwwwww 2021 https://github.com/HwwwwwLemon/DozeConfig All Rights Reserved.
3 | #
4 |
5 | # Project-wide Gradle settings.
6 | # IDE (e.g. Android Studio) users:
7 | # Gradle settings configured through the IDE *will override*
8 | # any settings specified in this file.
9 | # For more details on how to configure your build environment visit
10 | # http://www.gradle.org/docs/current/userguide/build_environment.html
11 | # Specifies the JVM arguments used for the daemon process.
12 | # The setting is particularly useful for tweaking memory settings.
13 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 | # AndroidX package structure to make it clearer which packages are bundled with the
19 | # Android operating system, and which are packaged with your app"s APK
20 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
21 | android.useAndroidX=true
22 | # Automatically convert third-party libraries to use AndroidX
23 | android.enableJetifier=true
24 | # Kotlin code style for this project: "official" or "obsolete":
25 | kotlin.code.style=official
26 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 | #FFFFFF
27 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_run_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gradient_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
27 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/gradient_color_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
28 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_warning.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
32 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/test/java/com/github/hwwwwwlemon/dozeconfig/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig
24 |
25 | import org.junit.Test
26 |
27 | import org.junit.Assert.*
28 |
29 | /**
30 | * Example local unit test, which will execute on the development machine (host).
31 | *
32 | * See [testing documentation](http://d.android.com/tools/testing).
33 | */
34 | class ExampleUnitTest {
35 | @Test
36 | fun addition_isCorrect() {
37 | assertEquals(4, 2 + 2)
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
29 |
30 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
35 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_success_fill.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
28 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/tips_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
29 |
30 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_error_fill.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_question_fill.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.activity.base
24 |
25 | import androidx.appcompat.app.AppCompatActivity
26 | import androidx.appcompat.widget.Toolbar
27 | import com.github.hwwwwwlemon.dozeconfig.R
28 | import com.github.hwwwwwlemon.dozeconfig.utils.StatusBarUtil
29 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
30 |
31 | open class BaseActivity : AppCompatActivity() {
32 | open lateinit var mToolbar: Toolbar
33 |
34 | open fun initStatusBar() {
35 | mToolbar = findViewById(R.id.toolbar)
36 | setSupportActionBar(mToolbar)
37 | StatusBarUtil.immersive(this)
38 | StatusBarUtil.setPaddingSmart(this, mToolbar)
39 | if (!Utils.isDarkMode(this)) {
40 | StatusBarUtil.darkMode(this)
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/github/hwwwwwlemon/dozeconfig/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig
24 |
25 | import androidx.test.platform.app.InstrumentationRegistry
26 | import androidx.test.ext.junit.runners.AndroidJUnit4
27 |
28 | import org.junit.Test
29 | import org.junit.runner.RunWith
30 |
31 | import org.junit.Assert.*
32 |
33 | /**
34 | * Instrumented test, which will execute on an Android device.
35 | *
36 | * See [testing documentation](http://d.android.com/tools/testing).
37 | */
38 | @RunWith(AndroidJUnit4::class)
39 | class ExampleInstrumentedTest {
40 | @Test
41 | fun useAppContext() {
42 | // Context of the app under test.
43 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
44 | assertEquals("com.github.hwwwwwlemon.dozeconfig", appContext.packageName)
45 | }
46 | }
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_show_app_list.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_log.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_save.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_trash.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
28 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings.xml:
--------------------------------------------------------------------------------
1 |
3 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_assignment.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_info.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
33 |
36 |
37 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/settings_preferences.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
28 |
33 |
38 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 | #FFd4bff9
27 | #FFBB86FC
28 | #FF9965f4
29 | #FF7e3ff2
30 | #FF6200EE
31 | #FF4B00D1
32 | #FF3700B3
33 | #FFB2DFDB
34 | #FF03DAC5
35 | #FF4DB6AC
36 | #FF26A69A
37 | #FF009688
38 | #FF018786
39 | #FF000000
40 | #FFFFFFFF
41 | #4CAE50
42 | #FF2828
43 | #7AB67C
44 | #FF5858
45 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_icon.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
26 |
28 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_application_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
31 |
32 |
33 |
34 |
38 |
41 |
42 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/shortcuts.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 |
27 |
33 |
37 |
38 |
44 |
48 |
49 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_doze_run_log.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
31 |
32 |
33 |
39 |
44 |
45 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
39 |
40 |
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/shortcuts/RefreshDozeWhitelist.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 |
24 | package com.github.hwwwwwlemon.dozeconfig.activity.shortcuts
25 |
26 | import android.app.Activity
27 | import android.os.Bundle
28 | import android.os.Handler
29 | import com.github.hwwwwwlemon.dozeconfig.R
30 | import com.github.hwwwwwlemon.dozeconfig.utils.DozeFileUtil
31 | import com.github.hwwwwwlemon.dozeconfig.utils.StatusBarUtil
32 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
33 | import kotlin.system.exitProcess
34 |
35 | class RefreshDozeWhitelist : Activity() {
36 | override fun onCreate(savedInstanceState: Bundle?) {
37 | super.onCreate(savedInstanceState)
38 | StatusBarUtil.immersive(this)
39 | }
40 |
41 | override fun onResume() {
42 | super.onResume()
43 | if (DozeFileUtil.checkAppList.size == 0) {
44 | DozeFileUtil.loadDozeFile(this)
45 | }
46 | val handler = Handler()
47 | handler.postDelayed({
48 | if (Utils.refreshDozeWhitelist(this)) {
49 | Utils.showToast(this, getString(R.string.whitelist_opt_success))
50 | } else {
51 | Utils.showToast(this, getString(R.string.whitelist_opt_failed))
52 | }
53 | finish()
54 | }, 500)
55 | handler.postDelayed({
56 | exitProcess(0)
57 | }, 3000)
58 | }
59 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_rocket_fill.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/utils/ToastUtil.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.utils
24 |
25 |
26 | import android.R
27 | import android.annotation.SuppressLint
28 | import android.content.Context
29 | import android.graphics.Color
30 | import android.os.Handler
31 | import android.view.Gravity
32 | import android.widget.LinearLayout
33 | import android.widget.TextView
34 | import android.widget.Toast
35 |
36 |
37 | class ToastUtil {
38 | private var toast: Toast? = null
39 |
40 | fun init(ctx: Context, message: String): ToastUtil {
41 | default(ctx, message)
42 | return this
43 | }
44 |
45 | fun init(ctx: Context, res: Int): ToastUtil {
46 | default(ctx, ctx.getString(res))
47 | return this
48 | }
49 |
50 | @SuppressLint("ShowToast")
51 | private fun default(ctx: Context, message: String): ToastUtil {
52 | toast = Toast.makeText(ctx, message, Toast.LENGTH_SHORT)
53 | val view: LinearLayout = toast?.view as LinearLayout
54 | view.gravity = Gravity.CENTER
55 | val tv = view.findViewById(R.id.message) as TextView
56 | tv.setBackgroundColor(Color.TRANSPARENT)
57 | tv.gravity = Gravity.CENTER
58 | return this
59 | }
60 |
61 | fun indefinite(duration: Long): ToastUtil {
62 | Handler().postDelayed({ toast?.cancel() }, duration)
63 | return this
64 | }
65 |
66 | fun show() {
67 | toast?.show()
68 | }
69 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
39 |
40 |
41 |
42 |
49 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
27 |
28 |
30 |
31 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
62 |
63 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
30 |
32 |
33 |
39 |
42 |
45 |
46 |
47 |
48 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
30 |
37 |
38 |
42 |
47 |
51 |
57 |
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/SplashActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.activity
24 |
25 | import android.content.Intent
26 | import android.os.Bundle
27 | import android.os.Handler
28 | import android.text.method.LinkMovementMethod
29 | import androidx.appcompat.app.AppCompatActivity
30 | import androidx.core.text.HtmlCompat
31 | import com.github.hwwwwwlemon.dozeconfig.DozeManager
32 | import com.github.hwwwwwlemon.dozeconfig.MainActivity
33 | import com.github.hwwwwwlemon.dozeconfig.R
34 | import com.github.hwwwwwlemon.dozeconfig.databinding.ActivitySplashBinding
35 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
36 |
37 | class SplashActivity : AppCompatActivity() {
38 | private lateinit var mBinding: ActivitySplashBinding
39 | override fun onCreate(savedInstanceState: Bundle?) {
40 | super.onCreate(savedInstanceState)
41 | mBinding = ActivitySplashBinding.inflate(layoutInflater)
42 | setContentView(mBinding.root)
43 |
44 | mBinding.author.movementMethod = LinkMovementMethod.getInstance();
45 | mBinding.author.text =
46 | HtmlCompat.fromHtml(
47 | getString(R.string.author) + "@Hwwwww",
48 | HtmlCompat.FROM_HTML_MODE_LEGACY
49 | )
50 | mBinding.version.text = "version: " + resources.getString(R.string.version)
51 | }
52 |
53 | override fun onResume() {
54 | try {
55 | val handler = Handler()
56 | handler.postDelayed({
57 | if (DozeManager.checkPermission(this)) {
58 | Utils.showToast(this, "😴")
59 | val intent = Intent(this, MainActivity::class.java)
60 | startActivity(intent)
61 | finish()
62 | } else {
63 | mBinding.prompt.text = getString(R.string.permission_prompt)
64 | }
65 |
66 | }, 1500)
67 | } catch (e: Exception) {
68 | e.printStackTrace()
69 | }
70 |
71 | super.onResume()
72 | }
73 | }
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/utils/MyPreferences.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.utils
24 |
25 | import android.annotation.SuppressLint
26 | import android.content.Context
27 | import android.content.SharedPreferences
28 | import androidx.preference.PreferenceManager
29 |
30 |
31 | class MyPreferences {
32 |
33 | private val TAG = "MyPreferences"
34 | private lateinit var sharedPreferences: SharedPreferences
35 | private lateinit var editor: SharedPreferences.Editor
36 |
37 | @SuppressLint("CommitPrefEdits")
38 | constructor(ctx: Context) {
39 | sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ctx)
40 | editor = sharedPreferences.edit()
41 | }
42 |
43 | @SuppressLint("CommitPrefEdits")
44 | constructor(ctx: Context, fileName:String){
45 | sharedPreferences = ctx.getSharedPreferences(fileName,Context.MODE_PRIVATE)
46 | editor = sharedPreferences.edit()
47 | }
48 |
49 |
50 | fun save(key: String, defValue: Any) {
51 | when (defValue) {
52 | is Int -> editor.putInt(key, defValue)
53 | is Float -> editor.putFloat(key, defValue)
54 | is String -> editor.putString(key, defValue)
55 | is Boolean -> editor.putBoolean(key, defValue)
56 | is Long -> editor.putLong(key, defValue)
57 | }
58 | editor.apply()
59 |
60 | }
61 |
62 | fun get(key: String, defValue: Any): Any {
63 | return when (defValue) {
64 | is Int -> sharedPreferences.getInt(key, defValue)
65 | is Float -> sharedPreferences.getFloat(key, defValue)
66 | is String -> sharedPreferences.getString(key, defValue) as Any
67 | is Boolean -> sharedPreferences.getBoolean(key, defValue)
68 | is Long -> sharedPreferences.getLong(key, defValue)
69 | else -> ""
70 | }
71 | }
72 |
73 |
74 | fun removeUserInfo(key: String) {
75 | editor.remove(key)
76 | editor.apply()
77 | }
78 |
79 |
80 | fun clearUserInfo() {
81 | editor.clear()
82 | editor.apply()
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/utils/Utils.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.utils
24 |
25 | import android.content.Context
26 | import android.content.pm.ApplicationInfo
27 | import android.content.pm.PackageManager
28 | import android.content.res.Configuration
29 | import android.util.Log
30 | import android.util.TypedValue
31 | import java.io.DataOutputStream
32 |
33 |
34 | object Utils {
35 |
36 | fun refreshDozeWhitelist(ctx: Context): Boolean {
37 |
38 | if (DozeFileUtil.checkAppList.size==0){
39 | return false
40 | }
41 | val sb = StringBuffer("dumpsys deviceidle whitelist ")
42 | val app = getAppList(ctx)
43 | app.forEach {
44 | sb.append("-").append(it.packageName).append(" ")
45 | }
46 | DozeFileUtil.checkAppList.forEach {
47 | sb.append("+").append(it.packageName).append(" ")
48 | }
49 | val suProcess = Runtime.getRuntime().exec("su")
50 | val os = DataOutputStream(suProcess.outputStream)
51 | os.writeBytes(sb.toString())
52 | os.flush()
53 | os.close()
54 | val exitValue = suProcess.waitFor()
55 | Log.e("code", exitValue.toString())
56 | return exitValue == 0
57 | }
58 |
59 |
60 | fun isDarkMode(ctx: Context): Boolean {
61 | val mode = ctx.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
62 | return mode == Configuration.UI_MODE_NIGHT_YES;
63 | }
64 |
65 | fun getColorPrimary(ctx: Context): Int {
66 | val typedValue = TypedValue()
67 | ctx.theme.resolveAttribute(android.R.attr.colorPrimary, typedValue, true)
68 | return typedValue.data
69 | }
70 |
71 | fun getAppList(ctx: Context): MutableList {
72 | val pm: PackageManager = ctx.packageManager
73 | return pm.getInstalledApplications(0)
74 |
75 | }
76 |
77 | fun showToast(ctx: Context, content: String, duration: Int = 3000) {
78 | ToastUtil().init(ctx, content).indefinite(duration.toLong()).show()
79 | }
80 |
81 | fun showToast(ctx: Context, res: Int, duration: Int = 3000) {
82 | ToastUtil().init(ctx, res).indefinite(duration.toLong()).show()
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/utils/DozeFileUtil.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.utils
24 |
25 | import android.content.Context
26 | import android.content.pm.ApplicationInfo
27 | import com.github.hwwwwwlemon.dozeconfig.DozeManager
28 | import com.github.hwwwwwlemon.dozeconfig.adapter.ApplicationAdapter
29 | import kotlinx.coroutines.*
30 |
31 | object DozeFileUtil {
32 | val checkAppList = mutableListOf()
33 | val errorList = mutableListOf()
34 | var dozeApps = mutableListOf()
35 | private val controlScope = CoroutineScope(Dispatchers.Default)
36 | fun loadDozeFile(ctx: Context): Boolean {
37 | var flag = true
38 | try {
39 | checkAppList.clear()
40 | dozeApps.clear()
41 | errorList.clear()
42 | val dozeContent = DozeManager.readFile(DozeManager.DOZE_FILE_PATH, ctx, "\n")
43 | val pm = ctx.packageManager
44 | Regex("[a-z0-9]{1,24}\\.(.+)").findAll(dozeContent).forEach {
45 | dozeApps.add(it.value.trim())
46 | }
47 | for (i in dozeApps) {
48 | try {
49 | val app = pm.getApplicationInfo(i, 0)
50 | val flag = if ((app.flags and ApplicationInfo.FLAG_SYSTEM) == 0) 1 else 2
51 | checkAppList.add(
52 | ApplicationAdapter.Apps(
53 | app,
54 | i,
55 | pm.getApplicationLabel(app).toString(),
56 | flag,
57 | )
58 | )
59 | } catch (e: Exception) {
60 | e.printStackTrace()
61 | errorList.add("\uD83D\uDC49 $i ❌")
62 | flag = false
63 | continue
64 | }
65 | }
66 |
67 | } catch (e: Exception) {
68 | e.printStackTrace()
69 | flag = false
70 | }
71 | return flag
72 | }
73 |
74 |
75 | fun saveDozeFile(ctx: Context): Boolean {
76 | return runBlocking {
77 | controlScope.launch {
78 | val sb = StringBuilder("whitelist=\"\n")
79 | checkAppList.forEach {
80 | sb.append("+").append(it.packageName).append("\n")
81 | }
82 | val result = sb.append("\"").toString()
83 | DozeManager.writeFile(DozeManager.DOZE_FILE_PATH, result, ctx)
84 | }
85 | delay(200L)
86 | return@runBlocking DozeManager.checkDozeFile(ctx)
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | plugins {
24 | id 'com.android.application'
25 | id 'kotlin-android'
26 | }
27 | repositories {
28 | maven { url 'https://www.jitpack.io' }
29 | }
30 | android {
31 | compileSdkVersion 29
32 | buildToolsVersion "30.0.3"
33 |
34 | defaultConfig {
35 | applicationId "com.github.hwwwwwlemon.dozeconfig"
36 | minSdkVersion 25
37 | targetSdkVersion 29
38 | versionCode 10202
39 | versionName "1.2.2 Release"
40 |
41 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
42 |
43 | ndk {
44 | abiFilters 'arm64-v8a'//'armeabi-v7a', 'x86','armeabi'','x86_64','arm64-v8a'
45 | }
46 | }
47 |
48 | buildTypes {
49 | release {
50 | minifyEnabled false
51 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
52 | }
53 | }
54 | buildFeatures {
55 | dataBinding true
56 | viewBinding true
57 | }
58 | compileOptions {
59 | sourceCompatibility JavaVersion.VERSION_1_8
60 | targetCompatibility JavaVersion.VERSION_1_8
61 | }
62 | android {
63 | packagingOptions {
64 | exclude 'META-INF/*.kotlin_module'
65 | }
66 | }
67 |
68 | kotlinOptions {
69 | jvmTarget = '1.8'
70 | }
71 | }
72 |
73 | dependencies {
74 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
75 | implementation 'androidx.core:core-ktx:1.3.2'
76 | implementation 'androidx.appcompat:appcompat:1.2.0'
77 | implementation 'com.google.android.material:material:1.3.0'
78 | implementation 'androidx.preference:preference-ktx:1.1.1'
79 | implementation 'com.android.support.constraint:constraint-layout:2.0.4'
80 | implementation "androidx.recyclerview:recyclerview:1.2.0"
81 |
82 | implementation 'me.zhanghai.android.fastscroll:library:1.1.5'
83 | implementation 'com.scwang.smart:refresh-layout-kernel:2.0.3'
84 | implementation 'com.scwang.smart:refresh-header-material:2.0.3'
85 | implementation 'com.github.bumptech.glide:glide:4.12.0'
86 | implementation 'androidx.preference:preference-ktx:1.1.1'
87 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
88 | annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
89 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
90 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
91 | testImplementation 'junit:junit:4.13.2'
92 | androidTestImplementation 'androidx.test.ext:junit:1.1.2'
93 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
94 |
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/app/src/main/res/values-zh-rCN/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
26 | Doze配置
27 | 欢迎使用
28 | 模块运行日志
29 | 设置
30 | 关于
31 | 白名单列表
32 | 应用列表
33 | 选择Doze白名单
34 | 未找到白名单文件
35 | 请检查 sdcard/Android/doze.conf 是否存在?
36 | 找到白名单文件
37 | 尽情享用吧!🚀(点我)
38 | 白名单文件发生了错误!😭(点我查看错误)
39 | 搜索
40 | 请输入包名或应用名
41 | 日志文件
42 | 没有找到日志文件!
43 | 找到日志文件!
44 | 日志
45 | 显示系统应用
46 | 保存
47 | 删除日志
48 | 酷安:
49 |
50 | 这个应用是为了方便Doze模块添加白名单开发的。\n我们会获取一些隐私相关的权限来保证应用的正常运行:\n👉1、存储读写权限(读取白名单以及日志文件)\n👉2、读取应用列表权限(读取应用列表)\n👉3、Root权限(优化白名单)\n你在使用的过程中如果遇到任何问题(如Bug、程序崩溃等)可以在GitHub提交issues或者在酷安私信我
51 |
52 | 提示
53 | 你确定要删除日志文件?
54 | 更新日志:\n1、修复bug\n2、添加配置文件错误查看器
55 |
56 | 请给予相关权限(读写手机存储权限),否则无法正常使用本应用!
57 |
58 | 我还在滑动,给我停下来再操作!
59 | 保存成功!
60 | 保存失败!
61 |
62 | 常规
63 | 高级
64 | 延迟加载图标
65 | 在滑动的时候降低CPU的占用(开了约等于没开,作用也不是很大)
66 | 开启白名单优化
67 | 点击主界面卡片5次优化(需要Root)
68 | 自动保存Doze配置
69 | 自动保存doze.conf不需要点击右上角的保存
70 | 优化白名单
71 | 应用列表
72 | 优化成功!
73 | 优化失败!
74 | 删除配置文件
75 | 取消
76 | 确定
77 | 删除成功!
78 | 删除失败!
79 | 此操作会删除Doze白名单配置文件,这会直接导致模块和应用无法正常的工作。\n\n你确定删除吗?
80 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/application_unit_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
31 |
32 |
33 |
40 |
41 |
49 |
50 |
62 |
63 |
77 |
78 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/DozeRunLogActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.activity
24 |
25 | import android.os.Bundle
26 | import android.view.Menu
27 | import android.view.MenuItem
28 | import android.widget.TextView
29 | import androidx.appcompat.app.AlertDialog
30 | import com.github.hwwwwwlemon.dozeconfig.DozeManager
31 | import com.github.hwwwwwlemon.dozeconfig.R
32 | import com.github.hwwwwwlemon.dozeconfig.activity.base.BaseActivity
33 | import com.github.hwwwwwlemon.dozeconfig.databinding.ActivityDozeRunLogBinding
34 | import com.github.hwwwwwlemon.dozeconfig.databinding.TipsLayoutBinding
35 |
36 | class DozeRunLogActivity : BaseActivity() {
37 | private lateinit var mBinding: ActivityDozeRunLogBinding
38 | private lateinit var mLogContent: String
39 | private lateinit var mLogTextView: TextView
40 | override fun onCreate(savedInstanceState: Bundle?) {
41 | super.onCreate(savedInstanceState)
42 | mBinding = ActivityDozeRunLogBinding.inflate(layoutInflater)
43 | setContentView(mBinding.root)
44 | initStatusBar()
45 | }
46 |
47 | override fun onResume() {
48 | loadLogData()
49 | super.onResume()
50 | }
51 |
52 | override fun initStatusBar() {
53 | super.initStatusBar()
54 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
55 | supportActionBar?.setHomeButtonEnabled(true)
56 | supportActionBar?.title = getString(R.string.doze_run_log)
57 | }
58 |
59 | private fun loadLogData() {
60 | try {
61 | mLogContent = DozeManager.readFile("Android/doze.log", this, "\n")
62 | if (mLogContent.isEmpty()) {
63 | mLogContent = getString(R.string.found_log_file) + "但是内容为空!"
64 | }
65 | } catch (e: Exception) {
66 | mLogContent = getString(R.string.not_found_log_file)
67 | }
68 | mLogTextView = mBinding.logContent
69 | mLogTextView.text = mLogContent
70 | }
71 |
72 | override fun onCreateOptionsMenu(menu: Menu?): Boolean {
73 | menuInflater.inflate(R.menu.menu_run_log, menu)
74 | return true
75 | }
76 |
77 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
78 | return when (item.itemId) {
79 | R.id.delete_log -> {
80 | val promptBinding = TipsLayoutBinding.inflate(layoutInflater)
81 | promptBinding.promptContent.text = getString(R.string.prompt_delete_log)
82 | val alertDialogBuilder = AlertDialog.Builder(this)
83 | alertDialogBuilder.setTitle(R.string.prompt)
84 | alertDialogBuilder.setView(promptBinding.root)
85 | alertDialogBuilder.setNegativeButton(
86 | "OK"
87 | ) { _, _ ->
88 | run {
89 | DozeManager.deleteFile("Android/doze.log", this)
90 | loadLogData()
91 | }
92 | }
93 |
94 | alertDialogBuilder.setPositiveButton(
95 | "Cancel"
96 | ) { dialog, _ ->
97 | dialog.cancel()
98 | }
99 | val dialog = alertDialogBuilder.create()
100 | dialog.show()
101 | true
102 | }
103 | android.R.id.home -> {
104 | finish()
105 | true
106 | }
107 | else -> super.onOptionsItemSelected(item)
108 | }
109 | }
110 |
111 | }
--------------------------------------------------------------------------------
/dozewhitelist/META-INF/com/google/android/update-binary:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 |
3 | #################
4 | # Initialization
5 | #################
6 |
7 | umask 022
8 |
9 | # Global vars
10 | TMPDIR=/dev/tmp
11 | PERSISTDIR=/sbin/.magisk/mirror/persist
12 |
13 | rm -rf $TMPDIR 2>/dev/null
14 | mkdir -p $TMPDIR
15 |
16 | # echo before loading util_functions
17 | ui_print() { echo "$1"; }
18 |
19 | require_new_magisk() {
20 | ui_print "*******************************"
21 | ui_print " Please install Magisk v19.0+! "
22 | ui_print "*******************************"
23 | exit 1
24 | }
25 |
26 | is_legacy_script() {
27 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh
28 | return $?
29 | }
30 |
31 | print_modname() {
32 | local len
33 | len=$(echo -n $MODNAME | wc -c)
34 | len=$((len + 2))
35 | local pounds=$(printf "%${len}s" | tr ' ' '*')
36 | ui_print "$pounds"
37 | ui_print " $MODNAME "
38 | ui_print "$pounds"
39 | ui_print "******************************"
40 | ui_print "* Powered by Magisk "
41 | ui_print "******************************"
42 | ui_print "******************************"
43 | ui_print "* @Hwwwww "
44 | ui_print "******************************"
45 | }
46 |
47 | ##############
48 | # Environment
49 | ##############
50 |
51 | OUTFD=$2
52 | ZIPFILE=$3
53 |
54 | mount /data 2>/dev/null
55 |
56 | # Load utility functions
57 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
58 | . /data/adb/magisk/util_functions.sh
59 | [ $MAGISK_VER_CODE -gt 18100 ] || require_new_magisk
60 |
61 | # Preperation for flashable zips
62 | setup_flashable
63 |
64 | # Mount partitions
65 | mount_partitions
66 |
67 | # Detect version and architecture
68 | api_level_arch_detect
69 |
70 | # Setup busybox and binaries
71 | $BOOTMODE && boot_actions || recovery_actions
72 |
73 | ##############
74 | # Preparation
75 | ##############
76 |
77 | # Extract prop file
78 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2
79 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!"
80 |
81 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules
82 | MODULEROOT=$NVBASE/$MODDIRNAME
83 | MODID=$(grep_prop id $TMPDIR/module.prop)
84 | MODPATH=$MODULEROOT/$MODID
85 | MODNAME=$(grep_prop name $TMPDIR/module.prop)
86 |
87 | # Create mod paths
88 | rm -rf $MODPATH 2>/dev/null
89 | mkdir -p $MODPATH
90 |
91 | ##########
92 | # Install
93 | ##########
94 |
95 | if is_legacy_script; then
96 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2
97 |
98 | # Load install script
99 | . $TMPDIR/install.sh
100 |
101 | # Callbacks
102 | print_modname
103 | on_install
104 |
105 | # Custom uninstaller
106 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh
107 |
108 | # Skip mount
109 | $SKIPMOUNT && touch $MODPATH/skip_mount
110 |
111 | # prop file
112 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop
113 |
114 | # Module info
115 | cp -af $TMPDIR/module.prop $MODPATH/module.prop
116 |
117 | # post-fs-data scripts
118 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh
119 |
120 | # service scripts
121 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh
122 |
123 | ui_print "- Setting permissions"
124 | set_permissions
125 | else
126 | print_modname
127 |
128 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2
129 |
130 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then
131 | ui_print "- Extracting module files"
132 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2
133 |
134 | # Default permissions
135 | set_perm_recursive $MODPATH 0 0 0755 0644
136 | fi
137 |
138 | # Load customization script
139 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh
140 | fi
141 |
142 | # Handle replace folders
143 | for TARGET in $REPLACE; do
144 | ui_print "- Replace target: $TARGET"
145 | mktouch $MODPATH$TARGET/.replace
146 | done
147 |
148 | if $BOOTMODE; then
149 | # Update info for Magisk Manager
150 | mktouch $NVBASE/modules/$MODID/update
151 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop
152 | fi
153 |
154 | # Copy over custom sepolicy rules
155 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then
156 | ui_print "- Installing custom sepolicy patch"
157 | PERSISTMOD=$PERSISTDIR/magisk/$MODID
158 | mkdir -p $PERSISTMOD
159 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule
160 | fi
161 |
162 | # Remove stuffs that don't belong to modules
163 | rm -rf \
164 | $MODPATH/system/placeholder $MODPATH/customize.sh \
165 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null
166 |
167 | ##############
168 | # Finalizing
169 | ##############
170 |
171 | cd /
172 | $BOOTMODE || recovery_cleanup
173 | rm -rf $TMPDIR
174 |
175 | ui_print "- Done"
176 | exit 0
177 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_about.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 |
26 |
32 |
33 |
39 |
40 |
46 |
47 |
55 |
56 |
57 |
58 |
59 |
66 |
67 |
72 |
73 |
80 |
87 |
88 |
96 |
97 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/SettingsActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.activity
24 |
25 | import android.content.DialogInterface
26 | import android.os.Bundle
27 | import android.os.CountDownTimer
28 | import android.view.Menu
29 | import android.view.MenuItem
30 | import android.widget.Button
31 | import androidx.appcompat.app.AlertDialog
32 | import androidx.preference.PreferenceFragmentCompat
33 | import com.github.hwwwwwlemon.dozeconfig.DozeManager
34 | import com.github.hwwwwwlemon.dozeconfig.R
35 | import com.github.hwwwwwlemon.dozeconfig.activity.base.BaseActivity
36 | import com.github.hwwwwwlemon.dozeconfig.databinding.ActivitySettingsBinding
37 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
38 |
39 |
40 | class SettingsActivity : BaseActivity() {
41 | private lateinit var mBinding: ActivitySettingsBinding
42 | private lateinit var mDialog: AlertDialog
43 | override fun onCreate(savedInstanceState: Bundle?) {
44 | super.onCreate(savedInstanceState)
45 | mBinding = ActivitySettingsBinding.inflate(layoutInflater)
46 | setContentView(mBinding.root)
47 | if (savedInstanceState == null) {
48 | supportFragmentManager.beginTransaction()
49 | .add(R.id.container, SettingsFragment()).commit()
50 | }
51 |
52 | initStatusBar()
53 | }
54 |
55 | override fun initStatusBar() {
56 | super.initStatusBar()
57 | supportActionBar?.setDisplayHomeAsUpEnabled(true)
58 | supportActionBar?.setHomeButtonEnabled(true)
59 | supportActionBar?.title = getString(R.string.settings)
60 | }
61 |
62 | override fun onCreateOptionsMenu(menu: Menu?): Boolean {
63 | menuInflater.inflate(R.menu.menu_settings, menu)
64 | return true
65 | }
66 |
67 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
68 | return when (item.itemId) {
69 | android.R.id.home -> {
70 | finish()
71 | true
72 | }
73 | R.id.delete_config -> {
74 |
75 | val builder: AlertDialog.Builder = AlertDialog.Builder(this)
76 | builder.setTitle(R.string.prompt)
77 | builder.setMessage(R.string.delete_config_dialog)
78 | builder.setPositiveButton(getString(R.string.cancel)) { _, _ ->
79 | mDialog.dismiss()
80 | }
81 | builder.setNegativeButton(getString(R.string.confirm)) { _, _ ->
82 | try {
83 | if (DozeManager.deleteFile(DozeManager.DOZE_FILE_PATH, this)) {
84 | Utils.showToast(this, R.string.delete_success)
85 | }
86 | } catch (e: Exception) {
87 | Utils.showToast(this, R.string.delete_failed)
88 | }
89 | }
90 | mDialog = builder.create()
91 | mDialog.show()
92 | val btn: Button = mDialog.getButton(DialogInterface.BUTTON_NEGATIVE)
93 | val timer: CountDownTimer = object : CountDownTimer(6000, 1000) {
94 | override fun onTick(arg0: Long) {
95 | val thetime = (arg0 / 1000).toInt()
96 | mDialog.getButton(DialogInterface.BUTTON_NEGATIVE).text =
97 | "${getString(R.string.confirm)}${if (thetime > 0) "($thetime)" else ""}"
98 | }
99 |
100 | override fun onFinish() {
101 | btn.isEnabled = true
102 | }
103 | }
104 | btn.isEnabled = false
105 | timer.start()
106 | true
107 | }
108 | else -> super.onOptionsItemSelected(item)
109 | }
110 | }
111 |
112 | class SettingsFragment : PreferenceFragmentCompat() {
113 | override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
114 | setPreferencesFromResource(R.xml.settings_preferences, rootKey)
115 | }
116 | }
117 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 | DozeConfig
26 | Welcome
27 | Module run log
28 | Settings
29 | About
30 | Whitelist
31 | Applications
32 | Choose doze whitelist
33 | Not found whitelist file
34 | Please check sdcard/Android/doze.conf is exists?
35 | Found whitelist file!
36 | Please enjoy! 🚀(Click me)
37 | Whitelist file is error! 😭(Click me)
38 | Log File
39 | Not found log file!
40 | Found log file!
41 | Search
42 | Please input package name or app name
43 | Log
44 | Show system apps
45 | Save
46 | Delete log
47 | GitHub:
48 | Coolapk:
49 | This application was developed for the convenience of adding a whitelist to the
50 | Doze module. \nWe will obtain some privacy-related permissions to ensure the normal operation of the
51 | application:\n👉1, storage read and write permissions (read whitelist and log files)\n👉2, read application list
52 | permissions (read application list )\n👉3, Root permission (optimized whitelist)\nIf you encounter any problems
53 | (such as bugs, program crashes, etc.) during use, you can submit an issue on GitHub or privately write to me in
54 | Coolapk
55 |
56 | 1.2.2 Release
57 | Tips
58 | Are sure delete log file?
59 | Features:\n1. Fix bugs
60 |
61 | Please give relevant permissions (read and write mobile phone storage permissions),
62 | otherwise you will not be able to use this application normally!
63 |
64 | I\'m still sliding, please stop and do it again!
65 | Save successfully!
66 | Save failed!
67 |
68 | Common setting
69 | Advanced setting
70 | Lazy load icon
71 | Reduce the CPU usage when sliding
72 | Run doze whitelist optimization
73 | Tap the main interface card 5 times to optimize (Root)
74 | Auto save doze config
75 | Auto save doze.conf
76 | Optimize the whitelist
77 | APP List
78 | Successfully!
79 | Failed!
80 | Delete config file
81 | Cancel
82 | Confirm
83 | Delete successfully!
84 | Delete failed!
85 | This operation will delete the Doze whitelist configuration file, which will
86 | directly cause the module and application to not work properly.\n\nAre you sure to delete it?
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright (c) Hwwwww 2021 https://github.com/HwwwwwLemon/DozeConfig All Rights Reserved.
5 | #
6 |
7 | ##############################################################################
8 | ##
9 | ## Gradle start up script for UN*X
10 | ##
11 | ##############################################################################
12 |
13 | # Attempt to set APP_HOME
14 | # Resolve links: $0 may be a link
15 | PRG="$0"
16 | # Need this for relative symlinks.
17 | while [ -h "$PRG" ] ; do
18 | ls=`ls -ld "$PRG"`
19 | link=`expr "$ls" : '.*-> \(.*\)$'`
20 | if expr "$link" : '/.*' > /dev/null; then
21 | PRG="$link"
22 | else
23 | PRG=`dirname "$PRG"`"/$link"
24 | fi
25 | done
26 | SAVED="`pwd`"
27 | cd "`dirname \"$PRG\"`/" >/dev/null
28 | APP_HOME="`pwd -P`"
29 | cd "$SAVED" >/dev/null
30 |
31 | APP_NAME="Gradle"
32 | APP_BASE_NAME=`basename "$0"`
33 |
34 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
35 | DEFAULT_JVM_OPTS=""
36 |
37 | # Use the maximum available, or set MAX_FD != -1 to use that value.
38 | MAX_FD="maximum"
39 |
40 | warn () {
41 | echo "$*"
42 | }
43 |
44 | die () {
45 | echo
46 | echo "$*"
47 | echo
48 | exit 1
49 | }
50 |
51 | # OS specific support (must be 'true' or 'false').
52 | cygwin=false
53 | msys=false
54 | darwin=false
55 | nonstop=false
56 | case "`uname`" in
57 | CYGWIN* )
58 | cygwin=true
59 | ;;
60 | Darwin* )
61 | darwin=true
62 | ;;
63 | MINGW* )
64 | msys=true
65 | ;;
66 | NONSTOP* )
67 | nonstop=true
68 | ;;
69 | esac
70 |
71 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
72 |
73 | # Determine the Java command to use to start the JVM.
74 | if [ -n "$JAVA_HOME" ] ; then
75 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
76 | # IBM's JDK on AIX uses strange locations for the executables
77 | JAVACMD="$JAVA_HOME/jre/sh/java"
78 | else
79 | JAVACMD="$JAVA_HOME/bin/java"
80 | fi
81 | if [ ! -x "$JAVACMD" ] ; then
82 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
83 |
84 | Please set the JAVA_HOME variable in your environment to match the
85 | location of your Java installation."
86 | fi
87 | else
88 | JAVACMD="java"
89 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
90 |
91 | Please set the JAVA_HOME variable in your environment to match the
92 | location of your Java installation."
93 | fi
94 |
95 | # Increase the maximum file descriptors if we can.
96 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
97 | MAX_FD_LIMIT=`ulimit -H -n`
98 | if [ $? -eq 0 ] ; then
99 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
100 | MAX_FD="$MAX_FD_LIMIT"
101 | fi
102 | ulimit -n $MAX_FD
103 | if [ $? -ne 0 ] ; then
104 | warn "Could not set maximum file descriptor limit: $MAX_FD"
105 | fi
106 | else
107 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
108 | fi
109 | fi
110 |
111 | # For Darwin, add options to specify how the application appears in the dock
112 | if $darwin; then
113 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
114 | fi
115 |
116 | # For Cygwin, switch paths to Windows format before running java
117 | if $cygwin ; then
118 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
119 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
120 | JAVACMD=`cygpath --unix "$JAVACMD"`
121 |
122 | # We build the pattern for arguments to be converted via cygpath
123 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
124 | SEP=""
125 | for dir in $ROOTDIRSRAW ; do
126 | ROOTDIRS="$ROOTDIRS$SEP$dir"
127 | SEP="|"
128 | done
129 | OURCYGPATTERN="(^($ROOTDIRS))"
130 | # Add a user-defined pattern to the cygpath arguments
131 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
132 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
133 | fi
134 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
135 | i=0
136 | for arg in "$@" ; do
137 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
138 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
139 |
140 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
141 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
142 | else
143 | eval `echo args$i`="\"$arg\""
144 | fi
145 | i=$((i+1))
146 | done
147 | case $i in
148 | (0) set -- ;;
149 | (1) set -- "$args0" ;;
150 | (2) set -- "$args0" "$args1" ;;
151 | (3) set -- "$args0" "$args1" "$args2" ;;
152 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
153 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
154 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
155 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
156 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
157 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
158 | esac
159 | fi
160 |
161 | # Escape application args
162 | save () {
163 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
164 | echo " "
165 | }
166 | APP_ARGS=$(save "$@")
167 |
168 | # Collect all arguments for the java command, following the shell quoting and substitution rules
169 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
170 |
171 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
172 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
173 | cd "$(dirname "$0")"
174 | fi
175 |
176 | exec "$JAVACMD" "$@"
177 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
31 |
33 |
35 |
37 |
39 |
41 |
43 |
45 |
47 |
49 |
51 |
53 |
55 |
57 |
59 |
61 |
63 |
65 |
67 |
69 |
71 |
73 |
75 |
77 |
79 |
81 |
83 |
85 |
87 |
89 |
91 |
93 |
95 |
97 |
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/DozeManager.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig
24 |
25 | import android.Manifest
26 | import android.app.Activity
27 | import android.content.Context
28 | import android.content.Intent
29 | import android.content.pm.PackageManager
30 | import android.os.Environment
31 | import android.os.Process
32 | import android.util.Log
33 | import androidx.core.app.ActivityCompat
34 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
35 | import java.io.*
36 |
37 |
38 | object DozeManager {
39 | private const val REQUEST_EXTERNAL_STORAGE = 1
40 | const val DOZE_FILE_PATH = "Android/doze.conf"
41 | const val DOZE_LOG_PATH = "Android/doze.log"
42 | private val SDCARD_PATH = File(Environment.getExternalStorageDirectory().path)
43 | private val PERMISSIONS_STORAGE = arrayOf(
44 | "android.permission.READ_EXTERNAL_STORAGE",
45 | "android.permission.WRITE_EXTERNAL_STORAGE"
46 | )
47 |
48 |
49 | fun checkDozeFile(ctx: Context): Boolean {
50 | try {
51 | if (checkPermission(ctx)) {
52 | val file = File(SDCARD_PATH, DOZE_FILE_PATH)
53 | return file.exists()
54 | }
55 | } catch (e: FileNotFoundException) {
56 | e.printStackTrace()
57 | }
58 | return false
59 | }
60 |
61 | fun deleteFile(path: String, ctx: Context): Boolean {
62 | if (checkPermission(ctx)) {
63 | val file = File(SDCARD_PATH, path)
64 | if (!file.exists()) {
65 | throw FileNotFoundException(file.absolutePath)
66 | } else {
67 | return file.delete()
68 | }
69 | }
70 | return false
71 | }
72 |
73 | fun writeFile(path: String, content: String, ctx: Context) {
74 | if (checkPermission(ctx)) {
75 | val file = File(SDCARD_PATH, path)
76 | if (!file.exists()) {
77 | try {
78 | file.createNewFile()
79 | } catch (e: IOException) {
80 | e.printStackTrace()
81 | }
82 | }
83 | var fileOutputStream: FileOutputStream? = null
84 | try {
85 | fileOutputStream = FileOutputStream(file)
86 | fileOutputStream.write(content.toByteArray())
87 | } catch (e: java.lang.Exception) {
88 | e.printStackTrace()
89 | } finally {
90 | try {
91 | fileOutputStream?.close()
92 | } catch (e: IOException) {
93 | e.printStackTrace()
94 | }
95 | }
96 | }
97 | }
98 |
99 | fun readFile(path: String, ctx: Context, suffix: String = ""): String {
100 | val result = StringBuilder()
101 | if (checkPermission(ctx)) {
102 | var inputStream: InputStream? = null
103 | var reader: Reader? = null
104 | var bufferedReader: BufferedReader? = null
105 | try {
106 | val file = File(SDCARD_PATH, path)
107 | if (!file.exists()) {
108 | throw FileNotFoundException(file.absolutePath)
109 | }
110 | inputStream = FileInputStream(file)
111 | reader = InputStreamReader(inputStream)
112 | bufferedReader = BufferedReader(reader)
113 | var temp: String?
114 | while (bufferedReader.readLine().also { temp = it } != null) {
115 | result.append(temp).append(suffix)
116 | }
117 | } catch (e: Exception) {
118 | throw e
119 | } finally {
120 | try {
121 | bufferedReader?.close()
122 | } catch (e: IOException) {
123 | e.printStackTrace()
124 | }
125 | try {
126 | reader?.close()
127 | } catch (e: IOException) {
128 | e.printStackTrace()
129 | }
130 | try {
131 | inputStream?.close()
132 | } catch (e: IOException) {
133 | e.printStackTrace()
134 | }
135 | }
136 | }
137 | return result.toString()
138 | }
139 |
140 | fun checkPermission(ctx: Context): Boolean {
141 | //检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
142 | if (ActivityCompat.checkSelfPermission(
143 | ctx,
144 | Manifest.permission.WRITE_EXTERNAL_STORAGE
145 | ) == PackageManager.PERMISSION_DENIED
146 | ) {
147 | ActivityCompat.requestPermissions(ctx as Activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE)
148 | Utils.showToast(ctx, ctx.getString(R.string.permission_prompt))
149 | Log.e(
150 | "DozeManager", "The external storage read and write permissions are failed obtained!" +
151 | "${
152 | ActivityCompat.checkSelfPermission(
153 | ctx,
154 | Manifest.permission.WRITE_EXTERNAL_STORAGE
155 | ) == PackageManager.PERMISSION_GRANTED
156 | }"
157 | )
158 | return ActivityCompat.checkSelfPermission(
159 | ctx,
160 | Manifest.permission.WRITE_EXTERNAL_STORAGE
161 | ) == PackageManager.PERMISSION_GRANTED
162 | } else {
163 | Log.d("DozeManager", "The external storage read and write permissions are successfully obtained!")
164 | }
165 | return true
166 | }
167 |
168 | private fun restartApp(ctx: Context) {
169 | val intent = Intent(ctx, MainActivity::class.java)
170 | intent.putExtra("PackageName", ctx.packageName)
171 | intent.putExtra("Delayed", 1000)
172 | ctx.startService(intent)
173 | Log.e("DozeManager", "Restart")
174 | Process.killProcess(Process.myPid())
175 |
176 | }
177 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig
24 |
25 |
26 | import android.content.Intent
27 | import android.os.Bundle
28 | import android.os.Handler
29 | import android.text.method.LinkMovementMethod
30 | import android.view.LayoutInflater
31 | import android.widget.ImageView
32 | import android.widget.TextView
33 | import androidx.appcompat.app.AlertDialog
34 | import androidx.appcompat.app.AppCompatActivity
35 | import androidx.core.content.ContextCompat
36 | import androidx.core.text.HtmlCompat
37 | import com.bumptech.glide.Glide
38 | import com.github.hwwwwwlemon.dozeconfig.activity.ApplicationsListActivity
39 | import com.github.hwwwwwlemon.dozeconfig.activity.DozeRunLogActivity
40 | import com.github.hwwwwwlemon.dozeconfig.activity.SettingsActivity
41 | import com.github.hwwwwwlemon.dozeconfig.databinding.ActivityMainBinding
42 | import com.github.hwwwwwlemon.dozeconfig.databinding.DialogAboutBinding
43 | import com.github.hwwwwwlemon.dozeconfig.utils.DozeFileUtil
44 | import com.github.hwwwwwlemon.dozeconfig.utils.MyPreferences
45 | import com.github.hwwwwwlemon.dozeconfig.utils.StatusBarUtil
46 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
47 | import com.google.android.material.card.MaterialCardView
48 |
49 |
50 | class MainActivity : AppCompatActivity() {
51 | private lateinit var binding: ActivityMainBinding
52 | private lateinit var statusSummary: TextView
53 | private lateinit var statusTitle: TextView
54 | private lateinit var statusCard: MaterialCardView
55 | private lateinit var statusIcon: ImageView
56 | private var preferences: MyPreferences? = null
57 | private var runDozeWhitelistOpt = false
58 | private var firstPressedTime: Long = 10000
59 | private var handlerFlag = true
60 | private var status = 0
61 | private val counts = 5 // 点击次数
62 | private var count = 0
63 | private var isRun = false
64 | private var mHits = LongArray(counts)
65 |
66 |
67 | override fun onCreate(savedInstanceState: Bundle?) {
68 | super.onCreate(savedInstanceState)
69 | StatusBarUtil.immersive(this)
70 | preferences = MyPreferences(this)
71 | if (!Utils.isDarkMode(this)) {
72 | StatusBarUtil.darkMode(this);
73 | }
74 | binding = ActivityMainBinding.inflate(layoutInflater)
75 | setContentView(binding.root)
76 |
77 |
78 | //设置Title logo
79 | Glide.with(binding.dozeIcon).load(R.mipmap.ic_launcher_foreground).into(binding.dozeIcon)
80 | //应用列表
81 | binding.status.setOnClickListener {
82 |
83 | when (status) {
84 | 0 -> {
85 |
86 | continuousClick {
87 | if (runDozeWhitelistOpt) {
88 | Utils.refreshDozeWhitelist(this)
89 | } else {
90 | Utils.showToast(this, "\uD83E\uDD73")
91 | }
92 | }
93 |
94 | }
95 | 1 -> {
96 | Utils.showToast(this, "\uD83E\uDD7A")
97 | showDozeConfigurationFile()
98 | }
99 | 2 -> Utils.showToast(this, "\uD83D\uDE29")
100 | else -> Utils.showToast(this, "\uD83E\uDD76")
101 | }
102 |
103 |
104 | }
105 |
106 | binding.applicationsList.setOnClickListener {
107 | startActivity(
108 | Intent(
109 | this,
110 | ApplicationsListActivity::class.java
111 | )
112 | )
113 | }
114 | //Log
115 | binding.dozeRunLog.setOnClickListener {
116 | startActivity(
117 | Intent(
118 | this,
119 | DozeRunLogActivity::class.java
120 | )
121 | )
122 | }
123 | binding.settings.setOnClickListener {
124 | startActivity(
125 | Intent(
126 | this,
127 | SettingsActivity::class.java
128 | )
129 | )
130 | }
131 | //about
132 | binding.about.setOnClickListener {
133 | val alertDialogBuilder = AlertDialog.Builder(this)
134 | val dialogBinding = DialogAboutBinding.inflate(LayoutInflater.from(this), null, false)
135 | alertDialogBuilder.setView(dialogBinding.root)
136 | dialogBinding.aboutCard.background = ContextCompat.getDrawable(this, R.drawable.gradient_color)
137 | dialogBinding.github.movementMethod = LinkMovementMethod.getInstance();
138 | dialogBinding.github.text =
139 | HtmlCompat.fromHtml(
140 | getString(R.string.github) + "Issues",
141 | HtmlCompat.FROM_HTML_MODE_LEGACY
142 | )
143 |
144 | dialogBinding.author.movementMethod = LinkMovementMethod.getInstance();
145 | dialogBinding.author.text =
146 | HtmlCompat.fromHtml(
147 | getString(R.string.author) + "@Hwwwww",
148 | HtmlCompat.FROM_HTML_MODE_LEGACY
149 | )
150 | dialogBinding.appVersion.text = "version : " + getString(R.string.version)
151 | dialogBinding.description.text = getString(R.string.about_description)
152 | alertDialogBuilder.show()
153 | }
154 |
155 |
156 | }
157 |
158 | private fun continuousClick(func: () -> Any) {
159 | if (!runDozeWhitelistOpt || status != 0) {
160 | func()
161 | return
162 | }
163 |
164 | System.arraycopy(mHits, 1, mHits, 0, mHits.size - 1)
165 | mHits[mHits.size - 1] = System.currentTimeMillis()
166 | if (!isRun) {
167 | if (handlerFlag) {
168 | handlerFlag = false
169 | Handler().postDelayed({
170 | runOnUiThread {
171 | handlerFlag = true
172 | count = 0
173 | mHits = LongArray(counts)
174 | }
175 | }, 1500)
176 | }
177 |
178 | count++
179 | Utils.showToast(this, "再点击 ${counts - count} 次优化白名单 ", 600)
180 | }
181 | if (!isRun and (mHits[0] >= System.currentTimeMillis() - 3000) and (count == 5)) {
182 | mHits = LongArray(counts) //重新初始化数组
183 | isRun = true
184 | count = 0
185 | func()
186 | Handler().postDelayed({ runOnUiThread { isRun = false } }, 5000)
187 | }
188 |
189 | }
190 |
191 | override fun onResume() {
192 | runDozeWhitelistOpt = preferences?.get("run_doze_whitelist", false) as Boolean
193 | if (DozeManager.checkPermission(this)) {
194 | init()
195 | } else {
196 | finish()
197 | }
198 | super.onResume()
199 | }
200 |
201 | private fun init() {
202 | statusSummary = findViewById(R.id.status_summary)
203 | statusTitle = findViewById(R.id.status_title)
204 | statusCard = findViewById(R.id.status)
205 | statusIcon = findViewById(R.id.status_icon)
206 | var successColor = getColor(R.color.success)
207 | var errorColor = getColor(R.color.error)
208 | if (Utils.isDarkMode(this)) {
209 | successColor = getColor(R.color.success_dark)
210 | errorColor = getColor(R.color.error_dark)
211 | }
212 |
213 |
214 |
215 | when {
216 | DozeManager.checkDozeFile(this) and DozeFileUtil.loadDozeFile(this) -> {
217 | statusCard.setCardBackgroundColor(successColor)
218 | statusIcon.setImageResource(R.drawable.ic_success_fill)
219 | statusSummary.text = getString(R.string.found_whitelist_file_prompt)
220 | statusTitle.text = getString(R.string.found_whitelist_file)
221 | status = 0
222 | }
223 | DozeManager.checkDozeFile(this) and !DozeFileUtil.loadDozeFile(this) -> {
224 | statusCard.setCardBackgroundColor(errorColor)
225 | statusIcon.setImageResource(R.drawable.ic_question_fill)
226 | statusSummary.text = getString(R.string.whitelist_file_error)
227 | statusTitle.text = getString(R.string.found_whitelist_file)
228 | status = 1
229 | }
230 | else -> {
231 | statusCard.setCardBackgroundColor(errorColor)
232 | statusIcon.setImageResource(R.drawable.ic_error_fill)
233 | statusSummary.text = getString(R.string.not_found_whitelist_file_prompt)
234 | statusTitle.text = getString(R.string.not_found_whitelist_file)
235 | status = 2
236 | }
237 | }
238 |
239 | }
240 |
241 | private fun showDozeConfigurationFile() {
242 |
243 | val sb = StringBuilder("Error List:\n")
244 | DozeFileUtil.errorList.forEach {
245 | sb.append(it).append("\n")
246 | }
247 | sb.append("也许您没安装这个应用或者包名有错误。\n应用列表更新一次即可。")
248 | val dozeWhitelist = sb.toString()
249 | val builder = AlertDialog.Builder(this)
250 | builder.setTitle(R.string.prompt)
251 | builder.setMessage(dozeWhitelist)
252 | builder.create()
253 | builder.show()
254 |
255 | }
256 |
257 | override fun onBackPressed() {
258 | if (System.currentTimeMillis() - firstPressedTime < 2000) {
259 | super.onBackPressed(); //不要调用父类的方法
260 | } else {
261 | Utils.showToast(this, "再按一次退出")
262 | firstPressedTime = System.currentTimeMillis()
263 | }
264 |
265 | }
266 | }
267 |
268 |
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/activity/ApplicationsListActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.activity
24 |
25 |
26 | import android.content.Context
27 | import android.graphics.Rect
28 | import android.os.Bundle
29 | import android.util.AttributeSet
30 | import android.view.Menu
31 | import android.view.MenuItem
32 | import android.view.View
33 | import androidx.appcompat.widget.SearchView
34 | import androidx.recyclerview.widget.LinearLayoutManager
35 | import androidx.recyclerview.widget.RecyclerView
36 | import com.bumptech.glide.Glide
37 | import com.github.hwwwwwlemon.dozeconfig.DozeManager
38 | import com.github.hwwwwwlemon.dozeconfig.R
39 | import com.github.hwwwwwlemon.dozeconfig.activity.base.BaseActivity
40 | import com.github.hwwwwwlemon.dozeconfig.adapter.ApplicationAdapter
41 | import com.github.hwwwwwlemon.dozeconfig.databinding.ActivityApplicationListBinding
42 | import com.github.hwwwwwlemon.dozeconfig.utils.DozeFileUtil
43 | import com.github.hwwwwwlemon.dozeconfig.utils.MyPreferences
44 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
45 | import com.scwang.smart.refresh.header.MaterialHeader
46 | import com.scwang.smart.refresh.layout.api.RefreshLayout
47 | import kotlinx.coroutines.CoroutineScope
48 | import kotlinx.coroutines.Dispatchers
49 | import kotlinx.coroutines.launch
50 | import kotlinx.coroutines.withContext
51 | import me.zhanghai.android.fastscroll.FastScroller
52 | import me.zhanghai.android.fastscroll.FastScrollerBuilder
53 |
54 |
55 | class ApplicationsListActivity : BaseActivity() {
56 | private var refreshLayout: RefreshLayout? = null
57 | private var rv: RecyclerView? = null
58 | private var fastScroll: FastScroller? = null
59 | private var adapter: ApplicationAdapter? = null
60 | private var enableShowSystemApps: Int = 1
61 | private var self = this
62 | private val controlScope = CoroutineScope(Dispatchers.Default)
63 | private var searchView: SearchView? = null
64 | private lateinit var binding: ActivityApplicationListBinding
65 | private var preferences: MyPreferences? = null
66 |
67 | override fun onCreate(savedInstanceState: Bundle?) {
68 | super.onCreate(savedInstanceState)
69 | binding = ActivityApplicationListBinding.inflate(layoutInflater)
70 | preferences = MyPreferences(this)
71 | setContentView(binding.root)
72 | initStatusBar()
73 |
74 | }
75 |
76 | override fun onResume() {
77 | if (DozeFileUtil.checkAppList.size == 0) {
78 | if (DozeManager.checkDozeFile(this)) {
79 | DozeFileUtil.loadDozeFile(this)
80 | }
81 | }
82 |
83 | initLayout()
84 | super.onResume()
85 | }
86 |
87 | override fun initStatusBar() {
88 | super.initStatusBar()
89 | enableHomeButton(true)
90 | supportActionBar?.title = getString(R.string.applications)
91 | }
92 |
93 | private fun initLayout() {
94 | refreshLayout = findViewById(R.id.refreshLayout) as RefreshLayout
95 | refreshLayout?.setRefreshHeader(MaterialHeader(this))
96 | refreshLayout?.apply {
97 | setOnRefreshListener { loadApps(true) }
98 | autoRefresh()
99 | }
100 |
101 | rv = findViewById(R.id.my_recycler_view)
102 | val llm = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
103 | adapter = ApplicationAdapter(self, enableShowSystemApps, rv!!)
104 | adapter?.setHasStableIds(true);
105 | adapter?.refresh(true)
106 | rv?.addItemDecoration(SpaceItemDecoration(10));
107 | fastScroll = FastScrollerBuilder(rv!!).useMd2Style().build()
108 | if (preferences?.get("lazy_load_icon", false) as Boolean) {
109 | rv?.addOnScrollListener(AutoLoadRecyclerView(this).init())
110 | }
111 | rv?.itemAnimator?.changeDuration = 1500;
112 | rv?.layoutManager = llm
113 | rv?.adapter = adapter
114 | }
115 |
116 | private fun loadApps(force: Boolean = false) {
117 | try {
118 | adapter?.filterType = enableShowSystemApps
119 | adapter?.refresh(force)
120 | val close = if (adapter?.itemCount!! > 0) 100 else 2000
121 | refreshLayout?.finishRefresh(close)
122 |
123 | } catch (e: Exception) {
124 | e.printStackTrace()
125 | }
126 | }
127 |
128 | private fun enableHomeButton(status: Boolean) {
129 | supportActionBar?.setDisplayHomeAsUpEnabled(status)
130 | supportActionBar?.setHomeButtonEnabled(status)
131 | }
132 |
133 | override fun onCreateOptionsMenu(menu: Menu?): Boolean {
134 | menuInflater.inflate(R.menu.menu_show_app_list, menu)
135 | //Toolbar的搜索框
136 | val searchItem = menu?.findItem(R.id.toolbar_search)
137 | searchView = searchItem?.actionView as SearchView
138 |
139 | searchView?.queryHint = getString(R.string.search_hint)
140 | searchView?.setOnCloseListener {
141 | adapter?.searchStr = ""
142 | enableHomeButton(true)
143 | false
144 | }
145 | searchView?.setOnSearchClickListener {
146 | enableHomeButton(false)
147 | }
148 | searchView?.setOnQueryTextListener(adapter?.getSearchListener())
149 | return true
150 | }
151 |
152 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
153 | if (rv?.scrollState == 0) {
154 | return when (item.itemId) {
155 | R.id.toolbar_show_system_apps -> {
156 | item.isChecked = !item.isChecked
157 | enableShowSystemApps = if (item.isChecked) 2 else 1
158 | loadApps()
159 | true
160 | }
161 | R.id.toolbar_save -> {
162 | if (DozeFileUtil.saveDozeFile(this)) {
163 | Utils.showToast(this, getString(R.string.save_success))
164 | } else {
165 | Utils.showToast(this, getString(R.string.save_failed))
166 | }
167 | finish()
168 | true
169 | }
170 | android.R.id.home -> {
171 | finish()
172 | true
173 | }
174 | else -> super.onOptionsItemSelected(item)
175 | }
176 | } else {
177 | Utils.showToast(this, getString(R.string.in_loop))
178 | return false
179 | }
180 |
181 | }
182 |
183 | private fun release() {
184 | try {
185 | if (isFinishing) {
186 | Glide.with(self.applicationContext).pauseAllRequests()
187 | controlScope.launch {
188 | withContext(Dispatchers.Main) {
189 | Glide.get(self.applicationContext).clearMemory();
190 | }
191 | adapter?.clear()
192 | adapter = null
193 | rv = null
194 | }
195 | }
196 | } catch (e: Exception) {
197 | e.printStackTrace()
198 | }
199 |
200 | }
201 |
202 | override fun onBackPressed() {
203 | if (!searchView!!.isIconified) {
204 | searchView?.isIconified = true;
205 | } else {
206 | super.onBackPressed()
207 | }
208 |
209 | }
210 |
211 | override fun onStop() {
212 | release()
213 | super.onStop()
214 | }
215 |
216 |
217 | inner class AutoLoadRecyclerView(ctx: Context, attrs: AttributeSet?, defStyle: Int) :
218 | RecyclerView(ctx, attrs, defStyle) {
219 | constructor(ctx: Context) : this(ctx, null) {}
220 | constructor(ctx: Context, attrs: AttributeSet?) : this(ctx, attrs, 0) {}
221 |
222 | fun init(): ImageAutoLoadScrollListener {
223 | return ImageAutoLoadScrollListener()
224 | }
225 |
226 | //监听滚动来对图片加载进行判断处理
227 | inner class ImageAutoLoadScrollListener : OnScrollListener() {
228 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
229 | super.onScrolled(recyclerView, dx, dy)
230 | }
231 |
232 | override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
233 | super.onScrollStateChanged(recyclerView, newState)
234 | when (newState) {
235 | SCROLL_STATE_IDLE -> //当屏幕停止滚动,加载图片
236 | try {
237 | if (context != null) Glide.with(context).resumeRequests()
238 | } catch (e: Exception) {
239 | e.printStackTrace()
240 | }
241 | SCROLL_STATE_DRAGGING -> //当屏幕滚动且用户使用的触碰或手指还在屏幕上,停止加载图片
242 | try {
243 | if (context != null) Glide.with(context).pauseRequests()
244 | } catch (e: Exception) {
245 | e.printStackTrace()
246 | }
247 | SCROLL_STATE_SETTLING -> //由于用户的操作,屏幕产生惯性滑动,停止加载图片
248 | try {
249 |
250 | if (context != null) {
251 | Glide.with(context).pauseRequests()
252 | }
253 | } catch (e: Exception) {
254 | e.printStackTrace()
255 | }
256 | }
257 | }
258 | }
259 | }
260 |
261 | inner class SpaceItemDecoration(var mSpace: Int) : RecyclerView.ItemDecoration() {
262 | /**
263 | * Retrieve any offsets for the given item. Each field of `outRect` specifies
264 | * the number of pixels that the item view should be inset by, similar to padding or margin.
265 | * The default implementation sets the bounds of outRect to 0 and returns.
266 |
267 | * If this ItemDecoration does not affect the positioning of item views, it should set
268 | * all four fields of `outRect` (left, top, right, bottom) to zero
269 | * before returning.
270 | *
271 |
272 | * If you need to access Adapter for additional data, you can call
273 | * [RecyclerView.getChildAdapterPosition] to get the adapter position of the
274 | * View.
275 | *
276 | * @param outRect Rect to receive the output.
277 | * @param view The child view to decorate
278 | * @param parent RecyclerView this ItemDecoration is decorating
279 | * @param state The current state of RecyclerView.
280 | */
281 | override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
282 | super.getItemOffsets(outRect, view, parent, state)
283 | // outRect.left = mSpace
284 | // outRect.right = mSpace
285 | outRect.bottom = mSpace
286 | if (parent.getChildAdapterPosition(view) == 0) {
287 | outRect.top = mSpace
288 | }
289 | }
290 | }
291 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/github/hwwwwwlemon/dozeconfig/adapter/ApplicationAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License (MIT)
3 | *
4 | * Copyright © 2021 Hwwwww
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
7 | * associated documentation files (the “Software”), to deal in the Software without restriction,
8 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
10 | * subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all copies or substantial
13 | * portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
16 | * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 | *
21 | *
22 | */
23 | package com.github.hwwwwwlemon.dozeconfig.adapter
24 |
25 | import android.app.Activity
26 | import android.content.pm.ApplicationInfo
27 | import android.content.pm.PackageManager
28 | import android.graphics.drawable.Drawable
29 | import android.os.Handler
30 | import android.util.Log
31 | import android.view.LayoutInflater
32 | import android.view.View
33 | import android.view.ViewGroup
34 | import android.widget.Filter
35 | import android.widget.ImageView
36 | import android.widget.Switch
37 | import android.widget.TextView
38 | import androidx.appcompat.widget.SearchView
39 | import androidx.recyclerview.widget.RecyclerView
40 | import com.bumptech.glide.Glide
41 | import com.bumptech.glide.request.target.CustomTarget
42 | import com.bumptech.glide.request.transition.Transition
43 | import com.github.hwwwwwlemon.dozeconfig.R
44 | import com.github.hwwwwwlemon.dozeconfig.utils.DozeFileUtil
45 | import com.github.hwwwwwlemon.dozeconfig.utils.MyPreferences
46 | import com.github.hwwwwwlemon.dozeconfig.utils.Utils
47 | import kotlinx.coroutines.*
48 |
49 |
50 | class ApplicationAdapter() : RecyclerView.Adapter() {
51 |
52 | private val apps: MutableList = mutableListOf()
53 | private var showApps: MutableList = mutableListOf()
54 | private var searchApps: MutableList = mutableListOf()
55 | private var checkApps: MutableList = mutableListOf()
56 | private lateinit var rv: RecyclerView
57 | private lateinit var pm: PackageManager
58 | private lateinit var activity: Activity
59 | var filterType: Int = 1
60 | var searchStr: String = ""
61 | private var preferences: MyPreferences? = null
62 | private var isRefreshing = false
63 | private val viewModelJob = SupervisorJob()
64 | private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
65 | private val controlScope = CoroutineScope(Dispatchers.Default)
66 | private val mHandler = Handler()
67 |
68 | constructor(
69 | activity: Activity,
70 | filterType: Int,
71 | rv: RecyclerView
72 | ) : this() {
73 | preferences = MyPreferences(activity)
74 | this.rv = rv
75 | this.pm = activity.packageManager
76 | this.activity = activity
77 | this.filterType = filterType
78 | }
79 |
80 | inner class AppViewHolder constructor(itemView: View) :
81 | RecyclerView.ViewHolder(itemView) {
82 | var appName: TextView = itemView.findViewById(R.id.app_name) as TextView
83 | var packageName: TextView = itemView.findViewById(R.id.package_name) as TextView
84 | var appIcon: ImageView = itemView.findViewById(R.id.app_icon) as ImageView
85 | var switchIcon: Switch = itemView.findViewById(R.id.check_white_list_app) as Switch
86 | }
87 |
88 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder {
89 | val v: View = LayoutInflater.from(parent.context).inflate(R.layout.application_unit_layout, parent, false)
90 | return AppViewHolder(v)
91 | }
92 |
93 | override fun onBindViewHolder(holder: AppViewHolder, position: Int, payloads: MutableList) {
94 | if (payloads.isEmpty()) {
95 | bind(holder, position)
96 | }
97 |
98 | }
99 |
100 | override fun onBindViewHolder(holder: AppViewHolder, position: Int) {
101 | bind(holder, position)
102 | }
103 |
104 | private fun bind(holder: AppViewHolder, position: Int) {
105 | try {
106 | holder.appName.text = showApps[position].appName
107 | holder.packageName.text = showApps[position].packageName
108 | Glide.with(holder.appIcon)
109 | .load(showApps[position].applicationInfo.loadIcon(pm))
110 | .into(object : CustomTarget() {
111 | override fun onResourceReady(resource: Drawable, transition: Transition?) {
112 | holder.appIcon.setImageDrawable(resource)
113 | }
114 |
115 | override fun onLoadCleared(placeholder: Drawable?) {}
116 | override fun onLoadFailed(errorDrawable: Drawable?) {
117 | holder.appIcon.setImageDrawable(pm.defaultActivityIcon)
118 | }
119 | })
120 | holder.switchIcon.setOnCheckedChangeListener(null)
121 | holder.switchIcon.isChecked = DozeFileUtil.checkAppList.contains(showApps[position])
122 | holder.itemView.setOnClickListener {
123 | holder.switchIcon.toggle()
124 | }
125 | holder.switchIcon.setOnCheckedChangeListener { _, isChecked ->
126 | if (rv.scrollState == 0) {
127 | onCheckedChange(isChecked, showApps[position])
128 | }
129 | }
130 | } catch (e: Exception) {
131 | e.printStackTrace()
132 | }
133 | }
134 |
135 | private fun onCheckedChange(isChecked: Boolean, app: Apps) {
136 | if (isChecked) {
137 | DozeFileUtil.checkAppList.add(app)
138 | searchApps.remove(app)
139 | } else {
140 | DozeFileUtil.checkAppList.remove(app)
141 | searchApps.add(app)
142 | }
143 | mHandler.post {
144 | controlScope.launch {
145 | if (preferences?.get("auto_save", false) as Boolean) {
146 | DozeFileUtil.saveDozeFile(activity)
147 | withContext(Dispatchers.Main) {
148 | Utils.showToast(activity, activity.getString(R.string.auto_save), 1000)
149 | }
150 |
151 | }
152 | }
153 |
154 | }
155 |
156 |
157 | }
158 |
159 | override fun onViewRecycled(holder: AppViewHolder) {
160 | /* holder.appIcon.setImageDrawable(null)
161 | Glide.with(holder.appIcon).clear(holder.appIcon)*/
162 | super.onViewRecycled(holder)
163 | }
164 |
165 | override fun getItemCount(): Int {
166 | return showApps.size
167 |
168 | }
169 |
170 | private fun getFilter(): AppFilter {
171 | return AppFilter()
172 | }
173 |
174 | @Synchronized
175 | private fun setRefreshStatus(status: Boolean) {
176 | this.isRefreshing = status
177 | }
178 |
179 | @Synchronized
180 | private fun getRefreshStatus(): Boolean {
181 | return isRefreshing
182 | }
183 |
184 |
185 | override fun getItemId(position: Int): Long {
186 | val info = showApps[position].applicationInfo;
187 | return (info.packageName + "!" + info.uid / 100000).hashCode().toLong()
188 | }
189 |
190 | fun refresh(force: Boolean) {
191 | synchronized(this) {
192 | if (getRefreshStatus()) {
193 | Log.e("isRefreshing", "Cancel Refreshing")
194 | return;
195 | }
196 | setRefreshStatus(true)
197 | }
198 |
199 | try {
200 | controlScope.launch {
201 | async {
202 | checkApps.clear()
203 | checkApps.addAll(DozeFileUtil.checkAppList)
204 | sortList(checkApps)
205 | }.join()
206 |
207 | if (force) {
208 | val loadAppsJob = async { loadApps() }
209 | loadAppsJob.join()
210 | val searchAppsJob = async { sortList(searchApps) }
211 | searchAppsJob.join()
212 |
213 | joinAll(loadAppsJob, searchAppsJob)
214 | }
215 | val ready = async {
216 | withContext(Dispatchers.Main) {
217 | synchronized(this) {
218 | getFilter().filter(searchStr);
219 | setRefreshStatus(false)
220 | }
221 | }
222 | }
223 | ready.join()
224 | }
225 | } catch (e: Exception) {
226 | e.printStackTrace()
227 | }
228 | }
229 |
230 | private suspend fun loadApps() = withContext(Dispatchers.Default) {
231 | try {
232 | apps.clear()
233 | searchApps.clear()
234 | var flag: Int?
235 | val appList: MutableList = Utils.getAppList(activity.applicationContext)
236 | for (i in appList) {
237 | flag = if ((i.flags and ApplicationInfo.FLAG_SYSTEM) == 0) 1 else 2
238 | val excludeApp = !(i.packageName.contains("com.qti")
239 | || i.packageName.contains("com.android.theme")
240 | || i.packageName.contains("com.qualcomm")
241 | || i.packageName.contains("overlay")
242 | || i.packageName.contains("android.internal")
243 | )
244 |
245 | if (excludeApp) {
246 | val app = Apps(i, i.packageName, pm.getApplicationLabel(i).toString(), flag)
247 | if (checkApps.contains(app)) {
248 | continue
249 | }
250 | apps.add(app)
251 | }
252 | }
253 | searchApps.addAll(apps)
254 | } catch (e: Exception) {
255 | e.printStackTrace()
256 | false
257 | }
258 | }
259 |
260 |
261 | private suspend fun sortList(list: MutableList) = withContext(Dispatchers.Default) {
262 | try {
263 | list.sortBy {
264 | it.appName
265 | }
266 | } catch (e: Exception) {
267 | e.printStackTrace()
268 | }
269 |
270 | }
271 |
272 |
273 | fun getSearchListener(): SearchView.OnQueryTextListener {
274 | return object : SearchView.OnQueryTextListener {
275 | override fun onQueryTextSubmit(query: String): Boolean {
276 | searchStr = query
277 | refresh(false)
278 | return true
279 | }
280 |
281 | override fun onQueryTextChange(newText: String): Boolean {
282 | searchStr = newText
283 | refresh(false)
284 | return true
285 | }
286 | }
287 | }
288 |
289 |
290 | fun clear() {
291 | apps.clear()
292 | showApps.clear()
293 | checkApps.clear()
294 | searchApps.clear()
295 | uiScope.cancel()
296 | controlScope.cancel()
297 | viewModelJob.cancel()
298 | }
299 |
300 | inner class AppFilter : Filter() {
301 | override fun performFiltering(constraint: CharSequence): FilterResults {
302 | val filterResults = FilterResults()
303 | val filtered: MutableList = mutableListOf()
304 | val filteredCheck: MutableList = mutableListOf()
305 |
306 | if (constraint.toString().isEmpty()) {
307 | filtered.addAll(checkApps)
308 | filtered.addAll(
309 | if (filterType == 1) {
310 | searchApps.filter { (it.flag == 1) or checkApps.contains(it) }
311 | } else {
312 | searchApps.filter { !checkApps.contains(it) }
313 | }
314 | )
315 |
316 | } else {
317 | val showSystemApps = filterType == 2
318 | for (i in searchApps) {
319 | if ((i.packageName.contains(constraint.toString(), true) ||
320 | i.appName.contains(constraint.toString(), true))
321 | ) {
322 | if (((i.flag == 2) and !showSystemApps) or checkApps.contains(i)) {
323 | continue
324 | }
325 | filtered.add(i)
326 | }
327 |
328 | }
329 | for (i in checkApps) {
330 | if ((i.packageName.contains(constraint.toString(), true) ||
331 | i.appName.contains(constraint.toString(), true))
332 | ) {
333 | filteredCheck.add(i)
334 | }
335 |
336 | }
337 | }
338 | filtered.addAll(0, filteredCheck)
339 | filterResults.values = filtered
340 | filterResults.count = filtered.size
341 | return filterResults
342 | }
343 |
344 | override fun publishResults(constraint: CharSequence?, results: FilterResults) {
345 | showApps.clear()
346 | showApps.addAll(results.values as Collection)
347 | notifyDataSetChanged()
348 | }
349 | }
350 |
351 |
352 | class Apps(
353 | var applicationInfo: ApplicationInfo,
354 | var packageName: String,
355 | var appName: String,
356 | var flag: Int,
357 | ) {
358 | override fun equals(other: Any?): Boolean {
359 | if (other !is Apps) {
360 | return false;
361 | }
362 | return this.appName == other.appName && this.packageName == other.packageName
363 | }
364 |
365 | override fun hashCode(): Int {
366 | var result = 31 * packageName.hashCode()
367 | result = 31 * result + appName.hashCode()
368 | return result
369 | }
370 | }
371 |
372 | }
--------------------------------------------------------------------------------