Android Question How to get Magnetic Declination from the GPS location services

Angel Maza

Member
Licensed User
The GPS locations service has functions to get Lat, Lon, Bearing, Speed, etc. What seems to be missing is a way to get the magnetic declination. I tried the code below to use the native java function but it gives a compiler error code.

How can I get the magnetic Declination at a specified Lat/Lon/Altitude?

Thanks in advance!

Compiler error:
B4X:
Generating R file.    (0.69s)
Compiling generated Java code.    Error
javac 1.8.0_181
src\com\calypsoinstruments\CalypsoUltrasonicAPI\main.java:1124: error: cannot find symbol
    GeomagneticField mGeoField = new GeomagneticField(Lat, Lon, Altitude, Millis);
    ^
  symbol:   class GeomagneticField
  location: class main
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
1 error
B4a code:
B4X:
Public gpsManager As GPS
Public javaInline As JavaObject
..
gpsManager.Initialize("GPS")
Starter.javaInline.InitializeContext
...

Sub GPS_LocationChanged(myLocation As Location)
    ' store the current location data in the global dictionary 'sensorData'
    sensorData.Put("LAT", myLocation.Latitude)
    sensorData.Put("LON", myLocation.Longitude)
    If myLocation.BearingValid Then
        sensorData.Put("COG", myLocation.Speed)
    Else
        sensorData.Put("COG", 0.0)
    End If
    If myLocation.SpeedValid Then
        sensorData.Put("SOG", myLocation.Bearing)
    Else
        sensorData.Put("SOG", 0.0)
    End If
    If myLocation.AccuracyValid Then
        sensorData.Put("STATUS", myLocation.Accuracy)
    Else
        sensorData.Put("STATUS", 0.0)
    End If
    If myLocation.AltitudeValid Then
        sensorData.Put("ALT", myLocation.Altitude)
    Else
        sensorData.Put("ALT", 10.0)
    End If
    If localDeclination = 999 Then
        localDeclination = magDeclination ' get the magnetic delication at the current location & altitude
    End If
    sensorData.Put("DEC", localDeclination)   
End Sub


Sub magDeclination() As Float
    ' get the magnetic declination for the current location
    Dim magDec As Float = 0.0              ' default value
    #if B4A
        Dim millis As Long = DateTime.Now
        magDec = javaInline.RunMethod("getDeclination", Array As Object(sensorData.Get("LAT"), sensorData.Get("LON"), sensorData.Get("ALT"), millis))
        Log("Starter->magDeclination(): mag Declination = " & magDec & " | " & millis)
    #end if
    Return magDec
End Sub

#If JAVA
public float getDeclination(float Lat, float Lon, float Altitude, long Millis) {
   GeomagneticField mGeoField = new GeomagneticField(Lat, Lon, Altitude, Millis);
    return mGeoField.getDeclination();   
}
#End If
 

DonManfred

Expert
Licensed User
error: cannot find symbol
GeomagneticField mGeoField = new GeomagneticField(Lat, Lon, Altitude, Millis);
^
symbol: class GeomagneticField
add a
B4X:
import android.hardware.GeomagneticField;
to the beginning of the inline java
 

Angel Maza

Member
Licensed User
DonManfred,
that got rid of the Compiler error. Now I get the run-time error (java.lang.RuntimeException: Method: getDeclination not matched).

Any suggestions?

B4X:
Logger connected to:  motorola Moto G (5) Plus
--------- beginning of crash
--------- beginning of system
--------- beginning of main
*** Service (starter) Create ***
Initialize: alpha = 0  smoothing: 0
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
Main->Create_User_Preference_Screen(): Creating the User Preferences Screen for the first time...
** Activity (main) Resume **
Initialize: alpha = 0.3499999940395355  smoothing: 0.3499999940395355
Main->Launch_Background_Services(): pref Mac: C7:59:53:20:73:F9
starter_magdeclination (java line: 1057)
java.lang.RuntimeException: Method: getDeclination not matched.
    at anywheresoftware.b4j.object.JavaObject.RunMethod(JavaObject.java:129)
    at com.calypsoinstruments.CalypsoUltrasonicAPI.starter._magdeclination(starter.java:1057)
    at com.calypsoinstruments.CalypsoUltrasonicAPI.starter._gps_locationchanged(starter.java:1029)
    at java.lang.reflect.Method.invoke(Native Method)
    at anywheresoftware.b4a.BA.raiseEvent2(BA.java:191)
    at anywheresoftware.b4a.BA.raiseEvent(BA.java:171)
    at anywheresoftware.b4a.gps.GPS$1.onLocationChanged(GPS.java:65)
    at android.location.LocationManager$ListenerTransport._handleMessage(LocationManager.java:297)
    at android.location.LocationManager$ListenerTransport.-wrap0(LocationManager.java)
    at android.location.LocationManager$ListenerTransport$1.handleMessage(LocationManager.java:242)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6123)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
 

DonManfred

Expert
Licensed User

Angel Maza

Member
Licensed User
I thought that's what I'm doing in the Java Code section. Please note that I tried and renamed the function to getDeclinationJava() to differentiate it from the GeometricField method getDeclination(). The error reads now "java.lang.RuntimeException: Method: getDeclinationJava not matched." Thus it looks like B4a has a problem finding the native Java code function getDeclinationJava().

Thoughts?


native Java Code section in Main():
B4X:
#If JAVA
public float getDeclinationJava(float Lat, float Lon, float Altitude, long Millis) {
    import android.hardware.GeomagneticField;                                                    // import the GeomagneticField class
    GeomagneticField mGeoField = new GeomagneticField(Lat, Lon, Altitude, Millis);    // initialize the class
    return mGeoField.getDeclination();                                                               // call the getDeclination() method
}
#End If
My B4a code:
B4X:
in Starter()
Public javaInline As JavaObject
..
magDec = javaInline.RunMethod("getDeclinationJava", Array As Object(sensorData.Get("LAT"), sensorData.Get("LON"), sensorData.Get("ALT"), millis))
in Main()
Starter.javaInline.InitializeContext
[/CODE]
 

JordiCP

Well-Known Member
Licensed User
"Not matched" means that it is expecting a different signature that the one it is receiving.
Your function expects (float,float,float,long) and your data (Lat, Lon, Alt) is double
You can change it this way
B4X:
public float getDeclinationJava(double Lat, double Lon, double Altitude, long Millis) {
   GeomagneticField mGeoField = new GeomagneticField((float)Lat, (float)Lon, (float)Altitude, Millis);
    return mGeoField.getDeclination();  
}
 
Top