Android Question Mock Location doesn't accept Lat/Lon

Fusseldieb

Active Member
Licensed User
Longtime User
Hi everyone,
I've tried to use the mock-locationprovider-lib and successfully simulated a location with it (after setting the target API down to 16 because of a deprecated library function which doesn't set a specific value that's required on newer API's, but anyways), but I'm struggling to set a specific Lat/Lon value to it.

If I take the example that is:
B4X:
latitude="5234.1421"        'lat. as decimal_degrees
ns="N"                    'north-south = NORTH
longitude="01311.7996"        'long. as decimal_degrees
we = "E"                    'west-east = EAST
altitude="84.0"                'alt. as meter     
speed="0.0"                'speed as km/h
bearing="75.0"            'cuorse as degrees
accuracy="2.0"            'accuracy of horizontal position fix in relation to used sattelites position as meter
it simulated a location somewhere in Germany, which is totally fine.

Now I've tried to put Lat/Lon values there -16.3000000 and -48.9300000 but the library doesn't like that and spits an error out that
java.lang.NumberFormatException: Invalid float: "0.6.000000"
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.initialParse(StringToReal.java:160)
at java.lang.StringToReal.parseFloat(StringToReal.java:323)
at java.lang.Float.parseFloat(Float.java:306)
at esolutions4you.B4A.moclocationprovider.moclocationprovider.publishMockLocation(moclocationprovider.java:95)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
I've tried to omit the negative sign and use ns="s" and we="w" but it still compained. Etc etc.

I'm trying for literal days now and have no clue on how to convert Lat/Lon to this format (it's not even normal decimal degress, it's something else).

Any help is welcome
 

Fusseldieb

Active Member
Licensed User
Longtime User
From memory, continents are moving (in different directions!) at 1-5 cm/year, so since 1984 that'd be like things have moved by a metre or so. Not sure how they cope with that with regards to property boundaries and suchlike. But there must be some system in place, like there is on maps where they note how much magnetic north is moving per year.
Ahahaha, that's very unlikely the case. I don't think the continent I live on shifts up to 200m while I'm running it through the formula :p
 
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
First thing to try: use Doubles, not Floats.

Floats only accurate to 1 part in 16 million, so you've already lost a couple of metres just in that.
Thanks for the tip. I thought it could be it, but... nope.

I tried following now:

B4X:
Sub GetDMS(val As Double) As String

    Dim valDeg As Double
    Dim valMin As Double
    Dim valSec As Double
    Dim result As String

    val = Abs(val)

    valDeg = Floor(val)
    result = valDeg

    valMin = Floor((val - valDeg) * 60.0F)
    result = result & valMin & "."

    valSec = Round((val - valDeg - valMin / 60.0F) * 3600.0F * 100000.0F)
    result = result & valSec

    Return result
End Sub

Using double, then I tried adding ".0" (maybe it 'rounds' without it, like C++?), then I tried adding "F". None helped. It stays quietly 200m away from me. No jumping, nothing. It stays there and moves +-1m occasionally. Something's still off.

Einstein here. What was I thinking in previous post?!?!?!
Ahahahaha...
 
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
Or "Aaaaaahhhhhh" (Tarzan falling from vine) ?
Well, that I'll certainly do in a couple of hours when I need to go to work without any sleep. Sometimes I really hate programming, but okay.
Some sacrifices are needed.

And I'm still clueless where I messes up here...
 
Upvote 0

emexes

Expert
Licensed User
Something like this might do the job:
B4X:
Sub GetDegreesMinutes(val As Double) As Double

    val = Abs(val)

    Dim valDeg As Double = Floor(val)    'whole degree
    Dim valMin As Double = val - valDeg    'fraction of degree

    return valDeg * 100 + valMin * 60

End Sub

'then

Dim LatitudeDDMM As String = FormatNumber2(GetDegreesMinutes(LongitudeDegrees), 2+2, 4, 4, False)
Dim LongitudeDDDMM As String = FormatNumber2(GetDegreesMinutes(LongitudeDegrees), 3+2, 4, 4, False)
 
Last edited:
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
The likely cause is that you are generating degrees-minutes-seconds but the mock location function is expecting degrees-minutes.
ABSOLUTE MADMAN, YOU ARE!

It worked! I've totally overseen it on the source.

Thank you!!!

The code is now as follows:

B4X:
Sub ConvertLatLon(lat As Float,lng As Float) As String
    Dim latResult As String
    Dim lngResult As String
    Dim dmsResult As String

    If(lat >=0) Then
        latResult = "N"
    Else
        latResult = "S"
    End If

    latResult = latResult & GetDMS(lat)

    If(lng >=0) Then
        lngResult = "E"
    Else
        lngResult = "W"
    End If
    If (lng < 100) Then
        lngResult = lngResult & "0"
    End If
  
    lngResult = lngResult & GetDMS(lng)

    dmsResult = latResult & " " & lngResult

    Return dmsResult
End Sub

Sub GetDMS(val As Double) As String

    Dim valDeg As Double
    Dim valMin As Double
    Dim result As String

    val = Abs(val)

    valDeg = Floor(val)
    result = valDeg

    valMin = ((val - valDeg) * 60.0)
    result = result & valMin
  
    Return result
End Sub
 
Last edited:
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
Something like this might do the job:
B4X:
Sub GetDegreesMinutes(val As Double) As Double

    Dim valDeg As Double
    Dim valMin As Double

    val = Abs(val)

    valDeg = Floor(val)    'whole degree
    valMin = val - valDeg    'fraction of degree

    return valDeg * 100 + valMin * 60

End Sub

'then

Dim LatitudeDDMM As String = FormatNumber2(GetDegreesMinutes(LongitudeDegrees), 2, 4, 4, False)
Dim LongitudeDDDMM As String = FormatNumber2(GetDegreesMinutes(LongitudeDegrees), 3, 4, 4, False)

Oh! I think we worked on the same thing at the same time.... hahaha
 
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
This is going to bite you when the minutes component is < 10 ie single digit.
And how can I overcome this?
I saw you're using NumberFormat. Are you prepending a zero?

Sorry the loss of attention, I'm not exactly fit anymore :p
 
Upvote 0

emexes

Expert
Licensed User
Sorry the loss of attention, I'm not exactly fit anymore :p
I'm afraid that comment made me laugh too...
And how can I overcome this?
Use my routine to convert the D.D to DMM.M, add the leading zeroes and round the trailing digits using NumberFormat2, then add the NSEW letter to the end.
I saw you're using NumberFormat. Are you prepending a zero?
I think so, but I haven't actually tested it. The second parameter specifies the minimum (ie, at least this many) digits before the decimal point... ugh, just realised I'd made a mistake, forgot about the 2 digits for minutes... now fixed...
 
Upvote 0

Fusseldieb

Active Member
Licensed User
Longtime User
I've adapted your snipped and settled with this:

B4X:
Sub ConvertLatLon(lat As Float,lng As Float) As String
    Dim latResult As String
    Dim lngResult As String

    If(lat >=0) Then
        latResult = "N"
    Else
        latResult = "S"
    End If

    If(lng >=0) Then
        lngResult = "E"
    Else
        lngResult = "W"
    End If

    latResult = latResult & NumberFormat2(GetDegreesMinutes(lat), 2+2, 4, 4, False)
    lngResult = lngResult & NumberFormat2(GetDegreesMinutes(lng), 3+2, 4, 4, False)
   
    Return latResult & " " & lngResult
   
End Sub

Sub GetDegreesMinutes(val As Double) As Double

    val = Abs(val)

    Dim valDeg As Double = Floor(val)    'whole degree
    Dim valMin As Double = val - valDeg    'fraction of degree

    Return valDeg * 100 + valMin * 60
End Sub
It seems to work exactly like it should. I'm too tired to see any problems on this now. So if your alarm bells ring, let me know...
 
Upvote 0

emexes

Expert
Licensed User
B4X:
Sub GetDegreesMinutes(val As Double, IsLatitudeFlag As Boolean) As String

    val = Abs(val)

    Dim valDeg As Double = Floor(val)    'whole degree
    Dim valMin As Double = val - valDeg    'fraction of degree

    Dim NumLeadingDigits As Int

    If IsLatitudeFlag Then
        NumLeadingDigits = 2 + 2
    Else
        NumLeadingDigits = 3 + 2
    End if

    Return NumberFormat2(valDeg * 100 + valMin * 60, NumLeadingDigits, 4, 4, False)

End Sub

Sub GetCompassLetter(val As Double, IsLatitudeFlag As Boolean) As String

    Dim NegPosCompassLetters As String
 
    If IsLatitudeFlag Then
        NegPosCompassLetters = "SN"
    Else
        NegPosCompassLetters = "EW"
    End if

    Dim CompassLetter As String

    If val < 0 Then
        CompassLetter = NegPosCompassLetters.CharAt(0)
    Else
        CompassLetter = NegPosCompassLetters.CharAt(1)
    End If

    Return CompassLetter

End Sub

'then

latitude = GetDegreesMinutes(LatitudeDegrees, True)
ns = GetCompassLetter(LatitudeDegrees, True)

longitude = GetDegreesMinutes(LongitudeDegrees, False)
we = GetCompassLetter(LongitudeDegrees, False)
Tested as thoroughly as usual (ie, not) but... what could possibly go wrong???!
 
Upvote 0

emexes

Expert
Licensed User
It seems to work exactly like it should. I'm too tired to see any problems on this now. So if your alarm bells ring, let me know...
Looks good, except that in the original post, the numbers and the compass letters were separate. But that's not wrong, just not as convenient (for this particular library).
 
Upvote 0
Top