fix ANR
This commit is contained in:
parent
93148fcf36
commit
d1314a1b32
@ -50,8 +50,14 @@ import java.io.File
|
|||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import android.os.StrictMode
|
||||||
|
|
||||||
|
|
||||||
|
// Thread pool for tile downloading to prevent blocking UI thread
|
||||||
|
private val tileDownloadExecutor = Executors.newFixedThreadPool(4)
|
||||||
|
|
||||||
// MapState configuration for OpenStreetMap
|
// MapState configuration for OpenStreetMap
|
||||||
// Max zoom level is 18, tile size is 256x256
|
// Max zoom level is 18, tile size is 256x256
|
||||||
// At zoom level 18, there are 2^18 = 262144 tiles in each dimension
|
// At zoom level 18, there are 2^18 = 262144 tiles in each dimension
|
||||||
@ -67,6 +73,7 @@ val mapState = MapState(
|
|||||||
* Creates a cached tile stream provider for OpenStreetMap tiles
|
* Creates a cached tile stream provider for OpenStreetMap tiles
|
||||||
* Tiles are cached in the app's cache directory for offline access and faster loading
|
* Tiles are cached in the app's cache directory for offline access and faster loading
|
||||||
* Cache expires after 30 days to ensure map updates are fetched
|
* Cache expires after 30 days to ensure map updates are fetched
|
||||||
|
* Uses background thread pool to prevent ANR (Application Not Responding)
|
||||||
*/
|
*/
|
||||||
fun createCachedTileStreamProvider(context: Context, cacheExpiryDays: Int = 30): TileStreamProvider {
|
fun createCachedTileStreamProvider(context: Context, cacheExpiryDays: Int = 30): TileStreamProvider {
|
||||||
val cacheDir = File(context.cacheDir, "map_tiles")
|
val cacheDir = File(context.cacheDir, "map_tiles")
|
||||||
@ -89,12 +96,16 @@ fun createCachedTileStreamProvider(context: Context, cacheExpiryDays: Int = 30):
|
|||||||
// Use cached tile
|
// Use cached tile
|
||||||
FileInputStream(tileFile)
|
FileInputStream(tileFile)
|
||||||
} else {
|
} else {
|
||||||
// Download tile from OpenStreetMap (either new or expired)
|
// Download tile from OpenStreetMap in background thread
|
||||||
|
val future = tileDownloadExecutor.submit<FileInputStream?> {
|
||||||
|
try {
|
||||||
val url = URL("https://tile.openstreetmap.org/$zoomLvl/$col/$row.png")
|
val url = URL("https://tile.openstreetmap.org/$zoomLvl/$col/$row.png")
|
||||||
val connection = url.openConnection()
|
val connection = url.openConnection()
|
||||||
// Set User-Agent header as required by OSM tile usage policy
|
// Set User-Agent header as required by OSM tile usage policy
|
||||||
val userAgent = "${BuildConfig.APPLICATION_ID}/${BuildConfig.VERSION_NAME} (Android) (Contact: poliecho@pupes.org)"
|
val userAgent = "${BuildConfig.APPLICATION_ID}/${BuildConfig.VERSION_NAME} (Android) (Contact: poliecho@pupes.org)"
|
||||||
connection.setRequestProperty("User-Agent", userAgent)
|
connection.setRequestProperty("User-Agent", userAgent)
|
||||||
|
connection.connectTimeout = 5000 // 5 second timeout
|
||||||
|
connection.readTimeout = 10000 // 10 second timeout
|
||||||
|
|
||||||
val inputStream = connection.getInputStream()
|
val inputStream = connection.getInputStream()
|
||||||
|
|
||||||
@ -108,23 +119,36 @@ fun createCachedTileStreamProvider(context: Context, cacheExpiryDays: Int = 30):
|
|||||||
|
|
||||||
// Return the cached file's input stream
|
// Return the cached file's input stream
|
||||||
FileInputStream(tileFile)
|
FileInputStream(tileFile)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for download with timeout
|
||||||
|
try {
|
||||||
|
future.get() ?: run {
|
||||||
|
// If download failed but we have a cached tile (even if expired), use it
|
||||||
|
if (tileFile.exists()) {
|
||||||
|
FileInputStream(tileFile)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// If download fails but we have a cached tile (even if expired), use it
|
// If download timed out or failed, try using expired cache
|
||||||
val tileFile = File(cacheDir, "tile_${zoomLvl}_${col}_${row}.png")
|
|
||||||
if (tileFile.exists()) {
|
if (tileFile.exists()) {
|
||||||
try {
|
|
||||||
FileInputStream(tileFile)
|
FileInputStream(tileFile)
|
||||||
} catch (fallbackError: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
e.printStackTrace()
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -132,6 +156,21 @@ class MainActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// Configure StrictMode to detect threading violations (debug mode only)
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
StrictMode.setThreadPolicy(
|
||||||
|
StrictMode.ThreadPolicy.Builder()
|
||||||
|
.detectAll()
|
||||||
|
.penaltyLog() // Log violations instead of crashing
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
StrictMode.setVmPolicy(
|
||||||
|
StrictMode.VmPolicy.Builder()
|
||||||
|
.detectAll()
|
||||||
|
.penaltyLog()
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user