├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── themes.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── ic_launcher-playstore.png
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── cc
│ │ │ └── aoeiuv020
│ │ │ └── iamnotdisabled
│ │ │ └── MainActivity.kt
│ ├── test
│ │ └── java
│ │ │ └── cc
│ │ │ └── aoeiuv020
│ │ │ └── iamnotdisabled
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── cc
│ │ └── aoeiuv020
│ │ └── iamnotdisabled
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── build.gradle
├── hook
├── .gitignore
├── src
│ ├── main
│ │ ├── assets
│ │ │ └── xposed_init
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ ├── strings-notran.xml
│ │ │ │ └── colors.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ └── drawable
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── ic_launcher-playstore.png
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── cc
│ │ │ └── aoeiuv020
│ │ │ └── iamnotdisabled
│ │ │ └── hook
│ │ │ └── MainHook.java
│ ├── test
│ │ └── java
│ │ │ └── cc
│ │ │ └── aoeiuv020
│ │ │ └── iamnotdisabled
│ │ │ └── hook
│ │ │ └── ExampleUnitTest.kt
│ └── androidTest
│ │ └── java
│ │ └── cc
│ │ └── aoeiuv020
│ │ └── iamnotdisabled
│ │ └── hook
│ │ └── ExampleInstrumentedTest.kt
├── proguard-rules.pro
└── build.gradle
├── readme
└── chrome+litiaotiao.jpg
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
└── signing.gradle
├── latest-version.sh
├── latest-changelog.sh
├── template-update.md
├── settings.gradle
├── ChangeLog.txt
├── LICENSE
├── gradle.properties
├── README.md
├── .gitignore
├── gradlew.bat
├── signing.txt
├── gradlew
└── .github
└── workflows
└── main.yml
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/hook/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/hook/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | cc.aoeiuv020.iamnotdisabled.hook.MainHook
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 我残?
3 |
--------------------------------------------------------------------------------
/hook/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | 非残!
3 |
--------------------------------------------------------------------------------
/readme/chrome+litiaotiao.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/readme/chrome+litiaotiao.jpg
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/latest-version.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | cur="$(dirname $0)"
3 | cd $cur
4 | cat ChangeLog.txt |head -2 |tail -1 |sed 's/\(.*\):/\1/'
5 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/hook/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/hook/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AoEiuV020/IAmNotDisabled/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/AoEiuV020/IAmNotDisabled/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/AoEiuV020/IAmNotDisabled/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/AoEiuV020/IAmNotDisabled/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/AoEiuV020/IAmNotDisabled/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3DDC84
4 |
--------------------------------------------------------------------------------
/hook/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #DC3D3D
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Jan 06 01:57:28 CST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/latest-changelog.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # 打印最新版本的更新日志,
3 | # 关键是以markdown的格式加粗第一行,
4 | # 可选参数一个,指定版本打印更新日志,
5 | set -e
6 | cd $(dirname $0)
7 | versionName=$1
8 | versionName=${versionName:=$(./latest-version.sh)}
9 | cat ./ChangeLog.txt |sed -n "/$versionName:/,\$p" |sed '/^$/,$d;1d' |sed '1s/[,,]$//;1s/^\(.*\)$/### \1\n/'
10 |
--------------------------------------------------------------------------------
/hook/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/hook/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/template-update.md:
--------------------------------------------------------------------------------
1 | *[${BUILD_NAME}]更新,${VERSION_PREFIX}${BUILD_VERSION}*
2 | [CI](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}) [反馈](https://github.com/${GITHUB_REPOSITORY}/issues)
3 |
4 | *下载地址:*
5 | [GITHUB](https://github.com/${GITHUB_REPOSITORY}/releases/tag/${BUILD_VERSION})
6 |
7 | *更新日志:*
8 | ${TG_CHANGELOG}
9 |
--------------------------------------------------------------------------------
/hook/src/main/res/values/strings-notran.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - cc.aoeiuv020.iamnotdisabled
5 | - com.android.chrome
6 | - com.google.android.inputmethod.latin
7 |
8 |
9 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | //noinspection JcenterRepositoryObsolete,GrDeprecatedAPIUsage
7 | jcenter() // Warning: this repository is going to shut down soon
8 | }
9 | }
10 | rootProject.name = "IAmNotDisabled"
11 | include ':app'
12 | include ':hook'
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/hook/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/app/src/test/java/cc/aoeiuv020/iamnotdisabled/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/hook/src/test/java/cc/aoeiuv020/iamnotdisabled/hook/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled.hook
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/ChangeLog.txt:
--------------------------------------------------------------------------------
1 | 更新日志:
2 | 6.6:
3 | 兼容性优化,适配新版LSPosed的堆栈变化,
4 |
5 | 6.5:
6 | 性能优化,减少一个无用循环,
7 |
8 | 6.4:
9 | 优化卡顿问题,
10 |
11 | 6.3:
12 | 修复chrome隐瞒无障碍同时使用读屏软件,
13 |
14 | 6.2:
15 | 隐瞒无障碍的应用正常使用读屏软件,
16 |
17 | 6.1:
18 | 扩大针对处理的范围,
19 |
20 | 6.0:
21 | 发布到xposed仓库,
22 |
23 | 5.0:
24 | 改显示的版本号,
25 |
26 | 4.0:
27 | 优化hook安装包体积,
28 | 直接删除兼容低版本用的图标,
29 | 相应的最低版本提升到26,
30 |
31 | 3.0:
32 | 改低最低版本要求到安卓5,
33 | 没测试,只是想留一个支持低版本的包,
34 |
35 | 2.0:
36 | 优化hook安装包体积,
37 | 放弃kotlin,改用java,
38 |
39 | 1.0:
40 | 配置签名,
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/androidTest/java/cc/aoeiuv020/iamnotdisabled/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("cc.aoeiuv020.iamnotdisabled", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/hook/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
--------------------------------------------------------------------------------
/hook/src/androidTest/java/cc/aoeiuv020/iamnotdisabled/hook/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled.hook
2 |
3 | import androidx.test.platform.app.InstrumentationRegistry
4 | import androidx.test.ext.junit.runners.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
22 | assertEquals("cc.aoeiuv020.iamnotdisabled.hook", appContext.packageName)
23 | }
24 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/hook/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
15 |
18 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 啊o额iu鱼
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/hook/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdk 32
7 |
8 | defaultConfig {
9 | applicationId "cc.aoeiuv020.iamnotdisabled.hook"
10 | minSdk 26
11 | targetSdk 32
12 | versionCode rootProject.ext.versionCode
13 | versionName rootProject.ext.versionName
14 |
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | compileOptions {
25 | sourceCompatibility JavaVersion.VERSION_1_8
26 | targetCompatibility JavaVersion.VERSION_1_8
27 | }
28 | }
29 |
30 | dependencies {
31 | compileOnly 'de.robv.android.xposed:api:82'
32 |
33 | //noinspection GradleDynamicVersion
34 | testImplementation 'junit:junit:4.+'
35 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
37 | }
38 |
39 | apply from: rootProject.file('gradle/signing.gradle')
40 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IAmNotDisabled
2 | 使用xposed hook假装自己没有使用无障碍服务,
3 | [](./ChangeLog.txt)
4 | [](https://github.com/AoEiuV020/IAmNotDisabled/actions/workflows/main.yml)
5 | [](https://github.com/AoEiuV020/IAmNotDisabled/releases)
6 |
7 | ## !!!本项目并非反反作弊用途,只针对善意的无障碍检测,不保证对反作弊检测有效!!!
8 |
9 | 起因:[https://www.v2ex.com/t/826317](https://www.v2ex.com/t/826317)
10 | 使用无障碍服务会被部分app特殊对待,
11 | 然而有可能使用了无障碍只是为了便利,并不希望被优待,
12 | 于是有了本项目,
13 | 针对chrome,假装自己没有使用无障碍服务,才可以使用新版的各种标签相关功能和动画,
14 |
15 | ### 项目包含两个应用模块
16 | * app 我残? 用于测试hook效果,打开时检测到无障碍服务就会提示,
17 | * hook 非残! xposed模块通过hook负责查询无障碍的系统服务伪装成没有启用无障碍服务,
18 |
19 | ### 模块使用需求
20 | * 安卓8以上,不为啥,只是觉得没必要支持旧版,
21 | * [Riru-LSPosed](https://github.com/LSPosed/LSPosed) 1.6.5以上,不为啥,只是因为我开发时在用的就是这个,
22 | * 理论上对任何目标应用都有效,
23 |
24 | ### 模块使用方法
25 | 1. 手机解锁,
26 | 1. 刷入Magisk,
27 | 1. 刷入Magisk模块Riru和Riri-LSPosed,
28 | 1. 安装“[非残!](https://github.com/AoEiuV020/IAmNotDisabled/releases)”,IAmNotDisabled-hook.apk,
29 | 1. 在LSPosed中激活非残并勾选需要隐瞒无障碍服务应用,比如chrome,
30 | 1. 重启目标应用生效,
31 |
32 | 下图,开启“李跳跳”的同时使用chrome的新版标签,
33 | 
34 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | }
5 |
6 | android {
7 | compileSdk 32
8 |
9 | defaultConfig {
10 | applicationId "cc.aoeiuv020.iamnotdisabled"
11 | minSdk 26
12 | targetSdk 32
13 | versionCode rootProject.ext.versionCode
14 | versionName rootProject.ext.versionName
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | kotlinOptions {
30 | jvmTarget = '1.8'
31 | }
32 | }
33 |
34 | dependencies {
35 |
36 | implementation 'androidx.core:core-ktx:1.7.0'
37 | implementation 'androidx.appcompat:appcompat:1.4.0'
38 | implementation 'com.google.android.material:material:1.4.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
40 | //noinspection GradleDynamicVersion
41 | testImplementation 'junit:junit:4.+'
42 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
43 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
44 | }
45 |
46 | apply from: rootProject.file('gradle/signing.gradle')
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/
42 |
43 | # Keystore files
44 | # Uncomment the following lines if you do not want to check your keystore files in.
45 | *.jks
46 | *.jks.txt
47 | #*.keystore
48 |
49 | # External native build folder generated in Android Studio 2.2 and later
50 | .externalNativeBuild
51 | .cxx/
52 |
53 | # Google Services (e.g. APIs or Firebase)
54 | google-services.json
55 |
56 | # Freeline
57 | freeline.py
58 | freeline/
59 | freeline_project_description.json
60 |
61 | # fastlane
62 | fastlane/report.xml
63 | fastlane/Preview.html
64 | fastlane/screenshots
65 | fastlane/test_output
66 | fastlane/readme.md
67 |
68 | # Version control
69 | vcs.xml
70 |
71 | # lint
72 | lint/intermediates/
73 | lint/generated/
74 | lint/outputs/
75 | lint/tmp/
76 | # lint/reports/
77 |
78 | ###
79 | /release
80 | /signing.properties
81 | /publish.properties
82 | class_files.txt
83 | .attach_pid*
84 | *-mapping.txt
85 | *.apk.idsig
86 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/hook/src/main/res/drawable/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/gradle/signing.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | android {
3 |
4 | // 签名信息从signing.properties中获取,
5 | // debug和release使用相同签名,以便用debug包覆盖release包从而调试,
6 | // 如果没有,就会使用默认debug签名,
7 | def signingFile = rootProject.file('signing.properties')
8 | String sha1 = null
9 | if (signingFile.exists()) {
10 | def input = signingFile.newInputStream()
11 | def p = new Properties()
12 | p.load(input)
13 | input.close()
14 | // 签名文件存在才配置签名,
15 | def jks = rootProject.file(p['storeFile'])
16 | if (jks.exists()) {
17 | signingConfigs {
18 | config {
19 | keyAlias p['keyAlias']
20 | keyPassword p['keyPassword']
21 | storeFile jks
22 | storePassword p['storePassword']
23 | v1SigningEnabled true
24 | v2SigningEnabled true
25 | }
26 | }
27 | buildTypes {
28 | debug.signingConfig signingConfigs.config
29 | release.signingConfig signingConfigs.config
30 | }
31 | def signingConfig = signingConfigs.config
32 | if (signingConfig != null) {
33 | //noinspection UnnecessaryQualifiedReference
34 | def keyStore = java.security.KeyStore.getInstance(
35 | signingConfig.getStoreType() != null ?
36 | signingConfig.getStoreType() : KeyStore.getDefaultType())
37 | FileInputStream fis = new FileInputStream(signingConfig.getStoreFile())
38 | keyStore.load(fis, signingConfig.getStorePassword().toCharArray())
39 | fis.close()
40 | char[] keyPassword = signingConfig.getKeyPassword().toCharArray()
41 | //noinspection UnnecessaryQualifiedReference
42 | def entry = keyStore.getEntry(
43 | signingConfig.getKeyAlias(),
44 | new java.security.KeyStore.PasswordProtection(keyPassword))
45 | if (entry != null) {
46 | //noinspection UnnecessaryQualifiedReference
47 | def digest = java.security.MessageDigest.getInstance("SHA-1")
48 | sha1 = digest.digest(entry.getCertificate().encoded).encodeHex().toString()
49 | }
50 | }
51 | }
52 | }
53 | if (sha1 == null) {
54 | defaultConfig.buildConfigField('String', "SIGNATURE", 'null')
55 | } else {
56 | defaultConfig.buildConfigField('String', "SIGNATURE", '"' + sha1 + '"')
57 | }
58 |
59 | }
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/signing.txt:
--------------------------------------------------------------------------------
1 | Alias name: IAmNotDisabled
2 | Creation date: 2022年1月6日
3 | Entry type: PrivateKeyEntry
4 | Certificate chain length: 1
5 | Certificate[1]:
6 | Owner: CN=AoEiuV020, OU=IAmNotDisabled, O=AoEiuV020, L=China, ST=China, C=CN
7 | Issuer: CN=AoEiuV020, OU=IAmNotDisabled, O=AoEiuV020, L=China, ST=China, C=CN
8 | Serial number: 7b6f250d
9 | Valid from: Thu Jan 06 02:58:02 CST 2022 until: Mon May 24 02:58:02 CST 2049
10 | Certificate fingerprints:
11 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
12 | SHA256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
13 | Signature algorithm name: SHA256withRSA
14 | Subject Public Key Algorithm: 2048-bit RSA key
15 | Version: 3
16 |
17 | Extensions:
18 |
19 | #1: ObjectId: 2.5.29.14 Criticality=false
20 | SubjectKeyIdentifier [
21 | KeyIdentifier [
22 | 0000: 05 CD E3 EB DD 35 D2 58 E7 E4 FE 2A 37 3A AC F3 .....5.X...*7:..
23 | 0010: 5F 7D E8 1A _...
24 | ]
25 | ]
26 |
27 |
28 | > Task :hook:signingReport
29 | Variant: debug
30 | Config: config
31 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
32 | Alias: IAmNotDisabled
33 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
34 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
35 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
36 | Valid until: Monday, May 24, 2049
37 | ----------
38 | Variant: release
39 | Config: config
40 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
41 | Alias: IAmNotDisabled
42 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
43 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
44 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
45 | Valid until: Monday, May 24, 2049
46 | ----------
47 | Variant: debugAndroidTest
48 | Config: config
49 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
50 | Alias: IAmNotDisabled
51 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
52 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
53 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
54 | Valid until: Monday, May 24, 2049
55 | ----------
56 |
57 | > Task :app:signingReport
58 | Variant: debug
59 | Config: config
60 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
61 | Alias: IAmNotDisabled
62 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
63 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
64 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
65 | Valid until: Monday, May 24, 2049
66 | ----------
67 | Variant: release
68 | Config: config
69 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
70 | Alias: IAmNotDisabled
71 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
72 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
73 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
74 | Valid until: Monday, May 24, 2049
75 | ----------
76 | Variant: debugAndroidTest
77 | Config: config
78 | Store: /mnt/wext/code/git/IAmNotDisabled/IAmNotDisabled.jks
79 | Alias: IAmNotDisabled
80 | MD5: 44:43:D3:3D:34:46:4C:1B:16:60:91:87:4A:7F:1E:54
81 | SHA1: 66:ED:5E:E1:AC:D5:4E:F4:50:1C:3C:78:A3:7D:71:59:51:DA:21:7E
82 | SHA-256: 20:10:77:72:62:57:A8:81:00:50:0A:3D:B5:25:BC:EC:10:69:10:5B:F9:02:C3:F1:F6:F6:9E:C6:26:10:FB:61
83 | Valid until: Monday, May 24, 2049
84 | ----------
85 |
86 | Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
87 | Use '--warning-mode all' to show the individual deprecation warnings.
88 | See https://docs.gradle.org/7.0.2/userguide/command_line_interface.html#sec:command_line_warnings
89 |
90 | BUILD SUCCESSFUL in 973ms
91 | 2 actionable tasks: 2 executed
92 |
--------------------------------------------------------------------------------
/app/src/main/java/cc/aoeiuv020/iamnotdisabled/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled
2 |
3 | import android.accessibilityservice.AccessibilityServiceInfo
4 | import android.annotation.SuppressLint
5 | import android.os.Bundle
6 | import android.os.Handler
7 | import android.os.Looper
8 | import android.provider.Settings
9 | import android.view.View
10 | import android.view.accessibility.AccessibilityManager
11 | import android.widget.TextView
12 | import androidx.appcompat.app.AppCompatActivity
13 | import androidx.core.content.ContextCompat
14 | import androidx.lifecycle.DefaultLifecycleObserver
15 | import androidx.lifecycle.LifecycleOwner
16 |
17 | class MainActivity : AppCompatActivity() {
18 | override fun onCreate(savedInstanceState: Bundle?) {
19 | super.onCreate(savedInstanceState)
20 | setContentView(R.layout.activity_main)
21 |
22 | findViewById(R.id.tvResult).setOnClickListener {
23 | checkDisabled()
24 | }
25 | checkDisabled()
26 | addListener()
27 | }
28 |
29 | private fun addListener() {
30 | val accessibilityManager =
31 | ContextCompat.getSystemService(this, AccessibilityManager::class.java)
32 | ?: error("unreachable")
33 | lifecycle.addObserver(object : DefaultLifecycleObserver {
34 | private val handler = Handler(Looper.getMainLooper())
35 | private val listener = AccessibilityManager.AccessibilityStateChangeListener {
36 | updateDisabled(listOf("监听到无障碍服务 " + getEnabledString(it)))
37 | }
38 | private val touchExplorationListener =
39 | AccessibilityManager.TouchExplorationStateChangeListener {
40 | updateDisabled(listOf("监听到读屏服务 " + getEnabledString(it)))
41 | }
42 |
43 | override fun onCreate(owner: LifecycleOwner) {
44 | accessibilityManager.addAccessibilityStateChangeListener(listener)
45 | accessibilityManager.addAccessibilityStateChangeListener(listener, handler)
46 | accessibilityManager.addTouchExplorationStateChangeListener(touchExplorationListener)
47 | accessibilityManager.addTouchExplorationStateChangeListener(
48 | touchExplorationListener,
49 | handler
50 | )
51 | }
52 |
53 | override fun onDestroy(owner: LifecycleOwner) {
54 | accessibilityManager.removeAccessibilityStateChangeListener(listener)
55 | accessibilityManager.removeTouchExplorationStateChangeListener(touchExplorationListener)
56 | }
57 | })
58 | }
59 |
60 | private fun getEnabledString(enabled: Boolean) = if (enabled) "启用" else "禁用"
61 |
62 | private fun checkDisabled() {
63 | val serviceList = getFromAccessibilityManager() + getFromSettingsSecure()
64 | updateDisabled(serviceList)
65 | }
66 |
67 | @SuppressLint("SetTextI18n")
68 | private fun updateDisabled(
69 | serviceList: List
70 | ) {
71 | val tvResult: TextView = findViewById(R.id.tvResult)
72 | val tvReason: TextView = findViewById(R.id.tvReason)
73 | if (serviceList.isNotEmpty()) {
74 | tvResult.text = "你是残疾人!"
75 | tvReason.text = "因为:\n" + serviceList.joinToString("\n")
76 | } else {
77 | tvResult.text = "你很健康"
78 | tvReason.text = ""
79 | }
80 | }
81 |
82 | private fun getFromAccessibilityManager(): List {
83 | val accessibilityManager =
84 | ContextCompat.getSystemService(this, AccessibilityManager::class.java)
85 | ?: error("unreachable")
86 | val serviceList: List =
87 | accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
88 | ?: emptyList()
89 | val nameList = serviceList.map {
90 | packageManager.getApplicationLabel(it.resolveInfo.serviceInfo.applicationInfo)
91 | .toString()
92 | }.toMutableList()
93 | if (accessibilityManager.isEnabled) {
94 | nameList.add("AccessibilityManager.isEnabled")
95 | }
96 | if (accessibilityManager.isTouchExplorationEnabled) {
97 | nameList.add("AccessibilityManager.isTouchExplorationEnabled")
98 | }
99 | return nameList
100 | }
101 |
102 | private fun getFromSettingsSecure(): List {
103 | val settingValue = Settings.Secure.getString(
104 | contentResolver,
105 | Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
106 | )
107 | val nameList = if (settingValue.isEmpty()) {
108 | emptyList()
109 | } else {
110 | settingValue.split(':')
111 | }.toMutableList()
112 | val enabled = Settings.Secure.getInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED)
113 | if (enabled != 0) {
114 | nameList.add("ACCESSIBILITY_ENABLED == $enabled")
115 | }
116 | return nameList
117 | }
118 | }
--------------------------------------------------------------------------------
/hook/src/main/java/cc/aoeiuv020/iamnotdisabled/hook/MainHook.java:
--------------------------------------------------------------------------------
1 | package cc.aoeiuv020.iamnotdisabled.hook;
2 |
3 | import android.content.ContentResolver;
4 | import android.os.Handler;
5 | import android.provider.Settings;
6 | import android.view.accessibility.AccessibilityManager;
7 |
8 | import java.util.Collections;
9 |
10 | import de.robv.android.xposed.IXposedHookLoadPackage;
11 | import de.robv.android.xposed.IXposedHookZygoteInit;
12 | import de.robv.android.xposed.XC_MethodHook;
13 | import de.robv.android.xposed.XC_MethodReplacement;
14 | import de.robv.android.xposed.XposedBridge;
15 | import de.robv.android.xposed.XposedHelpers;
16 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
17 |
18 | /**
19 | * Created by AoEiuV020 on 2022.01.06-03:25:32.
20 | */
21 | @SuppressWarnings("RedundantThrows")
22 | public class MainHook implements IXposedHookLoadPackage, IXposedHookZygoteInit {
23 | @Override
24 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
25 | XposedBridge.log("handleLoadPackage: " + lpparam.processName);
26 | XposedHelpers.findAndHookMethod("android.provider.Settings$Secure", lpparam.classLoader, "getString", ContentResolver.class, String.class, new XC_MethodHook() {
27 | protected void beforeHookedMethod(MethodHookParam methodHookParam2) throws Throwable {
28 | if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(methodHookParam2.args[1])) {
29 | methodHookParam2.setResult("");
30 | }
31 | }
32 | });
33 | XposedHelpers.findAndHookMethod("android.provider.Settings$Secure", lpparam.classLoader, "getInt", ContentResolver.class, String.class, new XC_MethodHook() {
34 | protected void beforeHookedMethod(MethodHookParam methodHookParam2) throws Throwable {
35 | if (Settings.Secure.ACCESSIBILITY_ENABLED.equals(methodHookParam2.args[1])) {
36 | methodHookParam2.setResult(0);
37 | }
38 | }
39 | });
40 | }
41 |
42 | private boolean doNotHack(Throwable throwable) {
43 | if (throwable.getStackTrace().length >= 3) {
44 | StackTraceElement stackTraceElement = throwable.getStackTrace()[3];
45 | if (stackTraceElement.getClassName().startsWith("LSPHooker_")) {
46 | stackTraceElement = throwable.getStackTrace()[4];
47 | }
48 | return stackTraceElement.getClassName().startsWith("android.")
49 | || stackTraceElement.getClassName().startsWith("androidx.")
50 | || stackTraceElement.getClassName().startsWith("com.android.")
51 | || stackTraceElement.getClassName().startsWith("org.chromium.content.browser.");
52 | }
53 | return false;
54 | }
55 |
56 | @Override
57 | public void initZygote(StartupParam startupParam) throws Throwable {
58 | XposedBridge.log("initZygote: " + startupParam.modulePath);
59 | XposedHelpers.findAndHookMethod(
60 | "android.view.accessibility.AccessibilityManager",
61 | null,
62 | "getEnabledAccessibilityServiceList",
63 | int.class,
64 | XC_MethodReplacement.returnConstant(Collections.emptyList())
65 | );
66 | XposedHelpers.findAndHookMethod(
67 | "android.view.accessibility.AccessibilityManager",
68 | null,
69 | "isEnabled",
70 | new XC_MethodHook() {
71 | @Override
72 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
73 | Throwable throwable = new Throwable();
74 | if (doNotHack(throwable)) return;
75 | param.setResult(false);
76 | }
77 | }
78 | );
79 | XposedHelpers.findAndHookMethod(
80 | "android.view.accessibility.AccessibilityManager",
81 | null,
82 | "isTouchExplorationEnabled",
83 | new XC_MethodHook() {
84 | @Override
85 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
86 | Throwable throwable = new Throwable();
87 | if (doNotHack(throwable)) return;
88 | param.setResult(false);
89 | }
90 | }
91 | );
92 | XposedHelpers.findAndHookMethod(
93 | "android.view.accessibility.AccessibilityManager",
94 | null,
95 | "addAccessibilityStateChangeListener",
96 | AccessibilityManager.AccessibilityStateChangeListener.class,
97 | XC_MethodReplacement.returnConstant(true)
98 | );
99 | XposedHelpers.findAndHookMethod(
100 | "android.view.accessibility.AccessibilityManager",
101 | null,
102 | "addAccessibilityStateChangeListener",
103 | AccessibilityManager.AccessibilityStateChangeListener.class,
104 | Handler.class,
105 | XC_MethodReplacement.returnConstant(null)
106 | );
107 | XposedHelpers.findAndHookMethod(
108 | "android.view.accessibility.AccessibilityManager",
109 | null,
110 | "addTouchExplorationStateChangeListener",
111 | AccessibilityManager.TouchExplorationStateChangeListener.class,
112 | XC_MethodReplacement.returnConstant(true)
113 | );
114 | XposedHelpers.findAndHookMethod(
115 | "android.view.accessibility.AccessibilityManager",
116 | null,
117 | "addTouchExplorationStateChangeListener",
118 | AccessibilityManager.TouchExplorationStateChangeListener.class,
119 | Handler.class,
120 | XC_MethodReplacement.returnConstant(null)
121 | );
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | env:
3 | TZ: Asia/Shanghai
4 |
5 | on:
6 | push:
7 | paths-ignore:
8 | - '/readme/*'
9 | - '**/README.md'
10 | - '.github/workflows/*'
11 | - '!.github/workflows/main.yml'
12 |
13 | jobs:
14 | build:
15 |
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - uses: actions/checkout@v2
20 | - name: init custom env
21 | run: |
22 | set -a
23 | BUILD_NAME="${GITHUB_REPOSITORY#*/}"
24 | if [[ ${GITHUB_REF} == refs/tags* ]]
25 | then
26 | CREATE_RELEASE="true"
27 | BUILD_VERSION=${GITHUB_REF#refs/tags/}
28 | RELEASE_BODY=$(./latest-changelog.sh $BUILD_VERSION)
29 | if [[ -z "$RELEASE_BODY" ]]
30 | then
31 | RELEASE_BODY='### ${{ github.event.head_commit.message }}'
32 | fi
33 | TG_CHANGELOG="$RELEASE_BODY"
34 | elif [[ ${GITHUB_REF} == refs/pull* ]]
35 | then
36 | CREATE_RELEASE="false"
37 | num=${GITHUB_REF#refs/pull/}
38 | num=${num%/merge}
39 | BUILD_VERSION=pr-${num}-"$(date +'%Y%m%d%H%M%S')"
40 | else
41 | CREATE_RELEASE="true"
42 | echo PRE_RELEASE="true" >> .custom_env
43 | BUILD_VERSION="$(date +'%Y%m%d%H%M%S')"
44 | RELEASE_BODY=$(echo '${{ toJson(github.event.commits) }}' |jq -r 'map("### "+.message)|join("\n\n------\n")')
45 | TG_CHANGELOG=$(echo "$RELEASE_BODY"|sed -n "s/### \(.*\)/\1/p" |sed -n '{;=;p}' | sed "N;s/\n/. /g")
46 | VERSION_PREFIX='内测版-'
47 | fi
48 | BUILD_NAME_WITH_VERSION="$BUILD_NAME-$BUILD_VERSION"
49 | echo BUILD_NAME="$BUILD_NAME" >> .custom_env
50 | echo BUILD_VERSION="$BUILD_VERSION" >> .custom_env
51 | echo BUILD_NAME_WITH_VERSION="$BUILD_NAME_WITH_VERSION" >> .custom_env
52 | echo CREATE_RELEASE="$CREATE_RELEASE" >> .custom_env
53 | if test -n "$RELEASE_BODY"
54 | then
55 | echo 'RELEASE_BODY<> .custom_env
56 | echo "$RELEASE_BODY" >> .custom_env
57 | echo 'EOF' >> .custom_env
58 | echo 'UPDATE_BODY<> .custom_env
59 | envsubst < template-update.md >> .custom_env
60 | echo >> .custom_env
61 | echo 'EOF' >> .custom_env
62 | fi
63 | if [[ "$CREATE_RELEASE" == "true" && -n "${{ secrets.XPOSED_UPLOAD_TOKEN }}" ]]
64 | then
65 | echo CREATE_XPOSED_RELEASE="true" >> .custom_env
66 | fi
67 | if [[ "$CREATE_RELEASE" == "true" && -n "${{ secrets.TELEGRAM_TO }}" && -n "${{ secrets.TELEGRAM_TOKEN }}" ]]
68 | then
69 | echo SEND_TELEGRAM="true" >> .custom_env
70 | fi
71 | cat .custom_env
72 | cat .custom_env >> $GITHUB_ENV
73 | - name: set up JDK 1.11
74 | uses: actions/setup-java@v1
75 | with:
76 | java-version: 1.11
77 | - name: Build with Gradle
78 | run: |
79 | ./gradlew :app:assembleRelease
80 | ./gradlew :hook:assembleRelease
81 | - uses: AoEiuV020/sign-android-release@v2
82 | name: Sign app APK
83 | env:
84 | SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
85 | if: ${{ env.SIGNING_KEY != '' }}
86 | with:
87 | releaseDirectory: ./app/build/outputs/apk/release
88 | signingKeyBase64: ${{ secrets.SIGNING_KEY }}
89 | alias: ${{ secrets.ALIAS }}
90 | keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
91 | keyPassword: ${{ secrets.KEY_PASSWORD }}
92 | - uses: AoEiuV020/sign-android-release@v2
93 | name: Sign hook APK
94 | env:
95 | SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
96 | if: ${{ env.SIGNING_KEY != '' }}
97 | with:
98 | releaseDirectory: ./hook/build/outputs/apk/release
99 | signingKeyBase64: ${{ secrets.SIGNING_KEY }}
100 | alias: ${{ secrets.ALIAS }}
101 | keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
102 | keyPassword: ${{ secrets.KEY_PASSWORD }}
103 | - name: Build with Gradle
104 | run: |
105 | find ./app/build/outputs -name '*.apk' -exec mv {} $BUILD_NAME_WITH_VERSION-app.apk \;
106 | find ./hook/build/outputs -name '*.apk' -exec mv {} $BUILD_NAME_WITH_VERSION-hook.apk \;
107 | - name: Upload APK
108 | uses: actions/upload-artifact@master
109 | with:
110 | name: build
111 | path: ${{ env.BUILD_NAME_WITH_VERSION }}*.apk
112 | - name: create release
113 | if: ${{ env.CREATE_RELEASE == 'true' }}
114 | id: create_release
115 | uses: actions/create-release@v1
116 | env:
117 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
118 | with:
119 | tag_name: ${{ env.BUILD_VERSION }}
120 | release_name: ${{ env.BUILD_VERSION }}
121 | body: ${{ env.RELEASE_BODY }}
122 | draft: true
123 | prerelease: ${{ env.PRE_RELEASE == 'true' }}
124 | - name: Upload app
125 | if: ${{ env.CREATE_RELEASE == 'true' }}
126 | uses: actions/upload-release-asset@v1
127 | env:
128 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
129 | with:
130 | upload_url: ${{ steps.create_release.outputs.upload_url }}
131 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-app.apk
132 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-app.apk
133 | asset_content_type: application/zip
134 | - name: Upload hook
135 | if: ${{ env.CREATE_RELEASE == 'true' }}
136 | uses: actions/upload-release-asset@v1
137 | env:
138 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
139 | with:
140 | upload_url: ${{ steps.create_release.outputs.upload_url }}
141 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk
142 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk
143 | asset_content_type: application/zip
144 | - name: public release
145 | if: ${{ env.CREATE_RELEASE == 'true' }}
146 | uses: AoEiuV020/publish-release@master
147 | env:
148 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
149 | with:
150 | release_id: ${{ steps.create_release.outputs.id }}
151 |
152 | - name: create release
153 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }}
154 | id: xposed_create_release
155 | uses: actions/create-release@v1
156 | env:
157 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }}
158 | with:
159 | owner: Xposed-Modules-Repo
160 | repo: cc.aoeiuv020.iamnotdisabled.hook
161 | commitish: main
162 | tag_name: ${{ env.BUILD_VERSION }}
163 | release_name: ${{ env.BUILD_VERSION }}
164 | body: ${{ env.RELEASE_BODY }}
165 | draft: true
166 | prerelease: ${{ env.PRE_RELEASE == 'true' }}
167 | - name: Upload app
168 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }}
169 | uses: actions/upload-release-asset@v1
170 | env:
171 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }}
172 | with:
173 | upload_url: ${{ steps.xposed_create_release.outputs.upload_url }}
174 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-app.apk
175 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-app.apk
176 | asset_content_type: application/zip
177 | - name: Upload hook
178 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }}
179 | uses: actions/upload-release-asset@v1
180 | env:
181 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }}
182 | with:
183 | upload_url: ${{ steps.xposed_create_release.outputs.upload_url }}
184 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk
185 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk
186 | asset_content_type: application/zip
187 | - name: public release
188 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }}
189 | uses: AoEiuV020/publish-release@master
190 | env:
191 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }}
192 | with:
193 | owner: Xposed-Modules-Repo
194 | repo: cc.aoeiuv020.iamnotdisabled.hook
195 | release_id: ${{ steps.xposed_create_release.outputs.id }}
196 |
197 | - name: Send commit to telegram
198 | if: ${{ env.SEND_TELEGRAM == 'true' }}
199 | uses: appleboy/telegram-action@master
200 | with:
201 | to: ${{ secrets.TELEGRAM_TO }}
202 | token: ${{ secrets.TELEGRAM_TOKEN }}
203 | format: markdown
204 | disable_web_page_preview: true
205 | message: ${{ env.UPDATE_BODY }}
206 | document: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk
207 |
--------------------------------------------------------------------------------