调用 NMEA 侦听器,直到设置位置 Android

NMEA listener is called untill Location is Set Android

目前,我正在开发一个 GPS 应用程序,我需要一定程度的方向。当我添加 nmea 侦听器时,它只被调用一次。我正在使用 this and this 链接。但问题是,nmea listener 似乎只能工作一次。

class MainActivity : AppCompatActivity() {

private lateinit var locationManager: LocationManager

private var mOnNmeaMessageListener: OnNmeaMessageListener? = null

private var mLegacyNmeaListener: NmeaListener? = null

companion object {
    private const val PERMISSION_REQUEST_CODE = 1
    var counter  = 0
}


private fun nmeaProgress(rawNmea: String) {

    println("it is $rawNmea")
    //Here is the sample protocol example of   //$GPRMC,061244.00,A,4120.913656,N,06914.245043,E,1.0,118.8,040719,4.6,E,A*3F


    val rawNmeaSplit = rawNmea.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()

    if (rawNmeaSplit[0].equals("$GPRMC", ignoreCase = true)) {
        counter++
        val myString = rawNmeaSplit[0] + " , " + rawNmeaSplit[1] + " , " + rawNmeaSplit[2] + " , " +
                        rawNmeaSplit[3] + " , " + rawNmeaSplit[4] + " , " + rawNmeaSplit[5] + " , " +
                        rawNmeaSplit[6] + " , " + rawNmeaSplit[7] + " , " + rawNmeaSplit[8] + " , " +
                        rawNmeaSplit[9] + " , " + rawNmeaSplit[10] + " , " + rawNmeaSplit[11] + " , " + rawNmeaSplit[12] + ", $counter"
        message.text = myString

        val latitude = "Latitude: ${rawNmeaSplit[3]}"
        val longitude = "Longitude: ${rawNmeaSplit[5]}"
        val velocity = "Speed : ${rawNmeaSplit[7]}"
        val deg = "Degree : ${rawNmeaSplit[8]}"


        lat.text = longitude
        lng.text = latitude
        speed.text = velocity
        degree.text = deg

    }

}



override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    init()
}

private fun init() {
    val msg = "Data not received yet"
    lat.text = msg
    locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
}


@SuppressLint("MissingPermission")
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (grantResults.size != permissions.size) {
        Toast.makeText(this, "Please grant all permission", Toast.LENGTH_SHORT).show()
        finish()
    } else {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0.0f, locationListener)
        addNmeaListener()
    }

}

private val locationListener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location?) {


        //Will be implemented later

    }

    override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
        //
    }

    override fun onProviderEnabled(provider: String?) {
        //
    }

    override fun onProviderDisabled(provider: String?) {
        //
    }

}



override fun onResume() {
    super.onResume()
    requestUpdate()
}

private fun requestUpdate() {
    val list = arrayListOf<String>()

    if (ContextCompat.checkSelfPermission(
            applicationContext,
            Manifest.permission.ACCESS_FINE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        list.add(Manifest.permission.ACCESS_FINE_LOCATION)
    } else if (ContextCompat.checkSelfPermission(
            applicationContext,
            Manifest.permission.ACCESS_COARSE_LOCATION
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        list.add(Manifest.permission.ACCESS_COARSE_LOCATION)
    }

    val array = arrayOfNulls<String>(list.size)
    list.toArray(array)
    if (list.isEmpty()) {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 100, 0.0f, locationListener)
        //setNmeaListener()
        addNmeaListener()

    } else {
        ActivityCompat.requestPermissions(
            this,
            array,
            PERMISSION_REQUEST_CODE
        )
    }
}
private fun addNmeaListener() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        addNmeaListenerAndroidN()
    } else {
        addLegacyNmeaListener()
    }
}


@SuppressLint("MissingPermission")
@RequiresApi(api = Build.VERSION_CODES.N)
private fun addNmeaListenerAndroidN() {
    if (mOnNmeaMessageListener == null) {
        mOnNmeaMessageListener = OnNmeaMessageListener { message, timestamp ->
            nmeaProgress(message)
        }
    }
    locationManager.addNmeaListener(mOnNmeaMessageListener)
}


@SuppressLint("MissingPermission")
private fun addLegacyNmeaListener() {
    if (mLegacyNmeaListener == null) {
        mLegacyNmeaListener = NmeaListener { timestamp, nmea ->
            nmeaProgress(nmea)
        }
    }
    locationManager.addNmeaListener(mLegacyNmeaListener)
}

override fun onPause() {
    super.onPause()

    locationManager.removeUpdates(locationListener)

    removeNmeaListener()
}

private fun removeNmeaListener() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        if (mOnNmeaMessageListener != null) {
            locationManager.removeNmeaListener(mOnNmeaMessageListener)
        }
    } else {
        if (mLegacyNmeaListener != null) {
            locationManager.removeNmeaListener(mLegacyNmeaListener)
        }
    }
}

}

请注意轴承不是解决方案

更新

我已经测试过了,问题比较清楚了。它正在运行并完美地获取数据。更新UI(将此数据设置为对应的TextView)时会出现问题。如果位置不是由 GPS 设置的,传入的数据将被解析并放入 TextView 中,没有任何问题。但是当 LOCATION SET BY GPS 时,UI 不会更新。如果 GPS 再次搜索位置,则 UI 更新工作正常。我通过添加一个静态计数器和 logs

来检查它

它运行良好

欢迎任何帮助或建议。提前谢谢你

现在我知道了解决办法。问题出在 nmea 协议上。 GPRMC 在位置尚未固定时使用。位置固定后,不再使用GPRMC,可以参考GNRMC协议。但是应该关心哪个位置服务正在设置其位置(GPSGLONASSGALILEO?)。在这种情况下,我可以随意使用 GNRMC,因为它广泛可用。