· 8 years ago · Jan 25, 2018, 12:26 PM
1import groovy.io.FileType
2
3import javax.crypto.Cipher
4import javax.crypto.SecretKey
5import javax.crypto.spec.IvParameterSpec
6import javax.crypto.spec.SecretKeySpec
7
8apply plugin: 'com.android.application'
9apply plugin: 'kotlin-android'
10
11ext {
12 // Whether the theme assets should be encrypted or not,
13 // this makes it harder for pirates and kangers! (DEFAULT: true)
14 SHOULD_ENCRYPT_ASSETS = true
15
16 // Whether this theme supports third party theme systems, we will not be able to help you debug
17 // your themes on external theming systems, so the team will NOT respond to external systems if
18 // there are issues with your theme (DEFAULT: false)
19 SUPPORTS_THIRD_PARTY_SYSTEMS = true
20
21 // Encryption values, do not touch as we generate a random key every time you compile!
22 byte[] key = new byte[16]
23 new Random().nextBytes(key)
24 KEY = key
25 byte[] iv = new byte[16]
26 new Random().nextBytes(iv)
27 IV_KEY = iv
28}
29
30android {
31 compileSdkVersion 26
32 buildToolsVersion '27.0.1'
33
34 defaultConfig {
35 applicationId "aliceteam.theme.twilight.night"
36 minSdkVersion 24
37 targetSdkVersion 26
38 versionCode 3
39 versionName "0.3"
40
41 // Themers: Do not touch this, they will only formulate integrity structure of the core
42 // template
43 buildConfigField "boolean", "SUPPORTS_THIRD_PARTY_THEME_SYSTEMS", "" +
44 SUPPORTS_THIRD_PARTY_SYSTEMS
45 resValue "bool", "SUPPORTS_THIRD_PARTY_THEME_SYSTEMS", "" + SUPPORTS_THIRD_PARTY_SYSTEMS
46 resValue "string", "encryption_status", (shouldEncrypt() ? "onCompileVerify" : "false")
47
48 ndk {
49 moduleName "LoadingProcess"
50 }
51 }
52 buildTypes {
53 debug {
54 minifyEnabled false
55 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
56 }
57 release {
58 // When you compile an APK as release, your resources and IV keys will be safeguarded
59 minifyEnabled true
60 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
61 }
62 }
63 sourceSets {
64 main.java.srcDirs += 'src/main/kotlin'
65 }
66 externalNativeBuild {
67 ndkBuild {
68 path 'src/main/jni/Android.mk'
69 }
70 }
71}
72
73dependencies {
74 compile fileTree(include: ['*.jar'], dir: 'libs')
75 compile 'com.github.javiersantos:PiracyChecker:1.1'
76 compile("org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version") {
77 transitive = true
78 }
79 compile 'com.android.support:design:26.1.0'
80}
81
82// Themers, do not touch this! This is our function to help us encrypt your assets!
83task encryptAssets {
84 if (!shouldEncrypt()) {
85 println("Skipping assets encryption...")
86 return
87 }
88
89 def tempAssets = new File(getProjectDir(), "/src/main/assets-temp")
90 if (!tempAssets.exists()) {
91 println("Encrypting duplicated assets, don't worry, your original assets are safe...")
92 def list = []
93 def dir = new File(getProjectDir(), "/src/main/assets")
94 dir.eachFileRecurse(FileType.FILES) { file ->
95 list << file
96
97 FileInputStream fis = new FileInputStream(file)
98 File fo = new File(file.getAbsolutePath().replace("assets", "assets-temp"))
99 fo.getParentFile().mkdirs()
100 FileOutputStream fos = new FileOutputStream(fo)
101 byte[] buffer = new byte[4096]
102 int n
103 while ((n = fis.read(buffer)) != -1) {
104 fos.write(buffer, 0, n)
105 }
106 fis.close()
107 fos.close()
108 }
109
110 list.each {
111 if (it.getAbsolutePath().contains("overlays")) {
112 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
113 SecretKey secret = new SecretKeySpec(KEY, "AES")
114 IvParameterSpec iv = new IvParameterSpec(IV_KEY)
115
116 cipher.init(Cipher.ENCRYPT_MODE, secret, iv)
117 FileInputStream fis = new FileInputStream(it)
118 FileOutputStream fos = new FileOutputStream(it.getAbsolutePath() + ".enc")
119
120 byte[] input = new byte[64]
121 int bytesRead
122 while ((bytesRead = fis.read(input)) != -1) {
123 byte[] output = cipher.update(input, 0, bytesRead)
124 if (output != null) {
125 fos.write(output)
126 }
127 }
128 byte[] output = cipher.doFinal()
129 if (output != null) {
130 fos.write(output)
131 }
132 fis.close()
133 fos.flush()
134 fos.close()
135
136 it.delete()
137 }
138 }
139 } else {
140 throw new RuntimeException("Old temporary assets found! Try and do a clean project.")
141 }
142}
143
144task generateType3 {
145 doFirst {
146 if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
147 println("Running type3 generation script on Linux")
148 def script = "generate_type3/gen.sh".execute()
149 script.in.eachLine { line -> println "type3-gen: " + line }
150 script.err.eachLine { line -> println "type3-gen: ERROR: " + line }
151 script.waitFor()
152 } else {
153 println("Skipping type3 generation: not using a supported operating system")
154 }
155 }
156}
157
158task writeKeys {
159 def KEY_READY = String.valueOf("\"" + KEY + "\"")
160 .replace("\"", "")
161 .replace("[", "{")
162 .replace("]", "}")
163 def IV_KEY_READY = String.valueOf("\"" + IV_KEY + "\"")
164 .replace("\"", "")
165 .replace("[", "{")
166 .replace("]", "}")
167
168 def headerFile = new File(getProjectDir(), "src/main/jni/LoadingProcess.h")
169 headerFile.createNewFile()
170 headerFile.text = """
171#include <jni.h>
172
173jbyte DECRYPTION_KEY[] = ${KEY_READY};
174jbyte IV_KEY[] = ${IV_KEY_READY};
175"""
176}
177
178project.afterEvaluate {
179 android.applicationVariants.all { variant ->
180 variant.javaCompiler.dependsOn(generateType3)
181 }
182 preBuild.dependsOn encryptAssets
183}
184
185gradle.buildFinished {
186 def tempAssets = new File(getProjectDir(), "/src/main/assets-temp")
187 if (tempAssets.exists()) {
188 println("Cleaning duplicated encrypted assets, not your decrypted assets...")
189 def encryptedAssets = new File(getProjectDir(), "src/main/assets")
190 encryptedAssets.deleteDir()
191
192 tempAssets.eachFileRecurse(FileType.FILES) { file ->
193 FileInputStream fis = new FileInputStream(file)
194 File fo = new File(file.getAbsolutePath().replace("assets-temp", "assets"))
195 fo.getParentFile().mkdirs()
196 FileOutputStream fos = new FileOutputStream(fo)
197 byte[] buffer = new byte[4096]
198 int n
199 while ((n = fis.read(buffer)) != -1) {
200 fos.write(buffer, 0, n)
201 }
202 fis.close()
203 fos.close()
204 }
205 tempAssets.deleteDir()
206 }
207}
208
209boolean shouldEncrypt() {
210 ArrayList<String> tasks = project.gradle.startParameter.taskNames
211 return SHOULD_ENCRYPT_ASSETS && Arrays.toString(tasks).toLowerCase().contains("release")
212}
213
214repositories {
215 mavenCentral()
216 google()
217}