Added pass direction arrow to radar view #52
This commit is contained in:
1 parent
1da35e901a
commit
2d45fd614e
4 files changed
+105
-95
No files matched your search
+1
-2
@@ -61,8 +61,7 @@ dependencies {
|
|||||||
implementation "com.jakewharton.timber:timber:$timber_version"
|
implementation "com.jakewharton.timber:timber:$timber_version"
|
||||||
|
|
||||||
testImplementation "junit:junit:$junit_version"
|
testImplementation "junit:junit:$junit_version"
|
||||||
testImplementation "org.mockito:mockito-core:$mockito_version"
|
testImplementation "org.mockito:mockito-android:$mockito_version"
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
||||||
androidTestImplementation "org.mockito:mockito-android:$mockito_version"
|
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leak_canary_version"
|
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leak_canary_version"
|
||||||
}
|
}
|
||||||
+16
-22
@@ -20,17 +20,16 @@ package com.rtbishop.look4sat.presentation.satMapScreen
|
|||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import com.rtbishop.look4sat.data.PreferencesSource
|
import com.rtbishop.look4sat.data.PreferencesSource
|
||||||
import com.rtbishop.look4sat.data.SatDataRepository
|
import com.rtbishop.look4sat.data.SatDataRepository
|
||||||
import com.rtbishop.look4sat.injection.DefaultDispatcher
|
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
import com.rtbishop.look4sat.domain.predict4kotlin.Position
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
|
import com.rtbishop.look4sat.domain.predict4kotlin.StationPosition
|
||||||
import com.rtbishop.look4sat.framework.model.SatData
|
import com.rtbishop.look4sat.framework.model.SatData
|
||||||
|
import com.rtbishop.look4sat.injection.DefaultDispatcher
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import org.osmdroid.views.MapView
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
@@ -47,8 +46,8 @@ class SatMapViewModel @Inject constructor(
|
|||||||
private lateinit var selectedSat: Satellite
|
private lateinit var selectedSat: Satellite
|
||||||
|
|
||||||
val stationPos = liveData {
|
val stationPos = liveData {
|
||||||
val osmLat = getOsmLat(gsp.latitude)
|
val osmLat = clipLat(gsp.latitude)
|
||||||
val osmLon = getOsmLon(gsp.longitude)
|
val osmLon = clipLon(gsp.longitude)
|
||||||
emit(Position(osmLat, osmLon))
|
emit(Position(osmLat, osmLon))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,8 +114,8 @@ class SatMapViewModel @Inject constructor(
|
|||||||
val satPositions = mutableMapOf<Satellite, Position>()
|
val satPositions = mutableMapOf<Satellite, Position>()
|
||||||
list.forEach { satellite ->
|
list.forEach { satellite ->
|
||||||
val satPos = satellite.getPredictor(gsp).getSatPos(date)
|
val satPos = satellite.getPredictor(gsp).getSatPos(date)
|
||||||
val osmLat = getOsmLat(Math.toDegrees(satPos.latitude))
|
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = getOsmLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
satPositions[satellite] = Position(osmLat, osmLon)
|
satPositions[satellite] = Position(osmLat, osmLon)
|
||||||
}
|
}
|
||||||
_allSatPositions.postValue(satPositions)
|
_allSatPositions.postValue(satPositions)
|
||||||
@@ -129,8 +128,8 @@ class SatMapViewModel @Inject constructor(
|
|||||||
val currentTrack = mutableListOf<Position>()
|
val currentTrack = mutableListOf<Position>()
|
||||||
var oldLongitude = 0.0
|
var oldLongitude = 0.0
|
||||||
sat.getPredictor(gsp).getPositions(date, 15, 0, 2.4).forEach { satPos ->
|
sat.getPredictor(gsp).getPositions(date, 15, 0, 2.4).forEach { satPos ->
|
||||||
val osmLat = getOsmLat(Math.toDegrees(satPos.latitude))
|
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = getOsmLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
val currentPosition = Position(osmLat, osmLon)
|
val currentPosition = Position(osmLat, osmLon)
|
||||||
if (oldLongitude < -170.0 && currentPosition.longitude > 170.0) {
|
if (oldLongitude < -170.0 && currentPosition.longitude > 170.0) {
|
||||||
// adding left terminal position
|
// adding left terminal position
|
||||||
@@ -156,8 +155,8 @@ class SatMapViewModel @Inject constructor(
|
|||||||
private suspend fun setSelectedSatFootprint(sat: Satellite, gsp: StationPosition, date: Date) {
|
private suspend fun setSelectedSatFootprint(sat: Satellite, gsp: StationPosition, date: Date) {
|
||||||
withContext(defaultDispatcher) {
|
withContext(defaultDispatcher) {
|
||||||
val satFootprint = sat.getPosition(gsp, date).getRangeCircle().map { rangePos ->
|
val satFootprint = sat.getPosition(gsp, date).getRangeCircle().map { rangePos ->
|
||||||
val osmLat = getOsmLat(rangePos.latitude)
|
val osmLat = clipLat(rangePos.latitude)
|
||||||
val osmLon = getOsmLon(rangePos.longitude)
|
val osmLon = clipLon(rangePos.longitude)
|
||||||
Position(osmLat, osmLon)
|
Position(osmLat, osmLon)
|
||||||
}
|
}
|
||||||
_satFootprint.postValue(satFootprint)
|
_satFootprint.postValue(satFootprint)
|
||||||
@@ -167,8 +166,8 @@ class SatMapViewModel @Inject constructor(
|
|||||||
private suspend fun setSelectedSatData(sat: Satellite, gsp: StationPosition, date: Date) {
|
private suspend fun setSelectedSatData(sat: Satellite, gsp: StationPosition, date: Date) {
|
||||||
withContext(defaultDispatcher) {
|
withContext(defaultDispatcher) {
|
||||||
val satPos = sat.getPredictor(gsp).getSatPos(date)
|
val satPos = sat.getPredictor(gsp).getSatPos(date)
|
||||||
val osmLat = getOsmLat(Math.toDegrees(satPos.latitude))
|
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = getOsmLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
val osmPos = Position(osmLat, osmLon)
|
val osmPos = Position(osmLat, osmLon)
|
||||||
val qthLoc =
|
val qthLoc =
|
||||||
preferencesSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
preferencesSource.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
||||||
@@ -181,17 +180,12 @@ class SatMapViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOsmLat(latitude: Double): Double {
|
private fun clipLat(latitude: Double): Double {
|
||||||
return min(max(latitude, -85.0), 85.0)
|
return MapView.getTileSystem().cleanLatitude(latitude)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOsmLon(longitude: Double): Double {
|
private fun clipLon(longitude: Double): Double {
|
||||||
val newLongitude = when {
|
return MapView.getTileSystem().cleanLongitude(longitude)
|
||||||
longitude < -180.0 -> longitude + 360.0
|
|
||||||
longitude > 180.0 -> longitude - 360.0
|
|
||||||
else -> longitude
|
|
||||||
}
|
|
||||||
return min(max(newLongitude, -180.0), 180.0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrbitalVelocity(altitude: Double): Double {
|
private fun getOrbitalVelocity(altitude: Double): Double {
|
||||||
|
|||||||
+85
-68
@@ -18,10 +18,7 @@
|
|||||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.*
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.graphics.Path
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
@@ -33,49 +30,49 @@ import kotlin.math.sin
|
|||||||
class PassInfoView(context: Context) : View(context) {
|
class PassInfoView(context: Context) : View(context) {
|
||||||
|
|
||||||
private lateinit var satPass: SatPass
|
private lateinit var satPass: SatPass
|
||||||
private val polarWidth = resources.displayMetrics.widthPixels
|
|
||||||
private val polarCenter = polarWidth / 2f
|
|
||||||
private val scale = resources.displayMetrics.density
|
private val scale = resources.displayMetrics.density
|
||||||
private val radius = polarWidth * 0.48f
|
private val radarWidth = resources.displayMetrics.widthPixels
|
||||||
private val txtSize = scale * 16f
|
private val radarCenter = radarWidth / 2f
|
||||||
private val satTrack: Path = Path()
|
private val radarRadius = radarWidth * 0.48f
|
||||||
private val piDiv2 = Math.PI / 2.0
|
private val piDiv2 = Math.PI / 2.0
|
||||||
|
private val arrowPath = Path()
|
||||||
|
private val satTrack: Path = Path()
|
||||||
|
private val strokeSize = scale * 2f
|
||||||
|
private val satSize = scale * 8f
|
||||||
|
private val txtSize = scale * 16f
|
||||||
|
private val radarPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = ContextCompat.getColor(context, R.color.greyLight)
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
strokeWidth = strokeSize
|
||||||
|
}
|
||||||
|
private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = ContextCompat.getColor(context, R.color.themeLight)
|
||||||
|
textSize = txtSize
|
||||||
|
}
|
||||||
|
private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = Color.RED
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
strokeWidth = strokeSize
|
||||||
|
}
|
||||||
|
private val satPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = ContextCompat.getColor(context, R.color.themeLight)
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
private val arrowPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = ContextCompat.getColor(context, R.color.themeLight)
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
strokeWidth = strokeSize
|
||||||
|
}
|
||||||
private var azimuth: Float = 0f
|
private var azimuth: Float = 0f
|
||||||
private var pitch: Float = 0f
|
private var pitch: Float = 0f
|
||||||
private var roll: Float = 0f
|
private var roll: Float = 0f
|
||||||
|
|
||||||
private val radarPaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
color = ContextCompat.getColor(context, R.color.greyLight)
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
strokeWidth = scale * 2f
|
|
||||||
}
|
|
||||||
private val txtPaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
color = ContextCompat.getColor(context, R.color.themeLight)
|
|
||||||
textSize = txtSize
|
|
||||||
}
|
|
||||||
private val trackPaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
color = Color.RED
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
strokeWidth = scale * 2f
|
|
||||||
}
|
|
||||||
private val satPaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
color = ContextCompat.getColor(context, R.color.themeLight)
|
|
||||||
style = Paint.Style.FILL
|
|
||||||
}
|
|
||||||
private val orientPaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
color = Color.RED
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
strokeWidth = scale * 2f
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPass(satPass: SatPass) {
|
fun setPass(satPass: SatPass) {
|
||||||
this.satPass = satPass
|
this.satPass = satPass
|
||||||
createPassTrajectory(satPass)
|
if (!satPass.isDeepSpace) {
|
||||||
|
createPassTrajectory(satPass)
|
||||||
|
createPassTrajectoryArrow()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOrientation(azimuth: Float, pitch: Float, roll: Float) {
|
fun setOrientation(azimuth: Float, pitch: Float, roll: Float) {
|
||||||
@@ -88,63 +85,83 @@ class PassInfoView(context: Context) : View(context) {
|
|||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
override fun onDraw(canvas: Canvas) {
|
||||||
canvas.drawColor(ContextCompat.getColor(context, R.color.greyDark))
|
canvas.drawColor(ContextCompat.getColor(context, R.color.greyDark))
|
||||||
canvas.translate(polarCenter, polarCenter)
|
canvas.translate(radarCenter, radarCenter)
|
||||||
drawRadarView(canvas)
|
drawRadarView(canvas)
|
||||||
drawRadarText(canvas)
|
drawRadarText(canvas)
|
||||||
if (!satPass.isDeepSpace) canvas.drawPath(satTrack, trackPaint)
|
if (!satPass.isDeepSpace) {
|
||||||
|
canvas.drawPath(satTrack, trackPaint)
|
||||||
|
canvas.drawPath(satTrack, arrowPaint)
|
||||||
|
}
|
||||||
drawSatellite(canvas, satPass)
|
drawSatellite(canvas, satPass)
|
||||||
drawOrientation(canvas, azimuth, pitch)
|
drawCrosshair(canvas, azimuth, pitch)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPassTrajectory(satPass: SatPass) {
|
private fun createPassTrajectory(satPass: SatPass) {
|
||||||
val startTime = satPass.aosDate
|
val currentTime = satPass.aosDate
|
||||||
val endTime = satPass.losDate
|
while (currentTime.before(satPass.losDate)) {
|
||||||
while (startTime.before(endTime)) {
|
val satPos = satPass.predictor.getSatPos(currentTime)
|
||||||
val satPos = satPass.predictor.getSatPos(startTime)
|
val passX = sph2CartX(satPos.azimuth, satPos.elevation, radarRadius.toDouble())
|
||||||
val passX = sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble())
|
val passY = sph2CartY(satPos.azimuth, satPos.elevation, radarRadius.toDouble())
|
||||||
val passY = sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble())
|
if (currentTime.compareTo(satPass.aosDate) == 0) {
|
||||||
if (startTime.compareTo(satPass.aosDate) == 0) {
|
|
||||||
satTrack.moveTo(passX, -passY)
|
satTrack.moveTo(passX, -passY)
|
||||||
} else {
|
} else {
|
||||||
satTrack.lineTo(passX, -passY)
|
satTrack.lineTo(passX, -passY)
|
||||||
}
|
}
|
||||||
startTime.time += 15000
|
currentTime.time += 15000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createPassTrajectoryArrow() {
|
||||||
|
val radius = satSize
|
||||||
|
val sides = 3
|
||||||
|
val angle = 2.0 * Math.PI / sides
|
||||||
|
arrowPath.moveTo((radius * cos(angle)).toFloat(), (radius * sin(angle)).toFloat())
|
||||||
|
for (i in 1 until sides) {
|
||||||
|
val x = (radius * cos(angle - angle * i)).toFloat()
|
||||||
|
val y = (radius * sin(angle - angle * i)).toFloat()
|
||||||
|
arrowPath.lineTo(x, y)
|
||||||
|
}
|
||||||
|
arrowPath.close()
|
||||||
|
val trackLength = PathMeasure(satTrack, false).length
|
||||||
|
val quarter = trackLength / 4f
|
||||||
|
val center = trackLength / 2f
|
||||||
|
val effect = PathDashPathEffect(arrowPath, center, quarter, PathDashPathEffect.Style.ROTATE)
|
||||||
|
arrowPaint.pathEffect = effect
|
||||||
|
}
|
||||||
|
|
||||||
private fun drawRadarView(canvas: Canvas) {
|
private fun drawRadarView(canvas: Canvas) {
|
||||||
canvas.drawLine(-radius, 0f, radius, 0f, radarPaint)
|
canvas.drawLine(-radarRadius, 0f, radarRadius, 0f, radarPaint)
|
||||||
canvas.drawLine(0f, -radius, 0f, radius, radarPaint)
|
canvas.drawLine(0f, -radarRadius, 0f, radarRadius, radarPaint)
|
||||||
canvas.drawCircle(0f, 0f, radius, radarPaint)
|
canvas.drawCircle(0f, 0f, radarRadius, radarPaint)
|
||||||
canvas.drawCircle(0f, 0f, (radius / 3) * 2, radarPaint)
|
canvas.drawCircle(0f, 0f, (radarRadius / 3) * 2, radarPaint)
|
||||||
canvas.drawCircle(0f, 0f, radius / 3, radarPaint)
|
canvas.drawCircle(0f, 0f, radarRadius / 3, radarPaint)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawRadarText(canvas: Canvas) {
|
private fun drawRadarText(canvas: Canvas) {
|
||||||
canvas.drawText("N", scale, -radius + txtSize - scale * 2, txtPaint)
|
canvas.drawText("N", scale, -radarRadius + txtSize - strokeSize, textPaint)
|
||||||
canvas.drawText("30°", scale, -((radius / 3) * 2) - scale * 2, txtPaint)
|
canvas.drawText("30°", scale, -((radarRadius / 3) * 2) - strokeSize, textPaint)
|
||||||
canvas.drawText("60°", scale, -(radius / 3) - scale * 2, txtPaint)
|
canvas.drawText("60°", scale, -(radarRadius / 3) - strokeSize, textPaint)
|
||||||
canvas.drawText("90°", scale, -scale * 2, txtPaint)
|
canvas.drawText("90°", scale, -strokeSize, textPaint)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawSatellite(canvas: Canvas, satPass: SatPass) {
|
private fun drawSatellite(canvas: Canvas, satPass: SatPass) {
|
||||||
val satPos = satPass.predictor.getSatPos(Date())
|
val satPos = satPass.predictor.getSatPos(Date())
|
||||||
if (satPos.elevation > 0) {
|
if (satPos.elevation > 0) {
|
||||||
val x = sph2CartX(satPos.azimuth, satPos.elevation, radius.toDouble())
|
val satX = sph2CartX(satPos.azimuth, satPos.elevation, radarRadius.toDouble())
|
||||||
val y = sph2CartY(satPos.azimuth, satPos.elevation, radius.toDouble())
|
val satY = sph2CartY(satPos.azimuth, satPos.elevation, radarRadius.toDouble())
|
||||||
canvas.drawCircle(x, -y, txtSize / 2.4f, satPaint)
|
canvas.drawCircle(satX, -satY, satSize, satPaint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawOrientation(canvas: Canvas, azimuth: Float, pitch: Float) {
|
private fun drawCrosshair(canvas: Canvas, azimuth: Float, pitch: Float) {
|
||||||
val azimuthRad = Math.toRadians(azimuth.toDouble())
|
val azimuthRad = Math.toRadians(azimuth.toDouble())
|
||||||
val tmpElevation = Math.toRadians(pitch.toDouble())
|
val tmpElevation = Math.toRadians(pitch.toDouble())
|
||||||
val elevationRad = if (tmpElevation > 0.0) 0.0 else tmpElevation
|
val elevationRad = if (tmpElevation > 0.0) 0.0 else tmpElevation
|
||||||
val orientX = sph2CartX(azimuthRad, -elevationRad, radius.toDouble())
|
val crossX = sph2CartX(azimuthRad, -elevationRad, radarRadius.toDouble())
|
||||||
val orientY = sph2CartY(azimuthRad, -elevationRad, radius.toDouble())
|
val crossY = sph2CartY(azimuthRad, -elevationRad, radarRadius.toDouble())
|
||||||
canvas.drawLine(orientX - txtSize, -orientY, orientX + txtSize, -orientY, orientPaint)
|
canvas.drawLine(crossX - txtSize, -crossY, crossX + txtSize, -crossY, trackPaint)
|
||||||
canvas.drawLine(orientX, -orientY - txtSize, orientX, -orientY + txtSize, orientPaint)
|
canvas.drawLine(crossX, -crossY - txtSize, crossX, -crossY + txtSize, trackPaint)
|
||||||
canvas.drawCircle(orientX, -orientY, txtSize / 2, orientPaint)
|
canvas.drawCircle(crossX, -crossY, txtSize / 2, trackPaint)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sph2CartX(azimuth: Double, elevation: Double, r: Double): Float {
|
private fun sph2CartX(azimuth: Double, elevation: Double, r: Double): Float {
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
ext {
|
||||||
gradle_version = '4.2.0'
|
gradle_version = '4.2.1'
|
||||||
kotlin_version = '1.5.0'
|
kotlin_version = '1.5.0'
|
||||||
coroutines_version = '1.5.0-RC-native-mt'
|
coroutines_version = '1.5.0'
|
||||||
material_version = '1.3.0'
|
material_version = '1.3.0'
|
||||||
constraint_layout_version = '2.0.4'
|
constraint_layout_version = '2.0.4'
|
||||||
lifecycle_version = '2.3.1'
|
lifecycle_version = '2.3.1'
|
||||||
@@ -14,7 +14,7 @@ buildscript {
|
|||||||
osmdroid_version = '6.1.10'
|
osmdroid_version = '6.1.10'
|
||||||
timber_version = '4.7.1'
|
timber_version = '4.7.1'
|
||||||
junit_version = '4.13.2'
|
junit_version = '4.13.2'
|
||||||
mockito_version = '3.9.0'
|
mockito_version = '3.10.0'
|
||||||
leak_canary_version = '2.7'
|
leak_canary_version = '2.7'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
|
|||||||
Reference in new issue
Block a user