1+ import org.gradle.api.tasks.Exec
2+ import org.gradle.api.tasks.bundling.Zip
3+ import com.android.build.api.variant.ApplicationAndroidComponentsExtension
4+
15plugins {
26 alias(libs.plugins.android.application)
37}
@@ -9,9 +13,15 @@ android {
913 buildToolsVersion = " 36.0.0"
1014
1115 buildFeatures {
16+ buildConfig = true
1217 prefab = true
1318 }
1419
20+ externalNativeBuild.cmake {
21+ path(" src/CMakeLists.txt" )
22+ buildStagingDirectory = layout.buildDirectory.get().asFile
23+ }
24+
1525 packaging {
1626 jniLibs {
1727 excludes + = " **/libdobby.so"
@@ -27,50 +37,56 @@ android {
2737 targetSdk = 35
2838 versionCode = 19100
2939 versionName = " v19.1"
30- multiDexEnabled = false
3140
3241 externalNativeBuild {
3342 cmake {
3443 abiFilters(
3544 " arm64-v8a" ,
3645 " armeabi-v7a"
3746 )
38-
3947 arguments(
40- " -DCMAKE_BUILD_TYPE=Release" ,
4148 " -DANDROID_STL=none" ,
42- " -DCMAKE_BUILD_PARALLEL_LEVEL=${Runtime .getRuntime().availableProcessors()} " ,
43- " -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" ,
4449 " -DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
4550 )
46-
4751 val commonFlags = setOf (
48- " -fno-exceptions" ,
49- " -fno-rtti" ,
50- " -fvisibility=hidden" ,
51- " -fvisibility-inlines-hidden" ,
52- " -ffunction-sections" ,
53- " -fdata-sections" ,
54- " -w"
52+ " -fno-exceptions" , " -fno-rtti" , " -fvisibility=hidden" ,
53+ " -fvisibility-inlines-hidden" , " -ffunction-sections" ,
54+ " -fdata-sections" , " -w"
5555 )
56-
5756 cFlags + = " -std=c23"
5857 cFlags + = commonFlags
59-
6058 cppFlags + = " -std=c++26"
6159 cppFlags + = commonFlags
6260 }
6361 }
6462 }
6563
6664 buildTypes {
67- release {
65+ getByName( " release" ) {
6866 isMinifyEnabled = true
6967 isShrinkResources = true
7068 multiDexEnabled = false
7169 proguardFiles(
7270 getDefaultProguardFile(" proguard-android-optimize.txt" ), " proguard-rules.pro"
7371 )
72+ externalNativeBuild {
73+ cmake {
74+ arguments(
75+ " -DCMAKE_BUILD_TYPE=Release" ,
76+ " -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" ,
77+ " -DCMAKE_CXX_FLAGS_RELEASE=-DNDEBUG" ,
78+ " -DCMAKE_C_FLAGS_RELEASE=-DNDEBUG" ,
79+ )
80+ }
81+ }
82+ }
83+ getByName(" debug" ) {
84+ multiDexEnabled = false
85+ externalNativeBuild {
86+ cmake {
87+ arguments(" -DCMAKE_BUILD_TYPE=Debug" )
88+ }
89+ }
7490 }
7591 }
7692
@@ -96,47 +112,90 @@ tasks.register("updateModuleProp") {
96112 doLast {
97113 val versionName = project.android.defaultConfig.versionName
98114 val versionCode = project.android.defaultConfig.versionCode
99-
100115 val modulePropFile = project.rootDir.resolve(" module/module.prop" )
101-
102116 var content = modulePropFile.readText()
103-
104117 content = content.replace(Regex (" version=.*" ), " version=$versionName " )
105118 content = content.replace(Regex (" versionCode=.*" ), " versionCode=$versionCode " )
106-
107119 modulePropFile.writeText(content)
108120 }
109121}
110122
111- tasks.register(" copyFiles" ) {
112- dependsOn(" updateModuleProp" )
123+ androidComponents.onVariants { variant ->
124+ val variantNameCapped = variant.name.replaceFirstChar { it.uppercase() }
125+ val zipFileName = " PlayIntegrityFix_${project.android.defaultConfig.versionName} -${variant.name} .zip"
126+ val zipFile = project.layout.buildDirectory.file(" outputs/zips/$zipFileName " ).get().asFile
127+
128+ val copyTask = tasks.register(" copyModuleFilesFor$variantNameCapped " ) {
129+ group = " PIF Packaging"
130+ dependsOn(" updateModuleProp" , " assemble$variantNameCapped " )
131+
132+ doLast {
133+ val moduleFolder = project.rootDir.resolve(" module" )
134+ val buildDir = project.layout.buildDirectory.get().asFile
135+ val dexPath = if (variant.isMinifyEnabled) {
136+ " intermediates/dex/${variant.name} /minify${variantNameCapped} WithR8/classes.dex"
137+ } else {
138+ " intermediates/dex/${variant.name} /mergeDex${variantNameCapped} /classes.dex"
139+ }
140+ val soPath = " intermediates/stripped_native_libs/${variant.name} /strip${variantNameCapped} DebugSymbols/out/lib"
141+ buildDir.resolve(dexPath).copyTo(moduleFolder.resolve(" classes.dex" ), overwrite = true )
142+ buildDir.resolve(soPath).walk().filter { it.isFile && it.extension == " so" }.forEach { soFile ->
143+ soFile.copyTo(moduleFolder.resolve(" zygisk/${soFile.parentFile.name} .so" ), overwrite = true )
144+ }
145+ }
146+ }
113147
114- doLast {
115- val moduleFolder = project.rootDir.resolve(" module" )
116- val dexFile =
117- project.layout.buildDirectory.get().asFile.resolve(" intermediates/dex/release/minifyReleaseWithR8/classes.dex" )
118- val soDir =
119- project.layout.buildDirectory.get().asFile.resolve(" intermediates/stripped_native_libs/release/stripReleaseDebugSymbols/out/lib" )
120-
121- dexFile.copyTo(moduleFolder.resolve(" classes.dex" ), overwrite = true )
122-
123- soDir.walk().filter { it.isFile && it.extension == " so" }.forEach { soFile ->
124- val abiFolder = soFile.parentFile.name
125- val destination = moduleFolder.resolve(" zygisk/$abiFolder .so" )
126- soFile.copyTo(destination, overwrite = true )
148+ val zipTask = tasks.register<Zip >(" zip$variantNameCapped " ) {
149+ group = " PIF Packaging"
150+ dependsOn(copyTask)
151+ archiveFileName.set(zipFileName)
152+ destinationDirectory.set(project.layout.buildDirectory.dir(" outputs/zips" ).get().asFile)
153+ from(project.rootDir.resolve(" module" ))
154+ }
155+
156+ val pushTask = tasks.register<Exec >(" push$variantNameCapped " ) {
157+ group = " PIF Install"
158+ dependsOn(zipTask)
159+ commandLine(" adb" , " push" , zipFile.absolutePath, " /data/local/tmp" )
160+ }
161+
162+ val installMagiskTask = tasks.register<Exec >(" installMagisk$variantNameCapped " ) {
163+ group = " PIF Install"
164+ dependsOn(pushTask)
165+ commandLine(" adb" , " shell" , " su" , " -c" , " magisk --install-module /data/local/tmp/$zipFileName " )
166+ }
167+
168+ val installKsuTask = tasks.register(" installKsu$variantNameCapped " ) {
169+ group = " PIF Install"
170+ dependsOn(pushTask)
171+ doLast {
172+ exec { commandLine(" adb" , " shell" , " su" , " -c" , " ksud module install /data/local/tmp/$zipFileName " ) }
127173 }
128174 }
129- }
130175
131- tasks.register<Zip >(" zip" ) {
132- dependsOn(" copyFiles" )
176+ val installApatchTask = tasks.register(" installApatch$variantNameCapped " ) {
177+ group = " PIF Install"
178+ dependsOn(pushTask)
179+ doLast {
180+ exec { commandLine(" adb" , " shell" , " su" , " -c" , " apd module install /data/local/tmp/$zipFileName " ) }
181+ }
182+ }
133183
134- archiveFileName.set(" PlayIntegrityFix_${project.android.defaultConfig.versionName} .zip" )
135- destinationDirectory.set(project.rootDir.resolve(" out" ))
184+ tasks.register<Exec >(" installMagiskAndReboot$variantNameCapped " ) {
185+ group = " PIF Install & Reboot"
186+ dependsOn(installMagiskTask)
187+ commandLine(" adb" , " reboot" )
188+ }
136189
137- from(project.rootDir.resolve(" module" ))
138- }
190+ tasks.register<Exec >(" installKsuAndReboot$variantNameCapped " ) {
191+ group = " PIF Install & Reboot"
192+ dependsOn(installKsuTask)
193+ commandLine(" adb" , " reboot" )
194+ }
139195
140- afterEvaluate {
141- tasks[" assembleRelease" ].finalizedBy(" updateModuleProp" , " copyFiles" , " zip" )
196+ tasks.register<Exec >(" installApatchAndReboot$variantNameCapped " ) {
197+ group = " PIF Install & Reboot"
198+ dependsOn(installApatchTask)
199+ commandLine(" adb" , " reboot" )
200+ }
142201}
0 commit comments