├── .github └── workflows │ └── main.yml ├── .gitignore ├── ChangeLog.txt ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle ├── signing.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── hook ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── cc │ │ └── aoeiuv020 │ │ └── hookpicacg │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── xposed_init │ ├── ic_launcher-playstore.png │ ├── java │ │ └── cc │ │ │ └── aoeiuv020 │ │ │ └── hookpicacg │ │ │ └── MainHook.java │ └── res │ │ ├── drawable │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi-v26 │ │ └── ic_launcher.xml │ │ └── values │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings-notran.xml │ │ └── strings.xml │ └── test │ └── java │ └── cc │ └── aoeiuv020 │ └── hookpicacg │ └── ExampleUnitTest.kt ├── info.txt ├── latest-changelog.sh ├── latest-version.sh ├── settings.gradle └── template-update.md /.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 | workflow_dispatch: 13 | 14 | jobs: 15 | build: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: init custom env 22 | run: | 23 | set -a 24 | BUILD_NAME="${GITHUB_REPOSITORY#*/}" 25 | if [[ ${GITHUB_REF} == refs/tags* ]] 26 | then 27 | CREATE_RELEASE="true" 28 | BUILD_VERSION=${GITHUB_REF#refs/tags/} 29 | RELEASE_BODY=$(./latest-changelog.sh $BUILD_VERSION |sed '1s/[,,]$//;1s/^\(.*\)$/### \1\n/') 30 | if [[ -z "$RELEASE_BODY" ]] 31 | then 32 | RELEASE_BODY='### ${{ github.event.head_commit.message }}' 33 | TG_CHANGELOG="$(echo "$RELEASE_BODY"|sed -n "s/### \(.*\)/\1/p" |sed -n '{;=;p}' | sed "N;s/\n/. /g")" 34 | else 35 | TG_CHANGELOG=$(./latest-changelog.sh $BUILD_VERSION |sed -n '{;=;p}' | sed "N;s/\n/. /g") 36 | fi 37 | elif [[ ${GITHUB_REF} == refs/pull* ]] 38 | then 39 | CREATE_RELEASE="false" 40 | num=${GITHUB_REF#refs/pull/} 41 | num=${num%/merge} 42 | BUILD_VERSION=pr-${num}-"$(date +'%Y%m%d%H%M%S')" 43 | else 44 | CREATE_RELEASE="true" 45 | echo PRE_RELEASE="true" >> .custom_env 46 | BUILD_VERSION="$(date +'%Y%m%d%H%M%S')" 47 | RELEASE_BODY=$(echo '${{ toJson(github.event.commits) }}' |jq -r 'map("### "+.message)|join("\n\n------\n")') 48 | TG_CHANGELOG="$(echo "$RELEASE_BODY"|sed -n "s/### \(.*\)/\1/p" |sed -n '{;=;p}' | sed "N;s/\n/. /g")" 49 | VERSION_PREFIX='内测版-' 50 | fi 51 | BUILD_NAME_WITH_VERSION="$BUILD_NAME-$BUILD_VERSION" 52 | echo BUILD_NAME="$BUILD_NAME" >> .custom_env 53 | echo BUILD_VERSION="$BUILD_VERSION" >> .custom_env 54 | echo BUILD_NAME_WITH_VERSION="$BUILD_NAME_WITH_VERSION" >> .custom_env 55 | echo CREATE_RELEASE="$CREATE_RELEASE" >> .custom_env 56 | if test -n "$RELEASE_BODY" 57 | then 58 | echo 'RELEASE_BODY<> .custom_env 59 | echo "$RELEASE_BODY" >> .custom_env 60 | echo 'EOF' >> .custom_env 61 | echo 'UPDATE_BODY<> .custom_env 62 | envsubst < template-update.md >> .custom_env 63 | echo >> .custom_env 64 | echo 'EOF' >> .custom_env 65 | fi 66 | if [[ "$CREATE_RELEASE" == "true" && -n "${{ secrets.XPOSED_UPLOAD_TOKEN }}" && -n "${{ secrets.XPOSED_UPLOAD_REPO }}" ]] 67 | then 68 | echo CREATE_XPOSED_RELEASE="true" >> .custom_env 69 | fi 70 | if [[ "$CREATE_RELEASE" == "true" && -n "${{ secrets.TELEGRAM_TO }}" && -n "${{ secrets.TELEGRAM_TOKEN }}" ]] 71 | then 72 | echo SEND_TELEGRAM="true" >> .custom_env 73 | fi 74 | cat .custom_env 75 | cat .custom_env >> $GITHUB_ENV 76 | - name: set up JDK 1.11 77 | uses: actions/setup-java@v1 78 | with: 79 | java-version: 1.11 80 | - name: Build with Gradle 81 | run: | 82 | ./gradlew :hook:assembleRelease 83 | - uses: AoEiuV020/sign-android-release@v2 84 | name: Sign hook APK 85 | env: 86 | SIGNING_KEY: ${{ secrets.SIGNING_KEY }} 87 | if: ${{ env.SIGNING_KEY != '' }} 88 | with: 89 | releaseDirectory: ./hook/build/outputs/apk/release 90 | signingKeyBase64: ${{ secrets.SIGNING_KEY }} 91 | alias: ${{ secrets.ALIAS }} 92 | keyStorePassword: ${{ secrets.KEY_PASSWORD }} 93 | keyPassword: ${{ secrets.KEY_PASSWORD }} 94 | - name: Build with Gradle 95 | run: | 96 | find ./hook/build/outputs/apk/release -name '*.apk' -exec mv {} $BUILD_NAME_WITH_VERSION-hook.apk \; 97 | - name: Upload APK 98 | uses: actions/upload-artifact@master 99 | with: 100 | name: build 101 | path: ${{ env.BUILD_NAME_WITH_VERSION }}*.apk 102 | - name: create release 103 | if: ${{ env.CREATE_RELEASE == 'true' }} 104 | id: create_release 105 | uses: actions/create-release@v1 106 | env: 107 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 108 | with: 109 | tag_name: ${{ env.BUILD_VERSION }} 110 | release_name: ${{ env.BUILD_VERSION }} 111 | body: ${{ env.RELEASE_BODY }} 112 | draft: true 113 | prerelease: ${{ env.PRE_RELEASE == 'true' }} 114 | - name: Upload hook 115 | if: ${{ env.CREATE_RELEASE == 'true' }} 116 | uses: actions/upload-release-asset@v1 117 | env: 118 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 119 | with: 120 | upload_url: ${{ steps.create_release.outputs.upload_url }} 121 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk 122 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk 123 | asset_content_type: application/zip 124 | - name: public release 125 | if: ${{ env.CREATE_RELEASE == 'true' }} 126 | uses: AoEiuV020/publish-release@master 127 | env: 128 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 129 | with: 130 | release_id: ${{ steps.create_release.outputs.id }} 131 | 132 | - name: create release 133 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }} 134 | id: xposed_create_release 135 | uses: actions/create-release@v1 136 | env: 137 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }} 138 | with: 139 | owner: Xposed-Modules-Repo 140 | repo: ${{ secrets.XPOSED_UPLOAD_REPO }} 141 | commitish: main 142 | tag_name: ${{ env.BUILD_VERSION }} 143 | release_name: ${{ env.BUILD_VERSION }} 144 | body: ${{ env.RELEASE_BODY }} 145 | draft: true 146 | prerelease: ${{ env.PRE_RELEASE == 'true' }} 147 | - name: Upload hook 148 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }} 149 | uses: actions/upload-release-asset@v1 150 | env: 151 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }} 152 | with: 153 | upload_url: ${{ steps.xposed_create_release.outputs.upload_url }} 154 | asset_path: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk 155 | asset_name: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk 156 | asset_content_type: application/zip 157 | - name: public release 158 | if: ${{ env.CREATE_XPOSED_RELEASE == 'true' }} 159 | uses: AoEiuV020/publish-release@master 160 | env: 161 | GITHUB_TOKEN: ${{ secrets.XPOSED_UPLOAD_TOKEN }} 162 | with: 163 | owner: Xposed-Modules-Repo 164 | repo: ${{ secrets.XPOSED_UPLOAD_REPO }} 165 | release_id: ${{ steps.xposed_create_release.outputs.id }} 166 | 167 | - name: Send commit to telegram 168 | if: ${{ env.SEND_TELEGRAM == 'true' }} 169 | uses: appleboy/telegram-action@master 170 | with: 171 | to: ${{ secrets.TELEGRAM_TO }} 172 | token: ${{ secrets.TELEGRAM_TOKEN }} 173 | format: markdown 174 | disable_web_page_preview: true 175 | message: ${{ env.UPDATE_BODY }} 176 | document: ${{ env.BUILD_NAME_WITH_VERSION }}-hook.apk 177 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /ChangeLog.txt: -------------------------------------------------------------------------------- 1 | 更新日志: 2 | 2.2.1.3.3.4-6: 3 | 上传到lsposed仓库, 4 | 5 | 2.2.1.3.3.4-5: 6 | 取消列表广告, 7 | 8 | 2.2.1.3.3.4: 9 | 取消弹窗广告, 10 | 取消倒计时广告, 11 | 取消横幅广告, 12 | 取消首页广告, 13 | 移除游戏标签页, 14 | 移除阅读页的广告, 15 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HookPicACG 2 | xposed给哔咔去广告, 3 | [![img](https://img.shields.io/badge/%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97-ChangeLog-brightgreen)](./ChangeLog.txt) 4 | [![CI](https://github.com/AoEiuV020/HookPicACG/actions/workflows/main.yml/badge.svg)](https://github.com/AoEiuV020/HookPicACG/actions/workflows/main.yml) 5 | [![img](https://img.shields.io/github/v/release/AoEiuV020/HookPicACG.svg?include_prereleases)](https://github.com/AoEiuV020/HookPicACG/releases) 6 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.application' version '7.1.2' apply false 4 | id 'com.android.library' version '7.1.2' apply false 5 | } 6 | 7 | task clean(type: Delete) { 8 | delete rootProject.buildDir 9 | } -------------------------------------------------------------------------------- /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 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AoEiuV020/HookPicACG/46e562b83e9d76b4ea5430f72498b9753e9a92f3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 14 20:01:04 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /hook/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /hook/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | } 4 | 5 | android { 6 | compileSdk 32 7 | 8 | defaultConfig { 9 | applicationId "cc.aoeiuv020.hookpicacg" 10 | minSdk 26 11 | targetSdk 32 12 | versionCode 1 13 | versionName "2.2.1.3.3.4-5" 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 | compileOnly 'de.robv.android.xposed:api:82:sources' 33 | 34 | testImplementation 'junit:junit:4.13.2' 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 | -------------------------------------------------------------------------------- /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/hookpicacg/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package cc.aoeiuv020.hookpicacg 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.hookpicacg", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /hook/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 17 | 20 | 23 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /hook/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | cc.aoeiuv020.hookpicacg.MainHook -------------------------------------------------------------------------------- /hook/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AoEiuV020/HookPicACG/46e562b83e9d76b4ea5430f72498b9753e9a92f3/hook/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /hook/src/main/java/cc/aoeiuv020/hookpicacg/MainHook.java: -------------------------------------------------------------------------------- 1 | package cc.aoeiuv020.hookpicacg; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Bundle; 6 | import android.text.TextUtils; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import de.robv.android.xposed.IXposedHookLoadPackage; 12 | import de.robv.android.xposed.XC_MethodHook; 13 | import de.robv.android.xposed.XposedBridge; 14 | import de.robv.android.xposed.XposedHelpers; 15 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 16 | 17 | @SuppressWarnings("RedundantThrows") 18 | public class MainHook implements IXposedHookLoadPackage { 19 | @Override 20 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { 21 | XposedBridge.log("handleLoadPackage: " + lpparam.processName + ", " + lpparam.processName); 22 | Class dialogClass = XposedHelpers.findClassIfExists("com.picacomic.fregata.utils.views.AlertDialogCenter", lpparam.classLoader); 23 | if (dialogClass == null) { 24 | return; 25 | } 26 | XposedHelpers.findAndHookMethod( 27 | dialogClass, 28 | "showAnnouncementAlertDialog", 29 | Context.class, 30 | String.class, 31 | String.class, 32 | String.class, 33 | String.class, 34 | View.OnClickListener.class, 35 | new XC_MethodHook() { 36 | @Override 37 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 38 | param.setResult(null); 39 | } 40 | }); 41 | XposedHelpers.findAndHookMethod( 42 | "com.picacomic.fregata.utils.views.PopupWebview", 43 | lpparam.classLoader, 44 | "init", 45 | Context.class, 46 | new XC_MethodHook() { 47 | @Override 48 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 49 | XposedBridge.log("beforeHookedMethod: PopupWebview.init(Context)"); 50 | param.setResult(null); 51 | } 52 | }); 53 | XposedHelpers.findAndHookMethod( 54 | "com.picacomic.fregata.utils.views.BannerWebview", 55 | lpparam.classLoader, 56 | "init", 57 | Context.class, 58 | new XC_MethodHook() { 59 | @Override 60 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 61 | XposedBridge.log("beforeHookedMethod: BannerWebview.init(Context)"); 62 | param.setResult(null); 63 | } 64 | }); 65 | XposedHelpers.findAndHookMethod( 66 | "com.picacomic.fregata.activities.MainActivity", 67 | lpparam.classLoader, 68 | "onCreate", 69 | Bundle.class, 70 | new XC_MethodHook() { 71 | @Override 72 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 73 | XposedBridge.log("afterHookedMethod: MainActivity.onCreate(Bundle)"); 74 | View[] buttons_tabbar = (View[]) XposedHelpers.getObjectField(param.thisObject, "buttons_tabbar"); 75 | buttons_tabbar[2].setVisibility(View.GONE); 76 | Activity activity = (Activity) param.thisObject; 77 | ViewGroup root = (ViewGroup) ((ViewGroup) (activity.findViewById(android.R.id.content))).getChildAt(0); 78 | for (int i = root.getChildCount() - 1; i >= 0; i--) { 79 | View child = root.getChildAt(i); 80 | if (TextUtils.equals("com.picacomic.fregata.utils.views.BannerWebview", child.getClass().getName()) 81 | || TextUtils.equals("com.picacomic.fregata.utils.views.PopupWebview", child.getClass().getName())) { 82 | root.removeViewAt(i); 83 | } 84 | } 85 | } 86 | 87 | }); 88 | XposedHelpers.findAndHookMethod( 89 | "com.picacomic.fregata.fragments.HomeFragment", 90 | lpparam.classLoader, 91 | "onCreateView", 92 | LayoutInflater.class, 93 | ViewGroup.class, 94 | Bundle.class, 95 | new XC_MethodHook() { 96 | @Override 97 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 98 | XposedBridge.log("afterHookedMethod: HomeFragment.onCreateView"); 99 | View viewPager_banner = (View) XposedHelpers.getObjectField(param.thisObject, "viewPager_banner"); 100 | ((View) (viewPager_banner.getParent())).setVisibility(View.GONE); 101 | View linearLayout_announcements = (View) XposedHelpers.getObjectField(param.thisObject, "linearLayout_announcements"); 102 | linearLayout_announcements.setVisibility(View.GONE); 103 | } 104 | }); 105 | XposedHelpers.findAndHookMethod( 106 | "com.picacomic.fregata.adapters.ComicPageRecyclerViewAdapter", 107 | lpparam.classLoader, 108 | "onCreateViewHolder", 109 | ViewGroup.class, 110 | int.class, 111 | new XC_MethodHook() { 112 | @Override 113 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 114 | XposedBridge.log("afterHookedMethod: ComicPageRecyclerViewAdapter.onCreateViewHolder"); 115 | Object result = param.getResult(); 116 | if (!TextUtils.equals(result.getClass().getName(), "com.picacomic.fregata.holders.AdvertisementListViewHolder")) { 117 | return; 118 | } 119 | View webView_ads = (View) XposedHelpers.getObjectField(result, "itemView"); 120 | webView_ads.setVisibility(View.GONE); 121 | Object lp = XposedHelpers.newInstance(XposedHelpers.findClass("android.support.v7.widget.RecyclerView$LayoutParams", lpparam.classLoader), 0, 0); 122 | webView_ads.setLayoutParams((ViewGroup.LayoutParams) lp); 123 | } 124 | }); 125 | XposedHelpers.findAndHookMethod("com.picacomic.fregata.adapters.ComicListRecyclerViewAdapter", lpparam.classLoader, "onBindViewHolder", XposedHelpers.findClass("android.support.v7.widget.RecyclerView$ViewHolder", lpparam.classLoader), int.class, new XC_MethodHook() { 126 | @Override 127 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 128 | Object viewHolder = param.args[0]; 129 | if (viewHolder.getClass().getSimpleName().equals("AdvertisementListViewHolder")) { 130 | param.setResult(null); 131 | View itemView = (View) XposedHelpers.getObjectField(viewHolder, "itemView"); 132 | ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) itemView.getLayoutParams(); 133 | // 完全隐藏会影响分页加载的逻辑,所以保留一点, 134 | lp.height = 1; 135 | itemView.setLayoutParams(lp); 136 | } 137 | } 138 | }); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /hook/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 11 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /hook/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /hook/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/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #EC75A1 4 | -------------------------------------------------------------------------------- /hook/src/main/res/values/strings-notran.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | com.picacomic.fregata 5 | 6 | -------------------------------------------------------------------------------- /hook/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | HookPicACG 3 | -------------------------------------------------------------------------------- /hook/src/test/java/cc/aoeiuv020/hookpicacg/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package cc.aoeiuv020.hookpicacg 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 | @Suppress("INTEGER_OPERATOR_RESOLVE_WILL_CHANGE") 16 | assertEquals(4, 2 + 2) 17 | } 18 | } -------------------------------------------------------------------------------- /info.txt: -------------------------------------------------------------------------------- 1 | https://www.picacomic.com/ 2 | https://picacomic.xyz/ 3 | 94d2bc30d22368885183fd7e2e926b5d 2.2.1.3.3.4.apk 4 | Signer #1 certificate DN: CN=RUFF, OU=Pica Comic, O=Pica Comic, L=Pica, ST=Pica, C=Pica 5 | Signer #1 certificate SHA-256 digest: b1e7c5e0ffa816e6243ed4f6135bc369123d8d319d872d05f94004e5af9ce9c6 6 | Signer #1 certificate SHA-1 digest: 8da03c25c18b0f4010f7bd133c033885ea740fdc 7 | Signer #1 certificate MD5 digest: 9f2bb7cf7d04f11e6bd1e10c968d3065 8 | -------------------------------------------------------------------------------- /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' 10 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | maven { url 'https://api.xposed.info/' } 14 | } 15 | } 16 | rootProject.name = "HookPicACG" 17 | include ':hook' 18 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------