我创建了一个应用程序,它使用 LocationManager requestUpdateLocations 每秒检索位置。
一开始,在不使用前台服务的情况下,当我关闭屏幕时,位置更新立即停止。
然后我设置了一个前台服务,它实现了 LocationListener 和 GpsStatus.Listener。 我在 MainActivity 中使用 startForegroundService 启动此服务,并在通知栏中创建通知。 (我还请求 ACCESS_BACKGROUND_LOCATION 权限,该权限已被授予,并且工作正常) 现在,当我关闭屏幕时,我在 onLocationChanged 中完美记录了背景位置,但仅记录了 60 秒。 60 秒后,我系统地收到事件 GpsStatus.GPS_EVENT_STOPPED 并且我没有更多位置更新。
因为Android 宣布对后台位置检索的限制,我尝试每 35 秒而不是每秒检索一次位置。但在持续 60 秒后,当我预计后台至少有 30 分钟的位置更新时,我仍然得到 GpsStatus.GPS_EVENT_STOPPED。 最重要的是,我预计位置更新不会再发生,但 GPS 不会完全停止,因此它可以在 1 小时后恢复(Android 说:“您每小时会收到几个位置”)
有谁知道为什么GPS在后台运行60秒后系统关闭? 当我收到 GPS_EVENT_STOPPED 事件时,有办法重新启动 GPS 吗? (我尝试调用locationManager.removeUpdates(myListener)和locationManager.removeGpsStatusListener(myListener),然后调用requestLocationUpdates和addGpsStatusListener,但无事可做,GPS不会重新启动...) 是否需要进行任何配置来防止 GPS 停止? 我是否必须将后台的服务“连接”到我的活动,以便 GPS 不会神奇地停止?
注意:我总是在真实设备上测试,而不是在模拟器上。
这是我的 MyService 课程:
class MyService: Service(), LocationListener, GpsStatus.Listener {
private var myTime: Long? = null
private var locationManager: LocationManager? = null
fun startGps() {
locationManager?.removeUpdates(this)
locationManager?.removeGpsStatusListener(this)
locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager?.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0f, this)
locationManager?.addGpsStatusListener(this)
}
override fun onCreate() {
startGps()
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val pendingIntent: PendingIntent =
Intent(this, MainActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, 0)
}
val channelId = createNotificationChannel("my_service_speed", "My Speed Background Service")
val notification: Notification = Notification.Builder(this, channelId)
.setContentTitle("notification_title")
.setContentText("notification_message")
.setSmallIcon(R.drawable.ic_speed_icon_24)
.setContentIntent(pendingIntent)
.setTicker("ticker_text")
.build()
// Notification ID cannot be 0.
startForeground(111555, notification)
return super.onStartCommand(intent, flags, startId)
}
private fun createNotificationChannel(channelId: String, channelName: String): String{
val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE)
chan.lightColor = Color.BLUE
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service.createNotificationChannel(chan)
return channelId
}
override fun onBind(p0: Intent?): IBinder? {
return null
}
override fun onLocationChanged(location: Location) {
if (location.hasSpeed()) {
var tTime = System.currentTimeMillis()
if (myTime == null) {
myTime = tTime
} else {
tTime = System.currentTimeMillis()
}
var bdSpeed = BigDecimal(location.speed * 3.6)
bdSpeed = bdSpeed.setScale(1, BigDecimal.ROUND_DOWN)
val speed: Double = bdSpeed.toDouble()
println("New Speed: ----> $speed Km/h at second ${(tTime - myTime!!) / 1000}s")
}
}
override fun onGpsStatusChanged(event: Int) {
when (event) {
GpsStatus.GPS_EVENT_SATELLITE_STATUS -> {
val gs = locationManager?.getGpsStatus(null)
var gpsSatsInFix = 0
gs?.let {
val iterator: Iterator<GpsSatellite> = gs.satellites.iterator()
while (iterator.hasNext()) {
val gpssatellite = iterator.next()
if (gpssatellite.usedInFix()) {
gpsSatsInFix++
}
}
}
println("GPS_EVENT_SATELLITE_STATUS --> Satellites used: $gpsSatsInFix / ${gs!!.satellites.count()} available")
}
GpsStatus.GPS_EVENT_FIRST_FIX -> {
println("GPS_EVENT_FIRST_FIX ---> Satellites search ...")
}
GpsStatus.GPS_EVENT_STOPPED -> {
println("GPS_EVENT_STOPPED ---> GAME OVER ...")
}
}
}
}
我的 MainActivity 类:
class MainActivity : AppCompatActivity() {
// ...
override fun onCreate(savedInstanceState: Bundle?) {
// ...
val mIntent = Intent(this, MyService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(mIntent)
}
// ...
}
// ...
}