Fix StrictMode disk access violations #30
5 changed files with 23 additions and 11 deletions
|
@ -38,7 +38,9 @@ class MarkdownApplication : Application() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Timber.plant(ErrorReporterTree.create(this))
|
coroutineScope.launch {
|
||||||
|
Timber.plant(ErrorReporterTree.create(this@MarkdownApplication))
|
||||||
|
}
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
ReviewHelper.init(this)
|
ReviewHelper.init(this)
|
||||||
fileHelper = AndroidFileHelper(this)
|
fileHelper = AndroidFileHelper(this)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.wbrawner.simplemarkdown.utility
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.MediaStore
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
@ -34,8 +33,10 @@ interface FileHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidFileHelper(private val context: Context) : FileHelper {
|
class AndroidFileHelper(private val context: Context) : FileHelper {
|
||||||
override val defaultDirectory: File = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
|
override val defaultDirectory: File by lazy {
|
||||||
|
context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)
|
||||||
?: context.filesDir
|
?: context.filesDir
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun open(source: URI): Pair<String, String>? = withContext(Dispatchers.IO) {
|
override suspend fun open(source: URI): Pair<String, String>? = withContext(Dispatchers.IO) {
|
||||||
val uri = source.toString().toUri()
|
val uri = source.toString().toUri()
|
||||||
|
|
|
@ -19,10 +19,17 @@ interface PreferenceHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
class AndroidPreferenceHelper(context: Context, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)): PreferenceHelper {
|
class AndroidPreferenceHelper(context: Context, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.IO)): PreferenceHelper {
|
||||||
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
private val sharedPreferences by lazy {
|
||||||
private val states = Preference.entries.associateWith { MutableStateFlow(get(it)) }
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
}
|
||||||
|
private val states by lazy {
|
||||||
|
val allPrefs: Map<String, Any?> = sharedPreferences.all
|
||||||
|
Preference.entries.associateWith { preference ->
|
||||||
|
MutableStateFlow(allPrefs[preference.key] ?: preference.default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun get(preference: Preference): Any? = sharedPreferences.all[preference.key]?: preference.default
|
override fun get(preference: Preference): Any? = states[preference]?.value
|
||||||
|
|
||||||
override fun set(preference: Preference, value: Any?) {
|
override fun set(preference: Preference, value: Any?) {
|
||||||
sharedPreferences.edit {
|
sharedPreferences.edit {
|
||||||
|
|
|
@ -54,6 +54,7 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(libs.kotlinx.coroutines.core)
|
||||||
implementation(libs.acra.core)
|
implementation(libs.acra.core)
|
||||||
implementation(libs.acra.http)
|
implementation(libs.acra.http)
|
||||||
runtimeOnly(libs.acra.limiter)
|
runtimeOnly(libs.acra.limiter)
|
||||||
|
|
|
@ -2,7 +2,8 @@ package com.wbrawner.simplemarkdown.core
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import org.acra.ACRA
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.acra.config.httpSender
|
import org.acra.config.httpSender
|
||||||
import org.acra.data.StringFormat
|
import org.acra.data.StringFormat
|
||||||
import org.acra.ktx.initAcra
|
import org.acra.ktx.initAcra
|
||||||
|
@ -17,18 +18,18 @@ class ErrorReporterTree private constructor(): Timber.Tree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun create(application: Application): ErrorReporterTree {
|
suspend fun create(application: Application): ErrorReporterTree {
|
||||||
application.createErrorReporterTree()
|
application.createErrorReporterTree()
|
||||||
return ErrorReporterTree()
|
return ErrorReporterTree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Application.createErrorReporterTree() {
|
private suspend fun Application.createErrorReporterTree() = withContext(Dispatchers.IO) {
|
||||||
initAcra {
|
initAcra {
|
||||||
reportFormat = StringFormat.JSON
|
reportFormat = StringFormat.JSON
|
||||||
httpSender {
|
httpSender {
|
||||||
uri = "${BuildConfig.ACRA_URL}/report" /*best guess, you may need to adjust this*/
|
uri = "${BuildConfig.ACRA_URL}/report"
|
||||||
basicAuthLogin = BuildConfig.ACRA_USER
|
basicAuthLogin = BuildConfig.ACRA_USER
|
||||||
basicAuthPassword = BuildConfig.ACRA_PASS
|
basicAuthPassword = BuildConfig.ACRA_PASS
|
||||||
httpMethod = HttpSender.Method.POST
|
httpMethod = HttpSender.Method.POST
|
||||||
|
|
Loading…
Reference in a new issue