【发布时间】:2020-03-12 22:59:50
【问题描述】:
当我的应用程序运行时,我需要在后台访问位置。
当我的主要活动实现时,我成功接收到位置更新android.location.LocationListener
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
val criteria = Criteria()
val provider = locationManager.getBestProvider(criteria, false)
val location = locationManager.getLastKnownLocation(provider)
locationManager.requestLocationUpdates(provider, 5000, 20f, this)
setLocation(location)
} else {
/* ... */
}
但是我尝试将此代码添加到新的服务类(同时实现android.app.Service 和android.location.LocationListener),并且onLocationChanged 函数仅在应用程序处于视图中时触发。
我认为这个问题可能是以下问题之一:
我想我在某处读到过,我必须在服务内手动创建一个新线程,这样它就不会在与主要活动相同的线程上运行。这可能是问题所在,但我不知道如何做到这一点。我是 android 开发和 Kotlin 的新手。
我想我在某处读到,在后台访问位置时,我当前请求的位置权限不够,但找不到要更改的内容。
我在某处看到了一个解决方案,他们创建了一个每隔几秒运行一次的计时器,并从位置管理器手动请求最后一个位置。我没有对此进行测试,但如果它确实有效,它并不能满足我的需求。
requestLocationUpdates允许我配置最短时间和最短距离。当然我可以手动添加距离检查,但这可能会影响电池寿命和性能。
我该如何解决这个问题?
(如果有人不熟悉 Kotlin,我可以将任何 Java 代码更改为 Kotlin)
编辑 1
我的服务肯定在运行,因为位置更新是在前台接收的
这是我的服务的
onStartCommand代码:
override fun onStartCommand(intent: Intent, flags: Int, startid: Int): Int {
/* request location updates as above */
return START_STICKY
}
- 这是我在主要活动中启动服务的方式:
val serviceIntent = Intent(applicationContext, OnTheFlyLandmarkService::class.java)
startService(serviceIntent)
编辑 2
-
我还读到我需要显示一条通知,让用户知道我的服务正在后台运行。我尝试了以下代码,但这没有帮助:
val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.messageicon) .setContentTitle("My app") .setContentText("Accessing location in background...") .setAutoCancel(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() with(NotificationManagerCompat.from(this)) { notify(id, notification) }
编辑 3
我尝试了@Michael 所说的:在服务内部调用startForeground 并传入通知。这不起作用,我什至没有看到通知。
override fun onStartCommand(intent: Intent, flags: Int, startid: Int): Int {
val notification = buildNotification("My app", "Accessing location in background...")
startForeground(NOTIFICATION_ID_SERVICE, notification)
/* request location updates */
return START_STICKY
}
【问题讨论】:
-
您可以添加您创建的
Service代码吗?你的Service是从前台运行开始的吗?是Sticky吗? -
@madlymad 我添加了代码,这是一个粘性服务
-
从 Android 8.0 开始,如果您的应用在后台运行,它每小时只会获得几次位置更新。如果这对您来说还不够,请改用foreground service。
-
@Michael 这对我不起作用。感谢您迄今为止的所有帮助
标签: android kotlin android-service android-location