Android 我无休止的后台服务在几个小时后自动停止。为什么?
我的无休止的前台服务在3到4小时后自动停止,没有任何问题吗?LatLong在服务器上连续保存了3-4个小时,但随机关闭或销毁了服务,我不知道如何处理这个问题 类MyEndlessService:Service(),DatabaseListenerCallback{Android 我无休止的后台服务在几个小时后自动停止。为什么?,android,kotlin,service,background-service,Android,Kotlin,Service,Background Service,我的无休止的前台服务在3到4小时后自动停止,没有任何问题吗?LatLong在服务器上连续保存了3-4个小时,但随机关闭或销毁了服务,我不知道如何处理这个问题 类MyEndlessService:Service(),DatabaseListenerCallback{ private var wakeLock: PowerManager.WakeLock? = null private var isServiceStarted = false var TAG = "MyService&qu
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,strDate,"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,strDate,"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,strDate,"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, strDate, applicationContext).execute()
InsertLocationData(location, false, strDate, 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,
"No internet connection available. Please check your internet connection.",
Toast.LENGTH_SHORT
).show()
startActivity(Intent(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,
"" + response.body()!!.status.toString(),
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,strDate,"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?, 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, 300, 200, 400)
it
}
notificationManager.createNotificationChannel(channel)
}
val pendingIntent: PendingIntent = Intent(this, MainActivityFinal2::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, 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()
}
private var wakeLock:PowerManager.wakeLock?=null
私有变量isServiceStarted=false
var TAG=“MyService”
变量gps_状态=1
变量编辑器:SharedReferences.editor?=null
var previousBestLocation:位置?=null
APIVAR接口:GetDataService?=null
私有变量googleApiClient:googleApiClient?=null
私有变量lastLocation:位置?=null
私有变量locationRequest:locationRequest?=null
专用val更新间隔=10000
私有值最快\u间隔=更新\u间隔/2
var locationManager:locationManager?=null
var isFirsttime=true
var sharedPreferences:sharedPreferences?=null
覆盖有趣的onBind(意图:意图):IBinder{
返回空
}
覆盖启动命令(intent:intent?,标志:Int,startId:Int):Int{
日志(“使用startId执行的onStartCommand:$startId”)
if(intent!=null){
val action=intent.action
日志(“将意图与操作$action一起使用”)
何时(行动){
Actions.START.name->startService()
Actions.STOP.name->stopService()
else->log(“这永远不会发生。在接收到的意图中没有操作”)
}
}否则{
日志(
“具有空意图。它可能已被系统重新启动。”
)
}
返回起始点
}
重写fun onCreate(){
super.onCreate()
日志(“服务已创建”.toUpperCase())
val notification=createNotification()
startForeground(1,通知)
}
重写onDestroy(){
super.ondestory()
日志(“服务已被销毁”。toUpperCase())
val calendar=calendar.getInstance()
val mdformat=SimpleDataFormat(“HH:mm:ss”)
val strDate=mdformat.format(calendar.time)
LocalDatabaseForException(applicationContext,strDate,“服务已销毁”).execute()
val broadcastIntent=Intent()
broadcastIntent.action=“重新启动服务”
broadcastIntent.setClass(这是Restarter::class.java)
this.sendBroadcast(broadcastIntent)
}
重写onTaskRemoved(rootIntent:Intent){
val restartServiceIntent=Intent(applicationContext,MyEndlessService::class.java){
it.setPackage(packageName)
};
val restartservicependingent:pendingent=pendingent.getService(
这
1.
restartServiceIntent,
悬垂的帐篷,旗帜,一枪
);
applicationContext.getSystemService(Context.ALARM\u服务);
val alarmService:AlarmManager=applicationContext.getSystemService(Context.ALARM\u服务)作为AlarmManager;
alarmService.set(
AlarmManager.u实时,
SystemClock.elapsedRealtime()+1000,
restartServicePendingIntent酒店
);
}
私人娱乐startService(){
val calendar=calendar.getInstance()
val mdformat=SimpleDataFormat(“HH:mm:ss”)
val strDate=mdformat.format(calendar.time)
LocalDatabaseForException(applicationContext,strDate,“服务已启动”).execute()
如果(isServiceStarted)返回
日志(“启动前台服务任务”)
//Toast.makeText(这个“服务开始它的任务”,Toast.LENGTH\u SHORT.show())
isServiceStarted=true
setServiceState(此,ServiceState.STARTED)
//我们需要这个锁,这样我们的服务就不会受到打盹模式的影响
韦克洛克=
(作为PowerManager的getSystemService(Context.POWER\u服务)。运行{
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,“EndlessService::LOCK”)。应用{
获得
}
}
//我们要在一个协同程序中启动一个循环
GlobalScope.launch(Dispatchers.IO){
while(iServiceStarted){
发射(Dispatchers.IO){
pingFakeServer()
handleUserTracking()
}
延迟(1000)
}
日志(“服务的循环结束”)
}
}
私人娱乐服务{
日志(“停止前台服务”)
//Toast.makeText(这是“服务停止”,Toast.LENGTH\u SHORT.show())
val calendar=calendar.getInstance()
val mdformat=SimpleDataFormat(“HH:mm:ss”)
val strDate=mdformat.format(calendar.time)
LocalDatabaseForException(applicationContext,strDate,“服务已停止”).execute()
试一试{
韦克洛克?,让我来{
如果(it.isHeld){
//startService()
it.release()
}
}
//停止前景(真)
//stopSelf()
}捕获(e:例外){
日志(“服务已停止而未启动:${e.message}”)
val calendar=calendar.getInstance()
val mdformat=SimpleDataFormat(“HH:mm:ss”)
val strDate=mdformat.format(calendar.time)
LocalDatabaseForException(applicationContext,strDate,“服务停止而未启动:${e.message}”).execute()
}
isServiceStarted=false
setServiceState(此,ServiceState.STARTED)
}
私人娱乐pingFakeServer(){
SmartLocation.with(applicationContext.location())
.start(对象:OnLocationUpdatedListener{
覆盖乐趣onLocationUpdated(位置:位置?){
val SharedReferences=applicationContext.GetSharedReferences(
“AcessToken”,
AppCompatActivity.MODE_多进程
)
editor=getSharedReferences(“AcessToken”,MODE\u PRIVATE).edit()
editor=getSharedReferences(“AcessToken”,MODE\u PRIVATE).edit()
编辑器!!.putString(“temp\u latitude”,location!!.getLatitude().toString())
编辑器!!.putString(“temp\u latitude”,location!!.getLatitude().toString())
编辑器!!.apply()