androidkotlingpslocationnmea

How to get NMEA message **RMC or **GGA or **GSA Android


in this case, I have a problem with how to get NMEA message after we know how to get an NMEA message, the message looks like this

$GPGGA,073109.00,,,,,0,12,6.4,865.1,M,2.8,M,,*6B
$PGLOR,9,STA,073109.00,0.004,0.000,-2498,5,64,0,P,D,L,1,C,2,S,00100002,56,5,R,000833F4,TPEF,20,907631,LC,,,*64
$GPGSV,3,1,12,11,73,151,18,08,61,353,16,04,59,313,19,23,52,309,18*79
$GPGSV,3,2,12,01,37,182,15,22,34,193,15,27,31,019,26,03,31,220,15*77
$GPGSV,3,3,12,09,26,318,23,31,20,100,,14,16,146,19,16,04,027,*72
$GLGSV,2,1,07,68,43,211,15,81,34,040,21,69,33,280,15,67,12,163,18*69
$GLGSV,2,2,07,79,06,006,22,82,73,119,,83,34,192,*5D
$QZGSV,1,1,01,01,46,154,17*51
$GPGSA,A,1,,,,,,,,,,,,,10.3,8.0,6.4*08
$GNGSA,A,1,,,,,,,,,,,,,10.3,8.0,6.4*16
$GNGSA,A,1,,,,,,,,,,,,,10.3,8.0,6.4*16
$QZGSA,A,1,,,,,,,,,,,,,10.3,8.0,6.4*14
$IMGSA,A,1,,,,,,,,,,,,,10.3,8.0,6.4*1B
$GPRMC,073109.00,V,,,,,,,240220,,,N*77

and how to get an NMEA message to get $--RMC, $--GGA, $--GSA


Solution

  • if you curious how to get NMEA message you can look on this link maybe some people don't know how to get NMEA in the latest way, and I will explain it for the first, you need to add 2 permission

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    

    twice you need to make a class with implement 2 class it looks like this

    class NmeaActivity : AppCompatActivity(), LocationListener, OnNmeaMessageListener {
    }
    

    and after that, you need to make 2 variable that is for the permission and for LocationManager

    val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_ID = 0x10
    lateinit var locationManager : LocationManager
    var datanmea = ""
    

    third, you need to make a method to call NMEA listener and the location the method will look like this

    private fun initGPSgettingLogic() {
        this.locationManager =
            this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
    
        val gpsEnabled: Boolean = locationManager.isProviderEnabled(
            LocationManager.GPS_PROVIDER
        )
        if (gpsEnabled) { //GPS ON
            Log.d("NMEA_APP", javaClass.name + ":" + "GPS ON :)")
            if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Permission is not granted
                Log.d("NMEA_APP", javaClass.name + ":" + "Request Permission ")
                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_ID)
            }
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this)
            locationManager.addNmeaListener(this)
        } else { //GPS NOT ON
            Log.d("NMEA_APP", javaClass.name + ":" + "GPS NOT ON")
        }
    }
    

    forth, you need to call onNmeaMessage() to get the NMEA message we can get onNmeaMessage() by implementing the OnNmeaMessageListener without it we can't call the method and the code looks like this

    override fun onNmeaMessage(nmeamessage: String?, timestamp: Long) {
        Log.d(
            "NMEA_APP",
            javaClass.name + ":" + "[" + timestamp + "]" + nmeamessage+ ""
        )
        sendData(nmeamessage)
    }
    

    the message is on variable onNmeaMessage(nmeamessage: String?, timestamp: Long) we just need the nmeamessage to get the message and to get process the message I send it to method sendData(), if you want to show the NMEA message on TextView without processing the data you can append on Textview to show all message TextView.append(nmeamessage)

    the sendData() looks like this

    private fun sendData(nmea: String?) {
        var data = nmea?.substringBefore(",")
        var title = data?.substringAfter("$")
        var gen = title?.substring(2,5)
        if(gen == "GGA"){
            datanmea = ""
            datanmea += "$nmea\r\n"
        }
        if(gen == "GSA" || gen == "RMC"){
            datanmea += "$nmea\r\n"
        }
        if(gen == "RMC"){
            TextView.append(datanmea)
        }
    }
    

    because we just focus in $ we need to cut the , after it we need to cut the $ and then we cut from the char 2 to 5 and if we found GGA, GSA, RMC we just add it on variable datanmea and the message in one row will append, because RMC is on the last place I will append on TextView after getting all the message

    for the last step, you need to call initGPSgettingLogic() on method onCreate()

    and here is the complete code

    @RequiresApi(Build.VERSION_CODES.N)
    class NmeaActivity : AppCompatActivity(), LocationListener, OnNmeaMessageListener {
        val PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_ID = 0x10
        lateinit var locationManager : LocationManager
        var datanmea = ""
    
    override fun onCreate(savedInstanceState: Bundle?) {
        this.initGPSgettingLogic()
    }
    
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_ID -> {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.isNotEmpty()
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED
                ) { // granted
                    this.initGPSgettingLogic()
                } else { // denied,
                }
                return
            }
        }
    }
    
    private fun initGPSgettingLogic() {
        this.locationManager =
            this.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        val gpsEnabled: Boolean = locationManager.isProviderEnabled(
            LocationManager.GPS_PROVIDER
        )
        if (gpsEnabled) { //GPS ON
            Log.d("NMEA_APP", javaClass.name + ":" + "GPS ON :)")
            if (ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Permission is not granted
                Log.d("NMEA_APP", javaClass.name + ":" + "Request Permission ")
                // No explanation needed; request the permission
                ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION_ID)
            }
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10000f, this)
            locationManager.addNmeaListener(this)
        } else { //GPS NOT ON
            Log.d("NMEA_APP", javaClass.name + ":" + "GPS NOT ON")
        }
    
    }
    
    override fun onLocationChanged(location: Location?) {
    
    }
    override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
    
    }
    
    override fun onProviderEnabled(provider: String?) {
    
    }
    
    override fun onProviderDisabled(provider: String?) {
    
    }
    
    override fun onNmeaMessage(nmeamessage: String?, timestamp: Long) {
        Log.d(
            "NMEA_APP",
            javaClass.name + ":" + "[" + timestamp + "]" + nmeamessage+ ""
        )
        sendData(nmeamessage)
    }
    
    private fun sendData(nmea: String?) {
        var data = nmea?.substringBefore(",")
        var title = data?.substringAfter("$")
        var gen = title?.substring(2,5)
        if(gen == "GGA"){
            datanmea = ""
            datanmea += "$nmea\r\n"
        }
        if(gen == "GSA" || gen == "RMC"){
            datanmea += "$nmea\r\n"
        }
        if(gen == "RMC"){
            TextView.append(datanmea)
        }
    }
    }