Skip to content
This repository was archived by the owner on Sep 17, 2023. It is now read-only.

Commit 0a1b94c

Browse files
committed
feat: Use startup library to initialize some components
1 parent d70466e commit 0a1b94c

File tree

6 files changed

+115
-39
lines changed

6 files changed

+115
-39
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ dependencies {
158158
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
159159
implementation("androidx.viewpager2:viewpager2:1.1.0-beta02")
160160
implementation("androidx.activity:activity-ktx:1.8.0-alpha06")
161+
implementation("androidx.startup:startup-runtime:1.1.1")
161162

162163
val editorVersion = "0.22.0"
163164
//noinspection GradleDependency

app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@
5353
android:resource="@xml/file_paths" />
5454
</provider>
5555

56+
<provider
57+
android:name="androidx.startup.InitializationProvider"
58+
android:authorities="${applicationId}.androidx-startup"
59+
android:exported="false"
60+
tools:node="merge">
61+
<meta-data
62+
android:name="org.cosmicide.rewrite.startup.MainInitializer"
63+
android:value="androidx.startup" />
64+
</provider>
65+
5666
<activity
5767
android:name=".MainActivity"
5868
android:exported="true">

app/src/main/kotlin/org/cosmicide/rewrite/App.kt

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import android.app.Application
1111
import android.app.UiModeManager
1212
import android.content.res.Configuration
1313
import android.os.Build
14-
import android.os.StrictMode
1514
import android.util.Log
1615
import androidx.appcompat.app.AppCompatDelegate
1716
import androidx.recyclerview.widget.LinearLayoutManager
@@ -37,10 +36,13 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifTrue
3736
import org.lsposed.hiddenapibypass.HiddenApiBypass
3837
import rikka.sui.Sui
3938
import java.io.File
39+
import java.io.FileInputStream
4040
import java.io.FileNotFoundException
41+
import java.io.InputStream
4142
import java.lang.ref.WeakReference
43+
import java.math.BigInteger
44+
import java.security.MessageDigest
4245
import java.time.ZonedDateTime
43-
import java.util.concurrent.Executors
4446

4547
class App : Application() {
4648

@@ -62,39 +64,9 @@ class App : Application() {
6264
instance = WeakReference(this)
6365
HookManager.context = WeakReference(this)
6466

65-
val externalStorage = getExternalFilesDir(null)!!
66-
67-
Prefs.init(applicationContext)
68-
FileUtil.init(externalStorage)
69-
7067
setupHooks()
7168
loadPlugins()
7269

73-
if (BuildConfig.DEBUG) {
74-
StrictMode.setVmPolicy(
75-
StrictMode.VmPolicy.Builder().apply {
76-
detectLeakedRegistrationObjects()
77-
detectActivityLeaks()
78-
detectContentUriWithoutPermission()
79-
detectFileUriExposure()
80-
detectCleartextNetwork()
81-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
82-
penaltyLog()
83-
return@apply
84-
}
85-
permitNonSdkApiUsage()
86-
penaltyListener(Executors.newSingleThreadExecutor()) { violation ->
87-
Log.e("StrictMode", "VM violation", violation)
88-
violation.printStackTrace()
89-
}
90-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
91-
detectIncorrectContextUse()
92-
detectUnsafeIntentLaunch()
93-
}
94-
}.build()
95-
)
96-
}
97-
9870
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
9971
HiddenApiBypass.addHiddenApiExemptions("L")
10072
}
@@ -142,9 +114,6 @@ class App : Application() {
142114
* Extracts kotlin stdlib and stdlib-common from assets.
143115
*/
144116
fun extractFiles() {
145-
FileUtil.classpathDir.resolve("kotlin-stdlib-1.8.0.jar").apply {
146-
if (exists()) delete()
147-
}
148117
extractAsset(
149118
"kotlin-stdlib-1.9.0.jar",
150119
FileUtil.classpathDir.resolve("kotlin-stdlib-1.9.0.jar")
@@ -156,7 +125,10 @@ class App : Application() {
156125
}
157126

158127
fun extractAsset(assetName: String, targetFile: File) {
159-
targetFile.exists().ifTrue { return }
128+
if (targetFile.exists() && assetNeedsUpdate(assetName, targetFile)) {
129+
targetFile.delete()
130+
}
131+
160132
try {
161133
assets.open(assetName).use { inputStream ->
162134
targetFile.outputStream().use { outputStream ->
@@ -168,6 +140,25 @@ class App : Application() {
168140
}
169141
}
170142

143+
fun assetNeedsUpdate(assetName: String, targetFile: File): Boolean {
144+
val assetInputStream = assets.open(assetName)
145+
val targetFileInputStream = FileInputStream(targetFile)
146+
val assetChecksum = calculateChecksum(assetInputStream)
147+
val targetFileChecksum = calculateChecksum(targetFileInputStream)
148+
return assetChecksum != targetFileChecksum
149+
}
150+
151+
fun calculateChecksum(inputStream: InputStream): String {
152+
val md = MessageDigest.getInstance("SHA-256")
153+
val buffer = ByteArray(8192)
154+
var bytesRead: Int
155+
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
156+
md.update(buffer, 0, bytesRead)
157+
}
158+
val digest = md.digest()
159+
return BigInteger(1, digest).toString(16)
160+
}
161+
171162
fun disableModules() {
172163
JavacConfigProvider.disableModules()
173164
}
@@ -186,7 +177,6 @@ class App : Application() {
186177
}
187178

188179
private fun setupHooks() {
189-
190180
// Some libraries may call System.exit() to exit the app, which crashes the app.
191181
// Currently, only JGit does this.
192182
HookManager.registerHook(object : Hook(
@@ -223,8 +213,6 @@ class App : Application() {
223213
param.result = null
224214
}
225215
})
226-
227-
228216
}
229217

230218
override fun onConfigurationChanged(newConfig: Configuration) {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.cosmicide.rewrite.startup
2+
3+
import android.content.Context
4+
import android.os.Build
5+
import android.os.StrictMode
6+
import android.util.Log
7+
import androidx.startup.Initializer
8+
import org.cosmicide.rewrite.BuildConfig
9+
import java.util.concurrent.Executors
10+
11+
class DebugInitializer : Initializer<Unit> {
12+
13+
override fun create(context: Context) {
14+
if (BuildConfig.DEBUG) {
15+
enableStrictMode()
16+
}
17+
}
18+
19+
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
20+
21+
private fun enableStrictMode() {
22+
StrictMode.setVmPolicy(
23+
StrictMode.VmPolicy.Builder().apply {
24+
detectLeakedRegistrationObjects()
25+
detectActivityLeaks()
26+
detectContentUriWithoutPermission()
27+
detectFileUriExposure()
28+
detectCleartextNetwork()
29+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
30+
penaltyLog()
31+
return@apply
32+
}
33+
permitNonSdkApiUsage()
34+
penaltyListener(Executors.newSingleThreadExecutor()) { violation ->
35+
Log.e("StrictMode", "VM violation", violation)
36+
violation.printStackTrace()
37+
}
38+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
39+
detectIncorrectContextUse()
40+
detectUnsafeIntentLaunch()
41+
}
42+
}.build()
43+
)
44+
}
45+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.cosmicide.rewrite.startup
2+
3+
import android.content.Context
4+
import androidx.startup.Initializer
5+
6+
class MainInitializer : Initializer<Unit> {
7+
8+
override fun create(context: Context) {}
9+
10+
override fun dependencies(): List<Class<out Initializer<*>>> {
11+
return listOf(
12+
DebugInitializer::class.java,
13+
PreferencesInitializer::class.java
14+
)
15+
}
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.cosmicide.rewrite.startup
2+
3+
import android.content.Context
4+
import androidx.startup.Initializer
5+
import org.cosmicide.rewrite.common.Prefs
6+
import org.cosmicide.rewrite.util.FileUtil
7+
8+
class PreferencesInitializer : Initializer<Unit> {
9+
10+
override fun create(context: Context) {
11+
FileUtil.init(context.getExternalFilesDir(null)!!)
12+
Prefs.init(context.applicationContext)
13+
}
14+
15+
override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
16+
}

0 commit comments

Comments
 (0)