我无尽的后台服务在几个小时后自动停止为什么?

如何解决我无尽的后台服务在几个小时后自动停止为什么?

我的无限前台服务在 3 到 4 小时后自动停止,没有任何问题吗? LatLong 在服务器中连续保存 3-4 小时,但随机关闭或销毁服务,我不知道如何处理此问题?

class MyEndlessService : Service(),DatabaseListenerCallback {

private var wakeLock: PowerManager.WakeLock? = null
private var isServiceStarted = false
var TAG = "MyService"
var gps_status = 1
var editor: SharedPreferences.Editor? = null
var prevIoUsBestLocation: Location? = null
var apiInterface: GetDataService? = null
private var googleapiclient: Googleapiclient? = null
private var lastLocation: Location? = null
private var locationRequest: LocationRequest? = null
private val UPDATE_INTERVAL = 10000
private val FASTEST_INTERVAL = UPDATE_INTERVAL / 2
var locationManager: LocationManager? = null
var isFirsttime = true
var sharedPreferences: SharedPreferences? = null

override fun onBind(intent: Intent): IBinder? {
    return null
}

override fun onStartCommand(intent: Intent?,flags: Int,startId: Int): Int {
    log("onStartCommand executed with startId: $startId")
    if (intent != null) {
        val action = intent.action
        log("using an intent with action $action")
        when (action) {
            Actions.START.name -> startService()
            Actions.STOP.name -> stopService()
            else -> log("This should never happen. No action in the received intent")
        }
    } else {
        log(
            "with a null intent. It has been probably restarted by the system."
        )
    }
    return START_STICKY
}

override fun onCreate() {
    super.onCreate()
    log("The service has been created".toupperCase())
    val notification = createNotification()
    startForeground(1,notification)
}

override fun onDestroy() {
    super.onDestroy()
    log("The service has been destroyed".toupperCase())
    val calendar = Calendar.getInstance()
    val mdformat = SimpleDateFormat("HH:mm:ss")
    val strDate = mdformat.format(calendar.time)
    LocalDatabaseForException(applicationContext,strDate,"Service Destroyed").execute()
    val broadcastIntent = Intent()
    broadcastIntent.action = "restartservice"
    broadcastIntent.setClass(this,Restarter::class.java)
    this.sendbroadcast(broadcastIntent)
}

override fun onTaskRemoved(rootIntent: Intent) {
    val restartServiceIntent = Intent(applicationContext,MyEndlessService::class.java).also {
        it.setPackage(packageName)
    };
    val restartServicePendingIntent: PendingIntent = PendingIntent.getService(
        this,1,restartServiceIntent,PendingIntent.FLAG_ONE_SHOT
    );
    applicationContext.getSystemService(Context.ALARM_SERVICE);
    val alarmService: AlarmManager = applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager;
    alarmService.set(
        AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + 1000,restartServicePendingIntent
    );
}

private fun startService() {

    val calendar = Calendar.getInstance()
    val mdformat = SimpleDateFormat("HH:mm:ss")
    val strDate = mdformat.format(calendar.time)
    LocalDatabaseForException(applicationContext,"Service Started").execute()

    if (isServiceStarted) return
    log("Starting the foreground service task")
  //  Toast.makeText(this,"Service starting its task",Toast.LENGTH_SHORT).show()
    isServiceStarted = true
    setServiceState(this,ServiceState.STARTED)

    // we need this lock so our service gets not affected by Doze Mode
    wakeLock =
        (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
            newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"EndlessService::lock").apply {
                acquire()
            }
        }
    // we're starting a loop in a coroutine
    GlobalScope.launch(dispatchers.IO) {
        while (isServiceStarted) {
            launch(dispatchers.IO) {
                pingFakeServer()
                handleUserTracking()
            }
            delay(1000)
        }
        log("End of the loop for the service")
    }
}

private fun stopService() {
    log("Stopping the foreground service")
  //  Toast.makeText(this,"Service stopping",Toast.LENGTH_SHORT).show()
    val calendar = Calendar.getInstance()
    val mdformat = SimpleDateFormat("HH:mm:ss")
    val strDate = mdformat.format(calendar.time)
    LocalDatabaseForException(applicationContext,"Service Stopped").execute()
    try {
        wakeLock?.let {
            if (it.isHeld) {
               // startService()
                it.release()
            }
        }
      // stopForeground(true)
     //   stopSelf()
    } catch (e: Exception) {
        log("Service stopped without being started: ${e.message}")
        val calendar = Calendar.getInstance()
        val mdformat = SimpleDateFormat("HH:mm:ss")
        val strDate = mdformat.format(calendar.time)
        LocalDatabaseForException(applicationContext,"Service stopped without being started: ${e.message}").execute()
    }
    isServiceStarted = false
    setServiceState(this,ServiceState.STARTED)
}

private fun pingFakeServer()  {
    SmartLocation.with(applicationContext).location()
        .start(object : OnLocationUpdatedListener {

            override fun onLocationUpdated(location: Location?) {
                val sharedPreferences = applicationContext.getSharedPreferences(
                    "Acesstoken",AppCompatActivity.MODE_MULTI_PROCESS
                )
                editor = getSharedPreferences("Acesstoken",MODE_PRIVATE).edit()
                editor = getSharedPreferences("Acesstoken",MODE_PRIVATE).edit()
                editor!!.putString("temp_lattitude",location!!.getLatitude().toString())
                editor!!.putString("temp_lattitude",location!!.getLatitude().toString())
                editor!!.apply()
                val att = sharedPreferences!!.getString("Attendance_ID","")
                val userid = sharedPreferences.getInt("User_ID",0).toString()
                if ((att != "") and (userid != "")) {
                    if (prevIoUsBestLocation != null) {
                        if (isBetterLocation(location,prevIoUsBestLocation)) {
                            prevIoUsBestLocation = location
                            onNewLocationAgainwithLocalDatabase(location)
                        }
                    } else {
                        prevIoUsBestLocation = location
                        onNewLocationAgainwithLocalDatabase(location)
                    }



                }
            }

        })

}


fun getBatteryPercentage(context: Context): Int {
    return if (Build.VERSION.SDK_INT >= 21) {
        val bm = context.getSystemService(BATTERY_SERVICE) as BatteryManager
        bm.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    } else {
        val iFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
        val batteryStatus = context.registerReceiver(null,iFilter)
        val level = batteryStatus?.getIntExtra(BatteryManager.EXTRA_LEVEL,-1) ?: -1
        val scale = batteryStatus?.getIntExtra(BatteryManager.EXTRA_SCALE,-1) ?: -1
        val batteryPct = level / scale.todouble()
        (batteryPct * 100).toInt()
    }
}


fun handleUserTracking() {
    val settings = applicationContext.getSharedPreferences("Acesstoken",MODE_PRIVATE)
    val manager = getSystemService(LOCATION_SERVICE) as LocationManager
    gps_status = 1
    if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        gps_status = 0
        editor = getSharedPreferences("Acesstoken",MODE_PRIVATE).edit()
        editor!!.putString("temp_lattitude","")
        editor!!.putString("temp_longitude","")
        editor!!.apply()
    }
 
    Log.d("Gps status ",gps_status.toString())
}

fun hitApitoUpdate(gpsstatus: Int?) {
    val settings = applicationContext.getSharedPreferences("Acesstoken",MODE_PRIVATE)
    val lattitude = settings.getString("temp_lattitude","")
    val longitude = settings.getString("temp_longitude","")
    val userID = settings.getInt("User_ID",0).toString()
    val access_token = settings.getString("Access_Token","")
    val battery_per = getBatteryPercentage(this)
    apiInterface = apiclient.getClient().create(GetDataService::class.java)
    val call = apiInterface!!.updateGpsstatus(
        "Bearer $access_token",gpsstatus,userID,lattitude,longitude,battery_per
    )
    call.enqueue(object : Callback<GpaStatusPojo> {
        override fun onResponse(call: Call<GpaStatusPojo>,response: Response<GpaStatusPojo>) {
            try {
                // Toast.makeText(applicationContext,""+response.body()!!.message,Toast.LENGTH_SHORT).show()
                Log.d("Gps status ",response.body()!!.message)
            } catch (e: java.lang.Exception) {
                val dfgdsdsdsfds = ""
                Log.d("Gps sttaus 22 :",e.toString())
            }
        }

        override fun onFailure(call: Call<GpaStatusPojo>,t: Throwable) {
            Log.d("Gps sttaus 33 :",t.toString())
        }
    })
}




private fun onNewLocationAgainwithLocalDatabase(location: Location) {
    val calendar = Calendar.getInstance()
    val mdformat = SimpleDateFormat("HH:mm:ss")
    val strDate = mdformat.format(calendar.time)
    LocalDatabaseInsert(location,applicationContext).execute()
    InsertLocationData(location,false,applicationContext).execute()
    getLocationList()
}


private fun getLocationList() {
    GetLocationData(applicationContext,this).execute()
}

override fun processData(locationData: MutableList<LocationParam>?) {
    hitApitoBulkEnter(locationData!!)
}

private fun hitApitoBulkEnter(location: List<LocationParam>) {
    if (!Utils.isNetworkConnected(this)) {
        Toast.makeText(
            this,"No internet connection available. Please check your internet connection.",Toast.LENGTH_SHORT
        ).show()
        startActivity(Intent(this,InternetSettingCheck::class.java))
        return
    }
   

     // send location to the server 
  
}


private fun readWebPageBulkTest(location: String,mTemp: List<LocationParam>) {
    if (!Utils.isNetworkConnected(this)) {
        Toast.makeText(
            this,InternetSettingCheck::class.java))
        return
    }
    val settings = applicationContext.getSharedPreferences("Acesstoken",MODE_PRIVATE)
    val access_token = settings.getString("Access_Token","")
    val user_id = settings.getInt("User_ID",0).toString()
    var attendance_id = settings.getString("Attendance_ID","")
    apiInterface = apiclient.getClient().create(GetDataService::class.java)
    if (attendance_id == "") {
        attendance_id = "0"
    }
    if (user_id != "") {
        val call: Call<NewLocationPojo> = apiInterface!!.updateLatLongforUserIDBulk(
            "Bearer $access_token",location
        )
        Log.e("JsonLocation  :",location)
        call.enqueue(object : Callback<NewLocationPojo> {
            override fun onResponse(
                call: Call<NewLocationPojo>,response: Response<NewLocationPojo>
            ) {
                try {
                    if (response.body()!!.status == "success") {
                        Log.e("Api response :",response.body()!!.status)
                        Toast.makeText(
                            this@MyEndlessService,"" + response.body()!!.status.toString(),Toast.LENGTH_SHORT
                        ).show()
                        updatelatlong(location,mTemp)
                    } else {
                        Toast.makeText(
                            this@MyEndlessService,Toast.LENGTH_SHORT
                        ).show()
                    }
                } catch (e: java.lang.Exception) {
                    Toast.makeText(this@MyEndlessService,"" + e.toString(),Toast.LENGTH_SHORT)
                        .show()
                    Log.e("ServerSam :",e.toString())
                }
            }

            override fun onFailure(call: Call<NewLocationPojo>,t: Throwable) {
                Log.e("ServerSam :",t.toString())
                log("The service has been destroyed".toupperCase())
                val calendar = Calendar.getInstance()
                val mdformat = SimpleDateFormat("HH:mm:ss")
                val strDate = mdformat.format(calendar.time)
                LocalDatabaseForException(applicationContext,"Api Error :"+t.toString() ).execute()
            }
        })
    }

}

private fun getPostFinal() {

    class GetTasks : AsyncTask<Void?,Void?,List<LocationParam>>() {

        override fun onPostExecute(tasks: List<LocationParam>) {
            super.onPostExecute(tasks)
            DeleteLocationData(applicationContext).execute()
            GetLocationData22().execute()
            // testDataAfterDeleteion();
        }

        override fun doInBackground(vararg params: Void?): List<LocationParam> {
            val taskList = DatabaseClient
                .getInstance(applicationContext)
                .appDatabase
                .locationDao()
                .all
            Log.e("Database after updation",taskList.toString())
            return taskList
        }
    }

    val gt = GetTasks()
    gt.execute()
}


internal class GetLocationData22 : AsyncTask<Void?,List<LocationParam>>() {
    var mContext: Context? = null


    override fun onPostExecute(tasks: List<LocationParam>) {
        super.onPostExecute(tasks)
    }

    override fun doInBackground(vararg params: Void?): List<LocationParam> {
        val taskList = DatabaseClient.getInstance(mContext)
            .appDatabase
            .locationDao()
            .all
        Log.d("GetAfterDeleteion :",taskList.toString())
        return taskList
    }
}


protected fun isBetterLocation(location: Location,currentBestLocation: Location?): Boolean {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true
    }

    // Check whether the new location fix is newer or older
    val timedelta = location.time - currentBestLocation.time
    val isSignificantlyNewer = timedelta > MyService66.TWO_MINUTES
    val isSignificantlyOlder = timedelta < -MyService66.TWO_MINUTES
    val isNewer = timedelta > 0

    // If it's been more than two minutes since the current location,use the new location
    // because the user has likely moved
    if (isSignificantlyNewer) {
        return true
        // If the new location is more than two minutes older,it must be worse
    } else if (isSignificantlyOlder) {
        return false
    }

    // Check whether the new location fix is more or less accurate
    val accuracyDelta = (location.accuracy - currentBestLocation.accuracy).toInt()
    val isLessAccurate = accuracyDelta > 0
    val isMoreAccurate = accuracyDelta < 0
    val isSignificantlyLessAccurate = accuracyDelta > 200
    // Check if the old and new location are from the same provider
    val isFromSameProvider: Boolean =
        isSameProvider(location.provider,currentBestLocation.provider)
    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true
    } else if (isNewer && !isLessAccurate) {
        return true
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true
    }
    return false
}


/**
 * Checks whether two providers are the same
 */
private fun isSameProvider(provider1: String?,provider2: String?): Boolean {
    return if (provider1 == null) {
        provider2 == null
    } else provider1 == provider2
}

private fun createNotification(): Notification {
    val notificationChannelId = "ENDLESS SERVICE CHANNEL"

    // depending on the Android API that we're dealing with we will have
    // to use a specific method to create the notification
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationmanager = getSystemService(Context.NOTIFICATION_SERVICE) as notificationmanager
        val channel = NotificationChannel(
            notificationChannelId,"Endless Service notifications channel",notificationmanager.IMPORTANCE_HIGH
        ).let {
            it.description = "Endless Service channel"
            it.enableLights(true)
            it.lightColor = Color.RED
            it.enableVibration(true)
            it.vibrationPattern = longArrayOf(100,200,300,400,500,400)
            it
        }
        notificationmanager.createNotificationChannel(channel)
    }

    val pendingIntent: PendingIntent = Intent(this,MainActivityFinal2::class.java).let { notificationIntent ->
        PendingIntent.getActivity(this,notificationIntent,0)
    }

    val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
        this,notificationChannelId
    ) else Notification.Builder(this)

    return builder
        .setContentTitle("Sapphire location on")
       // .setContentText("This is your favorite endless service working")
        .setContentIntent(pendingIntent)
        .setSmallIcon(R.mipmap.app_icon)
     //   .setTicker("Ticker text")
        .setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
        .build()
}

}

解决方法

服务可以被停止,并且很可能在某个时候被操作系统停止。根据文档

Android 系统仅在内存不足时停止服务,并且必须为用户关注的 Activity 恢复系统资源。如果服务绑定到一个以用户为焦点的活动,那么它被杀死的可能性就较小;如果服务被声明为在前台运行,它很少被杀死。如果服务启动并长时间运行,系统会随着时间的推移降低其在后台任务列表中的位置,并且服务变得非常容易被杀死——如果您的服务已启动,您必须将其设计为优雅地处理重启系统。如果系统终止了您的服务,它会在资源可用时立即重新启动它,但这也取决于您从 onStartCommand() 返回的值。

重新启动服务的最佳做法是将服务声明为 STICKY_SERVICE 中的 onStartCommand()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?