0

我也创建了服务和 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)

notificationManager!!.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)
            }

        }
    }
}

}

此代码在打开应用程序时完美运行,将每次位置发送到服务器,但是当我关闭应用程序时,服务每分钟都在工作,告诉我你应该获取位置但 onLocationChanged 没有被调用:

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 调度程序: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()
}

为什么在活动服务中关闭应用程序几分钟后未调用 onLocationChanged?

4

1 回答 1

0

我认为您需要使用位置管理器。

LocationManager locationManager = (LocationManager) 
getSystemService(Context.LOCATION_SERVICE); 

locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER,
            2000,   
            10, this);

第一个参数是您正在使用的提供程序(在本例中为 GPS 提供程序)。第二个参数 (2000) 是每次更新之间的最短时间(以毫秒为单位)。第三个参数(10)是最小距离。最后一个参数是您的 LocationListener (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);
}
于 2018-06-14T12:05:00.157 回答