我也创建了服务和Firebase工作服务。当应用程序关闭时,它们可以完美运行。 我希望每分钟获取用户的位置,并在应用程序关闭时发送到服务器这是我的工作服务:
class NeverEndingJob : JobService() {
var counter = 0
var TAG = "NeverEndingJOb"
private val NOTIFICATION_ID = 404
private val CHANNEL_ID = "AppC"
internal var name: CharSequence = "AppC"
internal var importance: Int = 0
internal var mChannel: NotificationChannel? = null
internal var mNotificationManager: NotificationManager? = null
private var mLocationManager: LocationManager? = null
private var owner: ICapture? = null
var model :MyRestModel? = null
var notificationManager: NotificationManagerCompat? = null
private var mLocationListeners = arrayOf(LocationListener(LocationManager.GPS_PROVIDER), LocationListener(LocationManager.NETWORK_PROVIDER))
init {
MLog.d(TAG,"job created")
}
override fun onCreate() {
super.onCreate()
mNotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
importance = NotificationManager.IMPORTANCE_MIN
mChannel = NotificationChannel(CHANNEL_ID, name, importance)
mNotificationManager!!.createNotificationChannel(mChannel)
}
}
override fun onStopJob(job: JobParameters?): Boolean {
MLog.d(TAG,"job destroy")
val intent = Intent("app.name.RestartService")
sendBroadcast(intent)
stopTimer()
return true
}
override fun onStartJob(job: JobParameters?): Boolean {
mNotificationManager!!.notify(NOTIFICATION_ID, getNotification(R.string.working.getResource()))
startForeground(NOTIFICATION_ID, getNotification(R.string.working.getResource()))
startTimer()
return true
}
private var timer: Timer? = null
private var timerTask: TimerTask? = null
var oldTime: Long = 0
companion object {
private val TAG = "AppC"
private var LOCATION_INTERVAL:Long = 0
private var LOCATION_DISTANCE = 10f
}
private fun startTimer(){
timer = Timer()
initializeTimerTask()
val apiService = ApiService(Handler())
App.courInfo = Prefs.instance(App.preferences).getCourierLocInfo()
notificationManager = NotificationManagerCompat.from(this);
model = MyRestModel(apiService)
model!!.apiCallback = ApiCallback()
Log.e(TAG, "onCreate")
initializeLocationManager()
setLocationUpdates()
timer!!.schedule(timerTask, NeverEndingJob.LOCATION_INTERVAL, NeverEndingJob.LOCATION_INTERVAL) //
}
internal var mLastLocation: Location =Location(LocationManager.NETWORK_PROVIDER)
fun initializeTimerTask() {
timerTask = object : TimerTask() {
override fun run() {
Handler(Looper.getMainLooper()).post {
setLocationUpdates()
}
}
}
}
private fun stopTimer(){
if (timer != null) {
timer?.cancel();
timer = null;
}
}
private fun getNotification(title : String): Notification {
Log.d(TAG, "create notofication")
val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
NotificationCompat.Builder(this, CHANNEL_ID)
else
NotificationCompat.Builder(this)
builder.setSmallIcon(R.mipmap.ic_launcher)
.setWhen(0)
builder.setContentTitle(title)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher, null))
val not: Notification
not = builder.setOngoing(true).build()
return not
}
private inner class LocationListener(provider: String) : android.location.LocationListener {
init {
Log.e(TAG, "LocationListener $provider")
mLastLocation = Location(provider)
}
override fun onLocationChanged(location: Location) {
Log.e(TAG, "onLocationChanged: $location")
try{
val distance = location.distanceTo(mLastLocation)
mNotificationManager!!.notify(NOTIFICATION_ID, getNotification("${R.string.get_location.getResource()} Метр: ${distance.toInt()}"))
Handler().postDelayed({
mNotificationManager!!.notify(NOTIFICATION_ID, getNotification(R.string.working.getResource()))
},3000)
Log.e(TAG,"distance"+ "$distance")
if (distance > 10){
mLastLocation = location
sendLocation(mLastLocation)
}
Prefs.instance(App.preferences).setLastLocate(location)
Prefs.instance(App.preferences).setLastLocate(location)
}catch (e :java.lang.Exception){
Log.e(TAG, "send http lat lon exception: $e")
}
mLastLocation.set(location)
}
override fun onProviderDisabled(provider: String) {
Log.e(TAG, "onProviderDisabled: $provider")
}
override fun onProviderEnabled(provider: String) {
Log.e(TAG, "onProviderEnabled: $provider")
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {
Log.e(TAG, "onStatusChanged: $provider")
}
}
fun sendLocation(location : Location){
Log.e(TAG, "ready for send http lat lon $location ")
val currentTime = Functions.calculateDifference(System.currentTimeMillis())
Log.e(TAG, "get current time $currentTime ")
if (App.courInfo != null){
Log.e(TAG, "get open time ${App.courInfo!!.startTime} ")
Log.e(TAG, "get close time ${App.courInfo!!.endTime} ")
val startTime = App.courInfo!!.startTime
val endTime = App.courInfo!!.endTime
val isHourLess =currentTime.hour.toInt() > startTime.hour.toInt()
val isHourLessEqual =currentTime.hour.toInt() == startTime.hour.toInt()
val isMinLess = currentTime.minute.toInt() >= startTime.minute.toInt()
val isHourMore =currentTime.hour.toInt() < endTime.hour.toInt()
val isHourMoreEqual =currentTime.hour.toInt() == endTime.hour.toInt()
val isMinMore = currentTime.minute.toInt() <= endTime.minute.toInt()
if (isHourLess && isHourMore){
if (model != null){
model!!.setLocation(App.userData!!.phone, App.userData!!.token, App.userData!!.cId,location.latitude.toString(),location.longitude.toString())
}
}else if (isHourLessEqual && isHourMore){
if (isMinLess){
if (model != null){
model!!.setLocation(App.userData!!.phone, App.userData!!.token, App.userData!!.cId,location.latitude.toString(),location.longitude.toString())
}
}
}else if (isHourLess && isHourMoreEqual){
if (isMinMore){
if (model != null){
model!!.setLocation(App.userData!!.phone, App.userData!!.token, App.userData!!.cId,location.latitude.toString(),location.longitude.toString())
}
}
}
}
}
private fun initializeLocationManager() {
Log.e(TAG, "initializeLocationManager")
mLocationManager = applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
}
fun setLocationUpdates(){
try {
val locInfo = Prefs.instance(App.preferences).getCourierLocInfo()
if (locInfo != null){
NeverEndingJob.LOCATION_INTERVAL = 3000
NeverEndingJob.LOCATION_DISTANCE = locInfo.metres.toFloat()
}
Log.e(TAG, "onCreate $locInfo")
mLocationManager!!.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 0.toFloat(),
mLocationListeners[1])
} catch (ex: java.lang.SecurityException) {
Log.i(TAG, "fail to request location update, ignore", ex)
} catch (ex: IllegalArgumentException) {
Log.d(TAG, "network provider does not exist, " + ex.message)
}
}
inner class ApiCallback : ApiService.Callback{
override fun onSuccess(result: String) {
mNotificationManager!!.notify(NOTIFICATION_ID, getNotification(R.string.success_sended.getResource()))
Handler().postDelayed({
mNotificationManager!!.notify(NOTIFICATION_ID, getNotification(R.string.working.getResource()))
},3000)
通知管理器!.notify(1,mBuilder.build((( }
override fun onFail(failure: String) {
Log.e(TAG, "onFail $failure")
}
}
fun clearLocationListeners(){
if (mLocationManager != null) {
for (i in mLocationListeners.indices) {
try {
mLocationManager!!.removeUpdates(mLocationListeners[i])
} catch (ex: Exception) {
Log.i(NeverEndingJob.TAG, "fail to remove location listners, ignore", ex)
}
}
}
}
}
打开应用程序时,此代码可以完美运行,每次将位置发送到服务器,但是当我关闭应用程序时,服务每分钟都工作一次,告诉我您应该获取位置,但是onLocation更改未调用:
timerTask = object : TimerTask() {
override fun run() {
Handler(Looper.getMainLooper()).post {
setLocationUpdates()
}
}
}
清单:
<service
android:name=".service.NeverEndingJob"
android:enabled="true">
<!--<intent-filter>-->
<!--<action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>-->
<!--</intent-filter>-->
</service>
<receiver
android:name=".service.RestartService"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped">
<intent-filter>
<action android:name="app.name.RestartService" />
<action android:name="android.net.wifi.STATE_CHANGE" />
<!--<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />-->
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
接收器
class RestartService : BroadcastReceiver() {
var TAG = "RestartService"
override fun onReceive(p0: Context?, p1: Intent?) {
MLog.d(TAG,"service stopppedd")
val dispatcher = FirebaseJobDispatcher(GooglePlayDriver(p0))
val job = dispatcher
.newJobBuilder()
.setService(NeverEndingJob::class.java)
.setTag("AppC-Bg-Job")
.setRecurring(false)
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(0,0))
.setReplaceCurrent(false)
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setConstraints(Constraint.ON_ANY_NETWORK)
.build()
dispatcher.mustSchedule(job)
}
}
活动:
lateinit var dispatcher: FirebaseJobDispatcher
private fun startLocationService() {
dispatcher = FirebaseJobDispatcher(GooglePlayDriver(this))
val job = dispatcher
.newJobBuilder()
.setService(NeverEndingJob::class.java)
.setTag("Bringo-Couirer-Bg-Job")
.setRecurring(false)
.setLifetime(Lifetime.FOREVER)
.setTrigger(Trigger.executionWindow(0, 0))
.setReplaceCurrent(false)
.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
.setConstraints(Constraint.ON_ANY_NETWORK)
.build()
dispatcher.mustSchedule(job)
}
override fun onDestroy() {
super.onDestroy()
dispatcher.cancelAll()
}
为什么在活动服务中关闭应用程序几分钟后未调用位置更改?
我认为您需要使用位置管理器。
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER,
2000,
10, this);
第一个参数是您正在使用的提供程序(在本例中为 GPS 提供程序(。第二个参数 (2000( 是每次更新之间的最短时间(以毫秒为单位(。第三个参数 (10( 是最小距离。最后一个参数是你的位置侦听器(this(。
在用户关闭 GPS 的情况下实现 onProviderDisabled 也是一个好主意。
在服务中替代此方法
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Utils.showLog("onTaskedremoved called");
PendingIntent service = PendingIntent.getService(
getApplicationContext(),
1001,
new Intent(getApplicationContext(), ''your service name''.class),
PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
}