Issue
I have read multiple threads on this issue but none of them solved my problem, so I gave up and decided to write this.
I have a service (right now it's a background service but I am going to turn it into a foreground service) which monitors the battery level so it can notify the user when it reaches a certain percentage.
abstract class MonitoringService : Service() {
private var maxPercentage: Int = -1
private var thread: Thread? = null
private lateinit var batteryManager: BatteryManager
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
Log.d(null, "created service")
}
override fun onDestroy() {
thread?.interrupt()
updateServiceState(false)
Log.d(null, "destroyed service")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
println("started service")
if (intent == null) {
stopSelf(startId)
updateServiceState(false)
report(applicationContext, "service started with intent null")
return START_NOT_STICKY
}
when (intent.action) {
ACTION_START_SERVICE -> {
// if a thread is already active interrupt it
thread?.interrupt()
if (updateMaxPercentage(intent, startId) == 1) return START_NOT_STICKY
thread = Thread(Runnable {
while (true) {
if (batteryManager.isCharging && batteryManager.getIntProperty(
BatteryManager.BATTERY_PROPERTY_CAPACITY
) == maxPercentage
) {
Log.d(null, "time to do it")
}
Log.d(null, "time to not do it")
try {
// sleep for 1 minute
Thread.sleep(60000)
} catch (exception: InterruptedException) {
stopSelf(startId)
updateServiceState(false)
return@Runnable
}
}
})
thread?.start()
updateServiceState(true)
}
ACTION_STOP_SERVICE -> {
thread?.interrupt()
stopSelf(startId)
updateServiceState(false)
return START_NOT_STICKY
}
ACTION_UPDATE_SERVICE -> if (updateMaxPercentage(intent, startId) == 1) return START_NOT_STICKY
else -> {
stopSelf(startId)
updateServiceState(false)
report(applicationContext, "service started with action null")
return START_NOT_STICKY
}
}
return START_REDELIVER_INTENT
}
}
I start the service like so from my activity
private fun start() {
val serviceIntent = Intent(applicationContext, MonitoringService::class.java)
serviceIntent.action = ACTION_START_SERVICE
serviceIntent.putExtra("maxPercentage", maxPercentage)
println(startService(intent))
Log.d(null, "startService")
}
This is my AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.segv.batconv">
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.Batconv"
tools:targetApi="31">
<service
android:name=".MonitoringService"
android:enabled="true"/>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
I am testing this on an Android 11 device. The logs show no errors but the service doesn't start.
Thanks.
Solution
Remove the abstract
keyword from your MonitoringService
declaration:
class MonitoringService : Service()
By declaring it abstract
, you are saying that nothing can create an instance of that class.
Answered By - CommonsWare
Answer Checked By - Robin (JavaFixing Admin)