kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
commit
57aff30082
|
@ -4,6 +4,7 @@ apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'kotlinx-serialization'
|
apply plugin: 'kotlinx-serialization'
|
||||||
apply plugin: 'com.google.gms.google-services'
|
apply plugin: 'com.google.gms.google-services'
|
||||||
apply plugin: 'com.github.triplet.play'
|
apply plugin: 'com.github.triplet.play'
|
||||||
|
apply plugin: 'de.mobilej.unmock'
|
||||||
// apply plugin: "app.brant.amazonappstorepublisher"
|
// apply plugin: "app.brant.amazonappstorepublisher"
|
||||||
|
|
||||||
// Apply the Crashlytics Gradle plugin
|
// Apply the Crashlytics Gradle plugin
|
||||||
|
@ -14,6 +15,11 @@ apply plugin: 'com.google.protobuf'
|
||||||
|
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
|
unMock {
|
||||||
|
keep "android.net.Uri"
|
||||||
|
keep "android.util.Base64"
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
/*
|
/*
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
@ -31,8 +37,8 @@ android {
|
||||||
applicationId "com.geeksville.mesh"
|
applicationId "com.geeksville.mesh"
|
||||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 20207 // format is Mmmss (where M is 1+the numeric major number
|
versionCode 20211 // format is Mmmss (where M is 1+the numeric major number
|
||||||
versionName "1.2.7"
|
versionName "1.2.11"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
// per https://developer.android.com/studio/write/vector-asset-studio
|
// per https://developer.android.com/studio/write/vector-asset-studio
|
||||||
|
|
|
@ -668,8 +668,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
else {
|
else {
|
||||||
|
|
||||||
val curVer = DeviceVersion(info.firmwareVersion ?: "0.0.0")
|
val curVer = DeviceVersion(info.firmwareVersion ?: "0.0.0")
|
||||||
val minVer = DeviceVersion("1.2.0")
|
if (curVer < MeshService.minFirmwareVersion)
|
||||||
if (curVer < minVer)
|
|
||||||
showAlert(R.string.firmware_too_old, R.string.firmware_old)
|
showAlert(R.string.firmware_too_old, R.string.firmware_old)
|
||||||
else {
|
else {
|
||||||
// If our app is too old/new, we probably don't understand the new radioconfig messages, so we don't read them until here
|
// If our app is too old/new, we probably don't understand the new radioconfig messages, so we don't read them until here
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
package com.geeksville.mesh.model
|
package com.geeksville.mesh.model
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.net.Uri
|
|
||||||
import android.util.Base64
|
|
||||||
import com.geeksville.mesh.ChannelProtos
|
import com.geeksville.mesh.ChannelProtos
|
||||||
import com.geeksville.mesh.MeshProtos
|
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import com.google.zxing.BarcodeFormat
|
|
||||||
import com.google.zxing.MultiFormatWriter
|
|
||||||
import com.journeyapps.barcodescanner.BarcodeEncoder
|
|
||||||
import java.net.MalformedURLException
|
|
||||||
|
|
||||||
/** Utility function to make it easy to declare byte arrays - FIXME move someplace better */
|
/** Utility function to make it easy to declare byte arrays - FIXME move someplace better */
|
||||||
fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }
|
fun byteArrayOfInts(vararg ints: Int) = ByteArray(ints.size) { pos -> ints[pos].toByte() }
|
||||||
|
@ -19,19 +11,15 @@ data class Channel(
|
||||||
val settings: ChannelProtos.ChannelSettings = ChannelProtos.ChannelSettings.getDefaultInstance()
|
val settings: ChannelProtos.ChannelSettings = ChannelProtos.ChannelSettings.getDefaultInstance()
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
// Note: this string _SHOULD NOT BE LOCALIZED_ because it directly hashes to values used on the device for the default channel name.
|
|
||||||
// FIXME - make this work with new channel name system
|
|
||||||
const val defaultChannelName = "Default"
|
|
||||||
|
|
||||||
// These bytes must match the well known and not secret bytes used the default channel AES128 key device code
|
// These bytes must match the well known and not secret bytes used the default channel AES128 key device code
|
||||||
val channelDefaultKey = byteArrayOfInts(
|
val channelDefaultKey = byteArrayOfInts(
|
||||||
0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
0xd4, 0xf1, 0xbb, 0x3a, 0x20, 0x29, 0x07, 0x59,
|
||||||
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf
|
0xf0, 0xbc, 0xff, 0xab, 0xcf, 0x4e, 0x69, 0xbf
|
||||||
)
|
)
|
||||||
|
|
||||||
// Placeholder when emulating
|
// TH=he unsecured channel that devices ship with
|
||||||
val emulated = Channel(
|
val defaultChannel = Channel(
|
||||||
ChannelProtos.ChannelSettings.newBuilder().setName(defaultChannelName)
|
ChannelProtos.ChannelSettings.newBuilder()
|
||||||
.setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build()
|
.setModemConfig(ChannelProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128).build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -78,14 +66,13 @@ data class Channel(
|
||||||
*/
|
*/
|
||||||
val humanName: String
|
val humanName: String
|
||||||
get() {
|
get() {
|
||||||
val suffix: Char = if (settings.psk.size() != 1) {
|
// start with the PSK then xor in the name
|
||||||
// we have a full PSK, so hash it to generate the suffix
|
val pskCode = xorHash(psk.toByteArray())
|
||||||
val code = settings.psk.fold(0, { acc, x -> acc xor (x.toInt() and 0xff) })
|
val nameCode = xorHash(name.toByteArray())
|
||||||
|
val suffix = 'A' + ((pskCode xor nameCode) % 26)
|
||||||
'A' + (code % 26)
|
|
||||||
} else
|
|
||||||
'0' + settings.psk.byteAt(0).toInt()
|
|
||||||
|
|
||||||
return "#${name}-${suffix}"
|
return "#${name}-${suffix}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun xorHash(b: ByteArray) = b.fold(0, { acc, x -> acc xor (x.toInt() and 0xff) })
|
|
@ -16,11 +16,6 @@ data class ChannelSet(
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
// Placeholder when emulating
|
|
||||||
val emulated = ChannelSet(
|
|
||||||
AppOnlyProtos.ChannelSet.newBuilder().addSettings(Channel.emulated.settings).build()
|
|
||||||
)
|
|
||||||
|
|
||||||
const val prefix = "https://www.meshtastic.org/d/#"
|
const val prefix = "https://www.meshtastic.org/d/#"
|
||||||
|
|
||||||
private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING
|
private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING
|
||||||
|
|
|
@ -94,6 +94,10 @@ class MeshService : Service(), Logging {
|
||||||
"com.geeksville.mesh",
|
"com.geeksville.mesh",
|
||||||
"com.geeksville.mesh.service.MeshService"
|
"com.geeksville.mesh.service.MeshService"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/** The minimmum firmware version we know how to talk to. We'll still be able to talk to 1.0 firmwares but only well enough to ask them to firmware update
|
||||||
|
*/
|
||||||
|
val minFirmwareVersion = DeviceVersion("1.2.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class ConnectionState {
|
enum class ConnectionState {
|
||||||
|
@ -167,7 +171,7 @@ class MeshService : Service(), Logging {
|
||||||
// FIXME - currently we don't support location reading without google play
|
// FIXME - currently we don't support location reading without google play
|
||||||
if (fusedLocationClient == null && isGooglePlayAvailable(this)) {
|
if (fusedLocationClient == null && isGooglePlayAvailable(this)) {
|
||||||
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
|
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
|
||||||
|
|
||||||
val request = LocationRequest.create().apply {
|
val request = LocationRequest.create().apply {
|
||||||
interval = requestInterval
|
interval = requestInterval
|
||||||
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
|
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
|
||||||
|
@ -945,13 +949,13 @@ class MeshService : Service(), Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
private var locationRequestInterval: Long = 0;
|
private var locationRequestInterval: Long = 0;
|
||||||
private fun setupLocationRequest () {
|
private fun setupLocationRequest() {
|
||||||
val desiredInterval: Long = if (myNodeInfo?.hasGPS == true) {
|
val desiredInterval: Long = if (myNodeInfo?.hasGPS == true) {
|
||||||
0L // no requests when device has GPS
|
0L // no requests when device has GPS
|
||||||
} else if (numOnlineNodes < 2) {
|
} else if (numOnlineNodes < 2) {
|
||||||
5 * 60 * 1000L // send infrequently, device needs these requests to set its clock
|
5 * 60 * 1000L // send infrequently, device needs these requests to set its clock
|
||||||
} else {
|
} else {
|
||||||
radioConfig?.preferences?.positionBroadcastSecs?.times( 1000L) ?: 5 * 60 * 1000L
|
radioConfig?.preferences?.positionBroadcastSecs?.times(1000L) ?: 5 * 60 * 1000L
|
||||||
}
|
}
|
||||||
|
|
||||||
debug("desired location request $desiredInterval, current $locationRequestInterval")
|
debug("desired location request $desiredInterval, current $locationRequestInterval")
|
||||||
|
@ -1174,18 +1178,6 @@ class MeshService : Service(), Logging {
|
||||||
/// Used to make sure we never get foold by old BLE packets
|
/// Used to make sure we never get foold by old BLE packets
|
||||||
private var configNonce = 1
|
private var configNonce = 1
|
||||||
|
|
||||||
|
|
||||||
private fun handleRadioConfig(radio: RadioConfigProtos.RadioConfig) {
|
|
||||||
val packetToSave = Packet(
|
|
||||||
UUID.randomUUID().toString(),
|
|
||||||
"RadioConfig",
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
radio.toString()
|
|
||||||
)
|
|
||||||
insertPacket(packetToSave)
|
|
||||||
radioConfig = radio
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a protobuf NodeInfo into our model objects and update our node DB
|
* Convert a protobuf NodeInfo into our model objects and update our node DB
|
||||||
*/
|
*/
|
||||||
|
@ -1296,6 +1288,9 @@ class MeshService : Service(), Logging {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If found, the old region string of the form 1.0-EU865 etc...
|
||||||
|
private var legacyRegion: String? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the nodeinfo (called from either new API version or the old one)
|
* Update the nodeinfo (called from either new API version or the old one)
|
||||||
*/
|
*/
|
||||||
|
@ -1309,6 +1304,7 @@ class MeshService : Service(), Logging {
|
||||||
insertPacket(packetToSave)
|
insertPacket(packetToSave)
|
||||||
|
|
||||||
rawMyNodeInfo = myInfo
|
rawMyNodeInfo = myInfo
|
||||||
|
legacyRegion = myInfo.region
|
||||||
regenMyNodeInfo()
|
regenMyNodeInfo()
|
||||||
|
|
||||||
// We'll need to get a new set of channels and settings now
|
// We'll need to get a new set of channels and settings now
|
||||||
|
@ -1342,34 +1338,37 @@ class MeshService : Service(), Logging {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curRegionValue == RadioConfigProtos.RegionCode.Unset_VALUE) {
|
if (curRegionValue == RadioConfigProtos.RegionCode.Unset_VALUE) {
|
||||||
TODO("Need gui for setting region")
|
// look for a legacy region
|
||||||
/* // look for a legacy region
|
|
||||||
val legacyRegex = Regex(".+-(.+)")
|
val legacyRegex = Regex(".+-(.+)")
|
||||||
myNodeInfo?.region?.let { legacyRegion ->
|
legacyRegion?.let { lr ->
|
||||||
val matches = legacyRegex.find(legacyRegion)
|
val matches = legacyRegex.find(lr)
|
||||||
if (matches != null) {
|
if (matches != null) {
|
||||||
val (region) = matches.destructured
|
val (region) = matches.destructured
|
||||||
val newRegion = RadioConfigProtos.RegionCode.valueOf(region)
|
val newRegion = RadioConfigProtos.RegionCode.valueOf(region)
|
||||||
info("Upgrading legacy region $newRegion (code ${newRegion.number})")
|
info("Upgrading legacy region $newRegion (code ${newRegion.number})")
|
||||||
curRegionValue = newRegion.number
|
curRegionValue = newRegion.number
|
||||||
}
|
}
|
||||||
} */
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If nothing was set in our (new style radio preferences, but we now have a valid setting - slam it in)
|
// If nothing was set in our (new style radio preferences, but we now have a valid setting - slam it in)
|
||||||
if (curConfigRegion == RadioConfigProtos.RegionCode.Unset && curRegionValue != RadioConfigProtos.RegionCode.Unset_VALUE) {
|
if (curConfigRegion == RadioConfigProtos.RegionCode.Unset && curRegionValue != RadioConfigProtos.RegionCode.Unset_VALUE) {
|
||||||
info("Telling device to upgrade region")
|
if (deviceVersion >= minFirmwareVersion) {
|
||||||
|
info("Telling device to upgrade region")
|
||||||
|
|
||||||
// Tell the device to set the new region field (old devices will simply ignore this)
|
// Tell the device to set the new region field (old devices will simply ignore this)
|
||||||
radioConfig?.let { currentConfig ->
|
radioConfig?.let { currentConfig ->
|
||||||
val newConfig = currentConfig.toBuilder()
|
val newConfig = currentConfig.toBuilder()
|
||||||
|
|
||||||
val newPrefs = currentConfig.preferences.toBuilder()
|
val newPrefs = currentConfig.preferences.toBuilder()
|
||||||
newPrefs.regionValue = curRegionValue
|
newPrefs.regionValue = curRegionValue
|
||||||
newConfig.preferences = newPrefs.build()
|
newConfig.preferences = newPrefs.build()
|
||||||
|
|
||||||
sendRadioConfig(newConfig.build())
|
sendRadioConfig(newConfig.build())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
warn("Device is too old to understand region changes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1413,10 +1412,14 @@ class MeshService : Service(), Logging {
|
||||||
|
|
||||||
regenMyNodeInfo() // we have a node db now, so can possibly find a better hwmodel
|
regenMyNodeInfo() // we have a node db now, so can possibly find a better hwmodel
|
||||||
myNodeInfo = newMyNodeInfo // we might have just updated myNodeInfo
|
myNodeInfo = newMyNodeInfo // we might have just updated myNodeInfo
|
||||||
|
|
||||||
sendAnalytics()
|
sendAnalytics()
|
||||||
|
|
||||||
requestRadioConfig()
|
if (deviceVersion < minFirmwareVersion) {
|
||||||
|
info("Device firmware is too old, faking config so firmware update can occur")
|
||||||
|
onHasSettings()
|
||||||
|
} else
|
||||||
|
requestRadioConfig()
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
warn("Ignoring stale config complete")
|
warn("Ignoring stale config complete")
|
||||||
|
|
|
@ -169,12 +169,12 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
||||||
// Generate a new channel with only the changes the user can change in the GUI
|
// Generate a new channel with only the changes the user can change in the GUI
|
||||||
model.channels.value?.primaryChannel?.let { oldPrimary ->
|
model.channels.value?.primaryChannel?.let { oldPrimary ->
|
||||||
val newSettings = oldPrimary.settings.toBuilder()
|
var newSettings = oldPrimary.settings.toBuilder()
|
||||||
newSettings.name = binding.channelNameEdit.text.toString().trim()
|
newSettings.name = binding.channelNameEdit.text.toString().trim()
|
||||||
|
|
||||||
// Generate a new AES256 key (for any channel not named Default)
|
// Generate a new AES256 key unleess the user is trying to go back to stock
|
||||||
if (!newSettings.name.equals(
|
if (!newSettings.name.equals(
|
||||||
Channel.defaultChannelName,
|
Channel.defaultChannel.name,
|
||||||
ignoreCase = true
|
ignoreCase = true
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
@ -184,10 +184,8 @@ class ChannelFragment : ScreenFragment("Channel"), Logging {
|
||||||
random.nextBytes(bytes)
|
random.nextBytes(bytes)
|
||||||
newSettings.psk = ByteString.copyFrom(bytes)
|
newSettings.psk = ByteString.copyFrom(bytes)
|
||||||
} else {
|
} else {
|
||||||
debug("ASSIGNING NEW default AES128 KEY")
|
debug("Switching back to default channel")
|
||||||
newSettings.name =
|
newSettings = Channel.defaultChannel.settings.toBuilder()
|
||||||
Channel.defaultChannelName // Fix any case errors
|
|
||||||
newSettings.psk = ByteString.copyFrom(Channel.channelDefaultKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val selectedChannelOptionString =
|
val selectedChannelOptionString =
|
||||||
|
|
|
@ -8,9 +8,10 @@ import org.junit.Test
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NodeInfoTest {
|
class NodeInfoTest {
|
||||||
val ni1 = NodeInfo(4, MeshUser("+one", "User One", "U1"), Position(37.1, 121.1, 35))
|
val model = MeshProtos.HardwareModel.ANDROID_SIM
|
||||||
val ni2 = NodeInfo(5, MeshUser("+two", "User Two", "U2"), Position(37.11, 121.1, 40))
|
val ni1 = NodeInfo(4, MeshUser("+one", "User One", "U1", model), Position(37.1, 121.1, 35))
|
||||||
val ni3 = NodeInfo(6, MeshUser("+three", "User Three", "U3"), Position(37.101, 121.1, 40))
|
val ni2 = NodeInfo(5, MeshUser("+two", "User Two", "U2", model), Position(37.11, 121.1, 40))
|
||||||
|
val ni3 = NodeInfo(6, MeshUser("+three", "User Three", "U3", model), Position(37.101, 121.1, 40))
|
||||||
|
|
||||||
private val currentDefaultLocale = LocaleListCompat.getDefault().get(0)
|
private val currentDefaultLocale = LocaleListCompat.getDefault().get(0)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.geeksville.mesh.model
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ChannelSetTest {
|
||||||
|
/** make sure we match the python and device code behavior */
|
||||||
|
@Test
|
||||||
|
fun matchPython() {
|
||||||
|
val url = Uri.parse("https://www.meshtastic.org/d/#CgUYAyIBAQ")
|
||||||
|
val cs = ChannelSet(url)
|
||||||
|
Assert.assertEquals("LongSlow", cs.primaryChannel!!.name, )
|
||||||
|
Assert.assertEquals("#LongSlow-V", cs.primaryChannel!!.humanName, )
|
||||||
|
Assert.assertEquals(url, cs.getChannelUrl(false))
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +1,32 @@
|
||||||
package com.geeksville.mesh.service
|
package com.geeksville.mesh.service
|
||||||
|
|
||||||
import com.geeksville.mesh.MeshUser
|
import com.geeksville.mesh.MeshProtos
|
||||||
import com.geeksville.mesh.NodeInfo
|
import com.geeksville.mesh.MeshUser
|
||||||
import com.geeksville.mesh.Position
|
import com.geeksville.mesh.NodeInfo
|
||||||
import org.junit.Assert
|
import com.geeksville.mesh.Position
|
||||||
import org.junit.Test
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
class MeshServiceTest {
|
|
||||||
|
class MeshServiceTest {
|
||||||
val nodeInfo = NodeInfo(4, MeshUser("+one", "User One", "U1"), Position(37.1, 121.1, 35, 10))
|
val model = MeshProtos.HardwareModel.ANDROID_SIM
|
||||||
|
val nodeInfo = NodeInfo(4, MeshUser("+one", "User One", "U1", model), Position(37.1, 121.1, 35, 10))
|
||||||
@Test
|
|
||||||
fun givenNodeInfo_whenUpdatingWithNewTime_thenPositionTimeIsUpdated() {
|
@Test
|
||||||
|
fun givenNodeInfo_whenUpdatingWithNewTime_thenPositionTimeIsUpdated() {
|
||||||
val newerTime = 20
|
|
||||||
updateNodeInfoTime(nodeInfo, newerTime)
|
val newerTime = 20
|
||||||
Assert.assertEquals(newerTime, nodeInfo.position?.time)
|
updateNodeInfoTime(nodeInfo, newerTime)
|
||||||
}
|
Assert.assertEquals(newerTime, nodeInfo.position?.time)
|
||||||
|
}
|
||||||
@Test
|
|
||||||
fun givenNodeInfo_whenUpdatingWithOldTime_thenPositionTimeIsNotUpdated() {
|
@Test
|
||||||
val olderTime = 5
|
fun givenNodeInfo_whenUpdatingWithOldTime_thenPositionTimeIsNotUpdated() {
|
||||||
val timeBeforeTryingToUpdate = nodeInfo.position?.time
|
val olderTime = 5
|
||||||
updateNodeInfoTime(nodeInfo, olderTime)
|
val timeBeforeTryingToUpdate = nodeInfo.position?.time
|
||||||
Assert.assertEquals(timeBeforeTryingToUpdate, nodeInfo.position?.time)
|
updateNodeInfoTime(nodeInfo, olderTime)
|
||||||
}
|
Assert.assertEquals(timeBeforeTryingToUpdate, nodeInfo.position?.time)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ buildscript {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.2'
|
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
|
|
||||||
|
@ -28,6 +28,9 @@ buildscript {
|
||||||
|
|
||||||
//classpath "app.brant:amazonappstorepublisher:0.1.0"
|
//classpath "app.brant:amazonappstorepublisher:0.1.0"
|
||||||
classpath 'com.github.triplet.gradle:play-publisher:2.8.0'
|
classpath 'com.github.triplet.gradle:play-publisher:2.8.0'
|
||||||
|
|
||||||
|
// for unit testing https://github.com/bjoernQ/unmock-plugin
|
||||||
|
classpath 'com.github.bjoernq:unmockplugin:0.7.6'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue