├── .gitattributes
├── .gitignore
├── README.md
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── module.gradle
├── module
├── .gitignore
├── build.gradle
├── libs
│ └── fingerprint-pay-qq-magisk.apk
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── cpp
│ ├── CMakeLists.txt
│ ├── log.h
│ └── main.cpp
├── run.sh
├── settings.gradle
└── template
└── magisk_module
├── .gitattributes
├── META-INF
└── com
│ └── google
│ └── android
│ ├── update-binary
│ └── updater-script
├── README.md
├── customize.sh
├── post-fs-data.sh
├── riru.sh
├── uninstall.sh
└── verify.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.prop text eol=lf
2 | *.sh text eol=lf
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | /.idea/caches/build_file_checksums.ser
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | .DS_Store
10 | /build
11 | /captures
12 | /out
13 | .externalNativeBuild
14 | elf-cleaner.sh
15 | settings.gradle
16 | .cxx
17 | module.gradle
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | move to https://github.com/eritpchy/FingerprintPay
2 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'idea'
2 |
3 | idea.module {
4 | excludeDirs += file('out')
5 | resourceDirs += file('template')
6 | resourceDirs += file('scripts')
7 | }
8 |
9 | buildscript {
10 | repositories {
11 | google()
12 | jcenter()
13 | }
14 | dependencies {
15 | classpath 'com.android.tools.build:gradle:4.1.1'
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
30 | ext {
31 | minSdkVersion = 23
32 | targetSdkVersion = 30
33 | }
34 |
--------------------------------------------------------------------------------
/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=-Xmx1536m
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 | # https://github.com/google/prefab/issues/122
21 | android.prefabVersion=1.1.2
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eritpchy/Fingerprint-pay-magisk-qq/8d8a698f5d03e99cefddc947793579ec79dd3946/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Oct 09 23:12:33 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/module.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 |
3 | moduleId = "module_xfingerprint_pay_qq"
4 | moduleName = "指纹支付 - QQ"
5 | moduleAuthor = "Jason Eric"
6 | moduleDescription = "让QQ支持指纹支付 Fingerprint pay for QQ."
7 | moduleVersion = "v3.9.22"
8 | moduleVersionCode = 2
9 |
10 | moduleMinRiruApiVersion = 9
11 | moduleMinRiruVersionName = "v22.0"
12 | moduleMaxRiruApiVersion = 10
13 |
14 | moduleProp = [
15 | name : moduleName,
16 | version : moduleVersion,
17 | versionCode: moduleVersionCode.toString(),
18 | author : moduleAuthor,
19 | description: moduleDescription,
20 | minApi : moduleMinRiruApiVersion
21 | ]
22 |
23 | magiskModuleProp = [
24 | id : "riru-${moduleId.replace('_', '-')}",
25 | name : "Riru - ${moduleProp['name']}",
26 | version : moduleProp['version'],
27 | versionCode: moduleProp['versionCode'],
28 | author : moduleProp['author'],
29 | description: moduleProp['description']
30 | ]
31 | }
--------------------------------------------------------------------------------
/module/.gitignore:
--------------------------------------------------------------------------------
1 | /.externalNativeBuild
2 | /build
3 | /release
--------------------------------------------------------------------------------
/module/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply from: file(rootProject.file('module.gradle'))
3 |
4 | android {
5 | compileSdkVersion rootProject.ext.targetSdkVersion
6 | defaultConfig {
7 | minSdkVersion rootProject.ext.minSdkVersion
8 | targetSdkVersion rootProject.ext.targetSdkVersion
9 | externalNativeBuild {
10 | cmake {
11 | arguments "-DMODULE_NAME:STRING=riru_$moduleId",
12 | "-DRIRU_MODULE_API_VERSION=$moduleMaxRiruApiVersion",
13 | "-DRIRU_MODULE_VERSION=$moduleVersionCode",
14 | "-DRIRU_MODULE_VERSION_NAME:STRING=\"$moduleVersion\""
15 |
16 | }
17 | }
18 | }
19 | buildFeatures {
20 | prefab true
21 | }
22 | externalNativeBuild {
23 | cmake {
24 | path "src/main/cpp/CMakeLists.txt"
25 | version "3.10.2"
26 | }
27 | }
28 | }
29 |
30 | repositories {
31 | mavenLocal()
32 | jcenter()
33 | maven { url 'https://dl.bintray.com/rikkaw/Libraries' }
34 | }
35 |
36 | dependencies {
37 | implementation 'rikka.ndk:riru:10'
38 | }
39 |
40 | def outDir = file("$rootDir/out")
41 | def magiskDir = file("$outDir/magisk_module")
42 | def zipName = "${magiskModuleProp['id'].replace('_', '-')}-${magiskModuleProp['version']}.zip"
43 | def riruDir = "$magiskDir/riru"
44 |
45 |
46 | import org.apache.tools.ant.filters.FixCrLfFilter
47 |
48 | import java.nio.file.Files
49 | import java.security.MessageDigest
50 |
51 | static def calcSha256(file) {
52 | def md = MessageDigest.getInstance("SHA-256")
53 | file.eachByte 4096, { bytes, size ->
54 | md.update(bytes, 0, size);
55 | }
56 | return md.digest().encodeHex()
57 | }
58 |
59 | static def renameOrFail(File from, File to) {
60 | if (!from.renameTo(to)) {
61 | throw new IOException("Unable reanme file $from to $to")
62 | }
63 | }
64 |
65 | android.libraryVariants.all { variant ->
66 | def task = variant.assembleProvider.get()
67 | task.doLast {
68 | // clear
69 | delete { delete magiskDir }
70 |
71 | // copy from template
72 | copy {
73 | from "$rootDir/template/magisk_module"
74 | into magiskDir.path
75 | exclude 'riru.sh'
76 | }
77 | // copy riru.sh
78 | copy {
79 | from "$rootDir/template/magisk_module"
80 | into magiskDir.path
81 | include 'riru.sh'
82 | filter { line ->
83 | line.replaceAll('%%%RIRU_MODULE_ID%%%', moduleId)
84 | .replaceAll('%%%RIRU_MIN_API_VERSION%%%', moduleMinRiruApiVersion.toString())
85 | .replaceAll('%%%RIRU_MIN_VERSION_NAME%%%', moduleMinRiruVersionName)
86 | }
87 | filter(FixCrLfFilter.class,
88 | eol: FixCrLfFilter.CrLf.newInstance("lf"))
89 | }
90 | // copy .git files manually since gradle exclude it by default
91 | Files.copy(file("$rootDir/template/magisk_module/.gitattributes").toPath(), file("${magiskDir.path}/.gitattributes").toPath())
92 |
93 | // generate module.prop
94 | def modulePropText = ""
95 | magiskModuleProp.each { k, v -> modulePropText += "$k=$v\n" }
96 | modulePropText = modulePropText.trim()
97 | file("$magiskDir/module.prop").text = modulePropText
98 |
99 | // generate module.prop for Riru
100 | def riruModulePropText = ""
101 | moduleProp.each { k, v -> riruModulePropText += "$k=$v\n" }
102 | riruModulePropText = riruModulePropText.trim()
103 | file(riruDir).mkdirs()
104 |
105 | // module.prop.new will be renamed to module.prop in post-fs-data.sh
106 | file("$riruDir/module.prop.new").text = riruModulePropText
107 |
108 | // copy native files
109 | def nativeOutDir = file("build/intermediates/cmake/$variant.name/obj")
110 |
111 | file("$magiskDir/system").mkdirs()
112 | file("$magiskDir/system_x86").mkdirs()
113 | renameOrFail(file("$nativeOutDir/arm64-v8a"), file("$magiskDir/system/lib64"))
114 | renameOrFail(file("$nativeOutDir/armeabi-v7a"), file("$magiskDir/system/lib"))
115 | renameOrFail(file("$nativeOutDir/x86_64"), file("$magiskDir/system_x86/lib64"))
116 | renameOrFail(file("$nativeOutDir/x86"), file("$magiskDir/system_x86/lib"))
117 |
118 | file("$magiskDir/system/framework").mkdirs()
119 | copy {
120 | from zipTree('libs/fingerprint-pay-qq-magisk.apk')
121 | rename('classes.dex', 'libriru_module_xfingerprint_pay_qq.dex')
122 | into file("$magiskDir/system/framework")
123 | include 'classes.dex'
124 | }
125 |
126 | // generate sha1sum
127 | fileTree("$magiskDir").matching {
128 | exclude "README.md", "META-INF"
129 | }.visit { f ->
130 | if (f.directory) return
131 | file(f.file.path + ".sha256sum").text = calcSha256(f.file)
132 | }
133 | }
134 | task.finalizedBy zipMagiskMoudle
135 | }
136 |
137 | task zipMagiskMoudle(type: Zip) {
138 | from magiskDir
139 | archiveName zipName
140 | destinationDir outDir
141 | }
--------------------------------------------------------------------------------
/module/libs/fingerprint-pay-qq-magisk.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eritpchy/Fingerprint-pay-magisk-qq/8d8a698f5d03e99cefddc947793579ec79dd3946/module/libs/fingerprint-pay-qq-magisk.apk
--------------------------------------------------------------------------------
/module/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/module/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | if (NOT DEFINED MODULE_NAME)
4 | message(FATAL_ERROR "MODULE_NAME is not set")
5 | endif ()
6 |
7 | add_definitions(-DRIRU_MODULE)
8 | add_definitions(-DRIRU_MODULE_API_VERSION=${RIRU_MODULE_API_VERSION})
9 | add_definitions(-DRIRU_MODULE_VERSION=${RIRU_MODULE_VERSION})
10 | add_definitions(-DRIRU_MODULE_VERSION_NAME=${RIRU_MODULE_VERSION_NAME})
11 |
12 | message("Build type: ${CMAKE_BUILD_TYPE}")
13 |
14 | set(CMAKE_CXX_STANDARD 11)
15 |
16 | set(LINKER_FLAGS "-ffixed-x18 -Wl,--hash-style=both")
17 | set(C_FLAGS "-Werror=format -fdata-sections -ffunction-sections")
18 |
19 | if (CMAKE_BUILD_TYPE STREQUAL "Release")
20 | set(C_FLAGS "${C_FLAGS} -O2 -fvisibility=hidden -fvisibility-inlines-hidden")
21 | set(LINKER_FLAGS "${LINKER_FLAGS} -Wl,-exclude-libs,ALL -Wl,--gc-sections")
22 | else ()
23 | set(C_FLAGS "${C_FLAGS} -O0")
24 | endif ()
25 |
26 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_FLAGS}")
27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS}")
28 |
29 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}")
30 | set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LINKER_FLAGS}")
31 |
32 | find_package(riru REQUIRED CONFIG)
33 |
34 | add_library(${MODULE_NAME} SHARED main.cpp)
35 | target_link_libraries(${MODULE_NAME} log riru::riru)
36 | set_target_properties(${MODULE_NAME} PROPERTIES LINK_FLAGS_RELEASE -s)
37 |
--------------------------------------------------------------------------------
/module/src/main/cpp/log.h:
--------------------------------------------------------------------------------
1 | #ifndef _LOGGING_H
2 | #define _LOGGING_H
3 |
4 | #include
5 | #include
6 |
7 | #ifndef LOG_TAG
8 | #define LOG_TAG "XFINGERPRINT"
9 | #endif
10 |
11 |
12 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
13 | #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
14 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
15 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
16 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
17 | #define PLOGE(fmt, args...) LOGE(fmt " failed with %d: %s", ##args, errno, strerror(errno))
18 |
19 | #endif // _LOGGING_H
--------------------------------------------------------------------------------
/module/src/main/cpp/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include "log.h"
11 |
12 | static bool sHookEnable = false;
13 | static char *sAppDataDir = NULL;
14 | static char *sNiceName = NULL;
15 |
16 | static char *jstringToC(JNIEnv * env, jstring jstr){
17 | char *ret = NULL;
18 | if (jstr) {
19 | const char* str = env->GetStringUTFChars(jstr, NULL);
20 | if (str != NULL) {
21 | int len = strlen(str);
22 | ret = (char*) malloc((len + 1) * sizeof(char));
23 | if (ret != NULL){
24 | memset(ret, 0, len + 1);
25 | memcpy(ret, str, len);
26 | }
27 | env->ReleaseStringUTFChars(jstr, str);
28 | }
29 | }
30 | return ret;
31 | }
32 |
33 | static bool equals(const char *str1, const char *str2) {
34 | if (str1 == NULL && str2 == NULL) {
35 | return true;
36 | } else {
37 | if (str1 != NULL && str2 != NULL) {
38 | return strcmp(str1, str2) == 0;
39 | } else {
40 | return false;
41 | }
42 | }
43 | }
44 |
45 |
46 | /** 参数说明:
47 | * jdexPath dex存储路径
48 | * jodexPath 优化后的dex包存放位置
49 | * jclassName 需要调用jar包中的类名
50 | * jmethodName 需要调用的类中的静态方法
51 | */
52 | static void loadDex(JNIEnv *env, jstring jdexPath, jstring jodexPath, jstring jclassName, const char* methodName, jstring jarg1) {
53 |
54 | if (!jdexPath) {
55 | LOGD("MEM ERR");
56 | return;
57 | }
58 |
59 | if (!jodexPath) {
60 | LOGD("MEM ERR");
61 | return;
62 | }
63 |
64 | if (!jclassName) {
65 | LOGD("MEM ERR");
66 | return;
67 | }
68 |
69 | if (!jarg1) {
70 | LOGD("MEM ERR");
71 | return;
72 | }
73 |
74 | jclass classloaderClass = env->FindClass("java/lang/ClassLoader");
75 | jmethodID getsysClassloaderMethod = env->GetStaticMethodID(classloaderClass, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
76 | jobject loader = env->CallStaticObjectMethod(classloaderClass, getsysClassloaderMethod);
77 | jclass dexLoaderClass = env->FindClass("dalvik/system/DexClassLoader");
78 | jmethodID initDexLoaderMethod = env->GetMethodID(dexLoaderClass, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V");
79 | jobject dexLoader = env->NewObject(dexLoaderClass,initDexLoaderMethod, jdexPath, jodexPath, NULL, loader);
80 | jmethodID findclassMethod = env->GetMethodID(dexLoaderClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
81 |
82 | if (findclassMethod == NULL) {
83 | findclassMethod = env->GetMethodID(dexLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
84 | }
85 |
86 | jclass javaClientClass = (jclass)env->CallObjectMethod(dexLoader, findclassMethod, jclassName);
87 | jmethodID targetMethod = env->GetStaticMethodID(javaClientClass, methodName, "(Ljava/lang/String;)V");
88 |
89 | if (targetMethod == NULL) {
90 | LOGD("target method(%s) not found", methodName);
91 | return;
92 | }
93 |
94 | env->CallStaticVoidMethod(javaClientClass, targetMethod, jarg1);
95 | }
96 |
97 | static void pre(JNIEnv *env, jstring *appDataDir, jstring *niceName) {
98 | char *cAppDataDir = jstringToC(env, *appDataDir);
99 | if (cAppDataDir == NULL) {
100 | LOGD("MEM ERR");
101 | return;
102 | }
103 | sAppDataDir = strdup(cAppDataDir);
104 | free(cAppDataDir);
105 | if (sAppDataDir == NULL) {
106 | LOGD("MEM ERR");
107 | return;
108 | }
109 | sNiceName = jstringToC(env, *niceName);
110 | if (sNiceName == NULL) {
111 | LOGD("MEM ERR");
112 | return;
113 | }
114 |
115 | sHookEnable = equals(sNiceName, "com.tencent.mobileqq")
116 | || equals(sNiceName, "com.tencent.mobileqq:tool");
117 | }
118 |
119 | static void post(JNIEnv *env) {
120 | if (sHookEnable) {
121 | char appCacheDir[PATH_MAX] = {0};
122 | snprintf(appCacheDir, PATH_MAX - 1, "%s/cache", sAppDataDir);
123 |
124 | const char *dexPath = "/data/local/tmp/libriru_module_xfingerprint_pay_qq.dex";
125 | if (access(dexPath, 0) != 0) {
126 | dexPath = "/system/framework/libriru_module_xfingerprint_pay_qq.dex";
127 | }
128 | loadDex(env,
129 | env->NewStringUTF(dexPath),
130 | env->NewStringUTF(appCacheDir),
131 | env->NewStringUTF("com.yyxx.wechatfp.xposed.plugin.XposedQQPlugin"),
132 | "main",
133 | env->NewStringUTF(sNiceName)
134 | );
135 | }
136 | }
137 |
138 | static void forkAndSpecializePre(
139 | JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtimeFlags,
140 | jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
141 | jintArray *fdsToClose, jintArray *fdsToIgnore, jboolean *is_child_zygote,
142 | jstring *instructionSet, jstring *appDataDir, jboolean *isTopApp, jobjectArray *pkgDataInfoList,
143 | jobjectArray *whitelistedDataInfoList, jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs) {
144 | pre(env, appDataDir, niceName);
145 | }
146 |
147 | static void forkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
148 | if (res == 0) {
149 | // in app process
150 | post(env);
151 | } else {
152 | // in zygote process, res is child pid
153 | // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
154 | }
155 | }
156 |
157 | static void specializeAppProcessPre(
158 | JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtimeFlags,
159 | jobjectArray *rlimits, jint *mountExternal, jstring *seInfo, jstring *niceName,
160 | jboolean *startChildZygote, jstring *instructionSet, jstring *appDataDir,
161 | jboolean *isTopApp, jobjectArray *pkgDataInfoList, jobjectArray *whitelistedDataInfoList,
162 | jboolean *bindMountAppDataDirs, jboolean *bindMountAppStorageDirs) {
163 | // added from Android 10, but disabled at least in Google Pixel devices
164 | pre(env, appDataDir, niceName);
165 | }
166 |
167 | static void specializeAppProcessPost(
168 | JNIEnv *env, jclass clazz) {
169 | // added from Android 10, but disabled at least in Google Pixel devices
170 | post(env);
171 | }
172 |
173 | static void forkSystemServerPre(
174 | JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, jintArray *gids, jint *runtimeFlags,
175 | jobjectArray *rlimits, jlong *permittedCapabilities, jlong *effectiveCapabilities) {
176 |
177 | }
178 |
179 | static void forkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
180 | if (res == 0) {
181 | // in system server process
182 | } else {
183 | // in zygote process, res is child pid
184 | // don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
185 | }
186 | }
187 |
188 | static int shouldSkipUid(int uid) {
189 | // by default, Riru only call module functions in "normal app processes" (10000 <= uid % 100000 <= 19999)
190 | // false = don't skip
191 | return false;
192 | }
193 |
194 | static void onModuleLoaded() {
195 | // called when the shared library of Riru core is loaded
196 | }
197 |
198 | extern "C" {
199 |
200 | int riru_api_version;
201 | RiruApiV9 *riru_api_v9;
202 |
203 | /*
204 | * Init will be called three times.
205 | *
206 | * The first time:
207 | * Returns the highest version number supported by both Riru and the module.
208 | *
209 | * arg: (int *) Riru's API version
210 | * returns: (int *) the highest possible API version
211 | *
212 | * The second time:
213 | * Returns the RiruModuleX struct created by the module.
214 | * (X is the return of the first call)
215 | *
216 | * arg: (RiruApiVX *) RiruApi strcut, this pointer can be saved for further use
217 | * returns: (RiruModuleX *) RiruModule strcut
218 | *
219 | * The second time:
220 | * Let the module to cleanup (such as RiruModuleX struct created before).
221 | *
222 | * arg: null
223 | * returns: (ignored)
224 | *
225 | */
226 | void *init(void *arg) {
227 | static int step = 0;
228 | step += 1;
229 |
230 | static void *_module;
231 |
232 | switch (step) {
233 | case 1: {
234 | auto core_max_api_version = *(int *) arg;
235 | riru_api_version = core_max_api_version <= RIRU_MODULE_API_VERSION ? core_max_api_version : RIRU_MODULE_API_VERSION;
236 | return &riru_api_version;
237 | }
238 | case 2: {
239 | switch (riru_api_version) {
240 | // RiruApiV10 and RiruModuleInfoV10 are equal to V9
241 | case 10:
242 | case 9: {
243 | riru_api_v9 = (RiruApiV9 *) arg;
244 |
245 | auto module = (RiruModuleInfoV9 *) malloc(sizeof(RiruModuleInfoV9));
246 | memset(module, 0, sizeof(RiruModuleInfoV9));
247 | _module = module;
248 |
249 | module->supportHide = true;
250 |
251 | module->version = RIRU_MODULE_VERSION;
252 | module->versionName = RIRU_MODULE_VERSION_NAME;
253 | module->onModuleLoaded = onModuleLoaded;
254 | module->shouldSkipUid = shouldSkipUid;
255 | module->forkAndSpecializePre = forkAndSpecializePre;
256 | module->forkAndSpecializePost = forkAndSpecializePost;
257 | module->specializeAppProcessPre = specializeAppProcessPre;
258 | module->specializeAppProcessPost = specializeAppProcessPost;
259 | module->forkSystemServerPre = forkSystemServerPre;
260 | module->forkSystemServerPost = forkSystemServerPost;
261 | return module;
262 | }
263 | default: {
264 | return nullptr;
265 | }
266 | }
267 | }
268 | case 3: {
269 | free(_module);
270 | return nullptr;
271 | }
272 | default: {
273 | return nullptr;
274 | }
275 | }
276 | }
277 | }
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 | cd ${0%/*}
4 | ./gradlew clean
5 | ./gradlew :module:assembleRelease
6 | adb shell rm -f "/data/local/tmp/libriru_module_xfingerprint_pay_qq.dex"
7 | adb push ./out/*.zip /sdcard/Download/
8 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':module'
2 |
--------------------------------------------------------------------------------
/template/magisk_module/.gitattributes:
--------------------------------------------------------------------------------
1 | # Declare files that will always have LF line endings on checkout.
2 | META-INF/** text eol=lf
3 | *.prop text eol=lf
4 | *.sh text eol=lf
5 | *.md text eol=lf
6 | sepolicy.rule text eol=lf
7 |
8 | # Denote all files that are truly binary and should not be modified.
9 | system/** binary
10 | system_x86/** binary
--------------------------------------------------------------------------------
/template/magisk_module/META-INF/com/google/android/update-binary:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 |
3 | #################
4 | # Initialization
5 | #################
6 |
7 | umask 022
8 |
9 | # Global vars
10 | TMPDIR=/dev/tmp
11 | PERSISTDIR=/sbin/.magisk/mirror/persist
12 |
13 | rm -rf $TMPDIR 2>/dev/null
14 | mkdir -p $TMPDIR
15 |
16 | # echo before loading util_functions
17 | ui_print() { echo "$1"; }
18 |
19 | require_new_magisk() {
20 | ui_print "*******************************"
21 | ui_print " Please install Magisk v19.0+! "
22 | ui_print "*******************************"
23 | exit 1
24 | }
25 |
26 | is_legacy_script() {
27 | unzip -l "$ZIPFILE" install.sh | grep -q install.sh
28 | return $?
29 | }
30 |
31 | print_modname() {
32 | local len
33 | len=`echo -n $MODNAME | wc -c`
34 | len=$((len + 2))
35 | local pounds=`printf "%${len}s" | tr ' ' '*'`
36 | ui_print "$pounds"
37 | ui_print " $MODNAME "
38 | ui_print "$pounds"
39 | ui_print "*******************"
40 | ui_print " Powered by Magisk "
41 | ui_print "*******************"
42 | }
43 |
44 | ##############
45 | # Environment
46 | ##############
47 |
48 | OUTFD=$2
49 | ZIPFILE=$3
50 |
51 | mount /data 2>/dev/null
52 |
53 | # Load utility functions
54 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk
55 | . /data/adb/magisk/util_functions.sh
56 | [ $MAGISK_VER_CODE -gt 18100 ] || require_new_magisk
57 |
58 | # Preperation for flashable zips
59 | setup_flashable
60 |
61 | # Mount partitions
62 | mount_partitions
63 |
64 | # Detect version and architecture
65 | api_level_arch_detect
66 |
67 | # Setup busybox and binaries
68 | $BOOTMODE && boot_actions || recovery_actions
69 |
70 | ##############
71 | # Preparation
72 | ##############
73 |
74 | # Extract prop file
75 | unzip -o "$ZIPFILE" module.prop -d $TMPDIR >&2
76 | [ ! -f $TMPDIR/module.prop ] && abort "! Unable to extract zip file!"
77 |
78 | $BOOTMODE && MODDIRNAME=modules_update || MODDIRNAME=modules
79 | MODULEROOT=$NVBASE/$MODDIRNAME
80 | MODID=`grep_prop id $TMPDIR/module.prop`
81 | MODPATH=$MODULEROOT/$MODID
82 | MODNAME=`grep_prop name $TMPDIR/module.prop`
83 |
84 | # Create mod paths
85 | rm -rf $MODPATH 2>/dev/null
86 | mkdir -p $MODPATH
87 |
88 | ##########
89 | # Install
90 | ##########
91 |
92 | if is_legacy_script; then
93 | unzip -oj "$ZIPFILE" module.prop install.sh uninstall.sh 'common/*' -d $TMPDIR >&2
94 |
95 | # Load install script
96 | . $TMPDIR/install.sh
97 |
98 | # Callbacks
99 | print_modname
100 | on_install
101 |
102 | # Custom uninstaller
103 | [ -f $TMPDIR/uninstall.sh ] && cp -af $TMPDIR/uninstall.sh $MODPATH/uninstall.sh
104 |
105 | # Skip mount
106 | $SKIPMOUNT && touch $MODPATH/skip_mount
107 |
108 | # prop file
109 | $PROPFILE && cp -af $TMPDIR/system.prop $MODPATH/system.prop
110 |
111 | # Module info
112 | cp -af $TMPDIR/module.prop $MODPATH/module.prop
113 |
114 | # post-fs-data scripts
115 | $POSTFSDATA && cp -af $TMPDIR/post-fs-data.sh $MODPATH/post-fs-data.sh
116 |
117 | # service scripts
118 | $LATESTARTSERVICE && cp -af $TMPDIR/service.sh $MODPATH/service.sh
119 |
120 | ui_print "- Setting permissions"
121 | set_permissions
122 | else
123 | print_modname
124 |
125 | unzip -o "$ZIPFILE" customize.sh -d $MODPATH >&2
126 |
127 | if ! grep -q '^SKIPUNZIP=1$' $MODPATH/customize.sh 2>/dev/null; then
128 | ui_print "- Extracting module files"
129 | unzip -o "$ZIPFILE" -x 'META-INF/*' -d $MODPATH >&2
130 |
131 | # Default permissions
132 | set_perm_recursive $MODPATH 0 0 0755 0644
133 | fi
134 |
135 | # Load customization script
136 | [ -f $MODPATH/customize.sh ] && . $MODPATH/customize.sh
137 | fi
138 |
139 | # Handle replace folders
140 | for TARGET in $REPLACE; do
141 | ui_print "- Replace target: $TARGET"
142 | mktouch $MODPATH$TARGET/.replace
143 | done
144 |
145 | if $BOOTMODE; then
146 | # Update info for Magisk Manager
147 | mktouch $NVBASE/modules/$MODID/update
148 | cp -af $MODPATH/module.prop $NVBASE/modules/$MODID/module.prop
149 | fi
150 |
151 | # Copy over custom sepolicy rules
152 | if [ -f $MODPATH/sepolicy.rule -a -e $PERSISTDIR ]; then
153 | ui_print "- Installing custom sepolicy patch"
154 | PERSISTMOD=$PERSISTDIR/magisk/$MODID
155 | mkdir -p $PERSISTMOD
156 | cp -af $MODPATH/sepolicy.rule $PERSISTMOD/sepolicy.rule
157 | fi
158 |
159 | # Remove stuffs that don't belong to modules
160 | rm -rf \
161 | $MODPATH/system/placeholder $MODPATH/customize.sh \
162 | $MODPATH/README.md $MODPATH/.git* 2>/dev/null
163 |
164 | ##############
165 | # Finalizing
166 | ##############
167 |
168 | cd /
169 | $BOOTMODE || recovery_cleanup
170 | rm -rf $TMPDIR
171 |
172 | ui_print "- Done"
173 | exit 0
--------------------------------------------------------------------------------
/template/magisk_module/META-INF/com/google/android/updater-script:
--------------------------------------------------------------------------------
1 | #MAGISK
2 |
--------------------------------------------------------------------------------
/template/magisk_module/README.md:
--------------------------------------------------------------------------------
1 | # Riru - Template
--------------------------------------------------------------------------------
/template/magisk_module/customize.sh:
--------------------------------------------------------------------------------
1 | SKIPUNZIP=1
2 |
3 | # extract verify.sh
4 | ui_print "- Extracting verify.sh"
5 | unzip -o "$ZIPFILE" 'verify.sh' -d "$TMPDIR" >&2
6 | if [ ! -f "$TMPDIR/verify.sh" ]; then
7 | ui_print "*********************************************************"
8 | ui_print "! Unable to extract verify.sh!"
9 | ui_print "! This zip may be corrupted, please try downloading again"
10 | abort_clean "*********************************************************"
11 | fi
12 | . $TMPDIR/verify.sh
13 |
14 | # extract riru.sh
15 | extract "$ZIPFILE" 'riru.sh' "$MODPATH"
16 | . $MODPATH/riru.sh
17 |
18 | check_riru_version
19 | check_architecture
20 |
21 | # extract libs
22 | ui_print "- Extracting module files"
23 |
24 | extract "$ZIPFILE" 'module.prop' "$MODPATH"
25 | extract "$ZIPFILE" 'post-fs-data.sh' "$MODPATH"
26 | extract "$ZIPFILE" 'uninstall.sh' "$MODPATH"
27 | #extract "$ZIPFILE" 'sepolicy.rule' "$MODPATH"
28 |
29 | if [ "$ARCH" = "x86" ] || [ "$ARCH" = "x64" ]; then
30 | ui_print "- Extracting x86 libraries"
31 | extract "$ZIPFILE" "system_x86/lib/libriru_$RIRU_MODULE_ID.so" "$MODPATH"
32 | mv "$MODPATH/system_x86/lib" "$MODPATH/system/lib"
33 |
34 | if [ "$IS64BIT" = true ]; then
35 | ui_print "- Extracting x64 libraries"
36 | extract "$ZIPFILE" "system_x86/lib64/libriru_$RIRU_MODULE_ID.so" "$MODPATH"
37 | mv "$MODPATH/system_x86/lib64" "$MODPATH/system/lib64"
38 | fi
39 | else
40 | ui_print "- Extracting arm libraries"
41 | extract "$ZIPFILE" "system/lib/libriru_$RIRU_MODULE_ID.so" "$MODPATH"
42 |
43 | if [ "$IS64BIT" = true ]; then
44 | ui_print "- Extracting arm64 libraries"
45 | extract "$ZIPFILE" "system/lib64/libriru_$RIRU_MODULE_ID.so" "$MODPATH"
46 | fi
47 | fi
48 |
49 | ui_print "- Extracting extra libraries"
50 | extract "$ZIPFILE" "system/framework/libriru_$RIRU_MODULE_ID.dex" "$MODPATH"
51 |
52 | set_perm_recursive "$MODPATH" 0 0 0755 0644
53 |
54 | # extract Riru files
55 | ui_print "- Extracting extra files"
56 | [ -d "$RIRU_MODULE_PATH" ] || mkdir -p "$RIRU_MODULE_PATH" || abort "! Can't create $RIRU_MODULE_PATH"
57 |
58 | rm -f "$RIRU_MODULE_PATH/module.prop.new"
59 | extract "$ZIPFILE" 'riru/module.prop.new' "$RIRU_MODULE_PATH" true
60 | cp -f "$RIRU_MODULE_PATH/module.prop.new" "$RIRU_MODULE_PATH/module.prop"
61 | set_perm "$RIRU_MODULE_PATH/module.prop.new" 0 0 0600 $RIRU_SECONTEXT
--------------------------------------------------------------------------------
/template/magisk_module/post-fs-data.sh:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 | MODDIR=${0%/*}
3 | [ ! -f "$MODDIR/riru.sh" ] && exit 1
4 | . $MODDIR/riru.sh
5 |
6 | # Rename module.prop.new
7 | if [ -f "$RIRU_MODULE_PATH/module.prop.new" ]; then
8 | rm "$RIRU_MODULE_PATH/module.prop"
9 | mv "$RIRU_MODULE_PATH/module.prop.new" "$RIRU_MODULE_PATH/module.prop"
10 | fi
--------------------------------------------------------------------------------
/template/magisk_module/riru.sh:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 | RIRU_PATH="/data/adb/riru"
3 | RIRU_MODULE_ID="%%%RIRU_MODULE_ID%%%"
4 | RIRU_MODULE_PATH="$RIRU_PATH/modules/$RIRU_MODULE_ID"
5 | RIRU_SECONTEXT="u:object_r:magisk_file:s0"
6 |
7 | check_riru_version() {
8 | RIRU_MIN_API_VERSION=%%%RIRU_MIN_API_VERSION%%%
9 | RIRU_MIN_VERSION_NAME="%%%RIRU_MIN_VERSION_NAME%%%"
10 |
11 | if [ ! -f "$RIRU_PATH/api_version" ] && [ ! -f "$RIRU_PATH/api_version.new" ]; then
12 | ui_print "*********************************************************"
13 | ui_print "! Riru $RIRU_MIN_VERSION_NAME or above is required"
14 | ui_print "! Please install Riru from Magisk Manager or https://github.com/RikkaApps/Riru/releases"
15 | abort "*********************************************************"
16 | fi
17 | RIRU_API_VERSION=$(cat "$RIRU_PATH/api_version.new") || RIRU_API_VERSION=$(cat "$RIRU_PATH/api_version") || RIRU_API_VERSION=0
18 | [ "$RIRU_API_VERSION" -eq "$RIRU_API_VERSION" ] || RIRU_API_VERSION=0
19 | ui_print "- Riru API version: $RIRU_API_VERSION"
20 | if [ "$RIRU_API_VERSION" -lt $RIRU_MIN_API_VERSION ]; then
21 | ui_print "*********************************************************"
22 | ui_print "! Riru $RIRU_MIN_VERSION_NAME or above is required"
23 | ui_print "! Please upgrade Riru from Magisk Manager or https://github.com/RikkaApps/Riru/releases"
24 | abort "*********************************************************"
25 | fi
26 | }
27 |
28 | check_architecture() {
29 | if [ "$ARCH" != "arm" ] && [ "$ARCH" != "arm64" ] && [ "$ARCH" != "x86" ] && [ "$ARCH" != "x64" ]; then
30 | abort "! Unsupported platform: $ARCH"
31 | else
32 | ui_print "- Device platform: $ARCH"
33 | fi
34 | }
--------------------------------------------------------------------------------
/template/magisk_module/uninstall.sh:
--------------------------------------------------------------------------------
1 | #!/sbin/sh
2 | MODDIR=${0%/*}
3 | [ ! -f "$MODDIR/riru.sh" ] && exit 1
4 | . $MODDIR/riru.sh
5 |
6 | rm -rf "$RIRU_MODULE_PATH"
--------------------------------------------------------------------------------
/template/magisk_module/verify.sh:
--------------------------------------------------------------------------------
1 | TMPDIR_FOR_VERIFY="$TMPDIR/.vunzip"
2 | mkdir "$TMPDIR_FOR_VERIFY"
3 |
4 | abort_verify() {
5 | ui_print "*********************************************************"
6 | ui_print "! $1"
7 | ui_print "! This zip may be corrupted, please try downloading again"
8 | abort "*********************************************************"
9 | }
10 |
11 | # extract
12 | extract() {
13 | zip=$1
14 | file=$2
15 | dir=$3
16 | junk_paths=$4
17 | [ -z "$junk_paths" ] && junk_paths=false
18 | opts="-o"
19 | [ $junk_paths = true ] && opts="-oj"
20 |
21 | file_path=""
22 | hash_path=""
23 | if [ $junk_paths = true ]; then
24 | file_path="$dir/$(basename "$file")"
25 | hash_path="$TMPDIR_FOR_VERIFY/$(basename "$file").sha256sum"
26 | else
27 | file_path="$dir/$file"
28 | hash_path="$TMPDIR_FOR_VERIFY/$file.sha256sum"
29 | fi
30 |
31 | unzip $opts "$zip" "$file" -d "$dir" >&2
32 | [ -f "$file_path" ] || abort_verify "$file not exists"
33 |
34 | unzip $opts "$zip" "$file.sha256sum" -d "$TMPDIR_FOR_VERIFY" >&2
35 | [ -f "$hash_path" ] || abort_verify "$file.sha256sum not exists"
36 |
37 | (echo "$(cat "$hash_path") $file_path" | sha256sum -c -s -) || abort_verify "Failed to verify $file"
38 | ui_print "- Verified $file" >&1
39 | }
--------------------------------------------------------------------------------