调用 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
协议。但是应该关心哪个位置服务正在设置其位置(GPS
、GLONASS
、GALILEO
?)。在这种情况下,我可以随意使用 GNRMC
,因为它广泛可用。
目前,我正在开发一个 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
协议。但是应该关心哪个位置服务正在设置其位置(GPS
、GLONASS
、GALILEO
?)。在这种情况下,我可以随意使用 GNRMC
,因为它广泛可用。