Skip to content

Instantly share code, notes, and snippets.

@nosix
Last active September 14, 2016 14:18
Show Gist options
  • Save nosix/0f2a7f55ebcc39bc56ab9eccf7991414 to your computer and use it in GitHub Desktop.
Save nosix/0f2a7f55ebcc39bc56ab9eccf7991414 to your computer and use it in GitHub Desktop.
How to use Android Service API
<?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="xxx">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".AppMonitorService"
android:exported="false" />
<receiver
android:name=".StartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>
package xxx
import android.app.*
import android.app.usage.UsageEvents
import android.app.usage.UsageStatsManager
import android.content.Context
import android.content.Intent
import android.util.Log
import java.util.*
class AppMonitorService : IntentService(AppMonitorService::class.simpleName) {
companion object {
private val TAG = AppMonitorService::class.qualifiedName
}
private val notificationId = Random().nextInt()
private var running: Boolean = false
private var workerThread: Thread? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
running = false
workerThread?.interrupt()
super.onStartCommand(intent, flags, startId)
return Service.START_STICKY
}
override fun onHandleIntent(intent: Intent?) {
if (!isUsageStatsAllowed()) {
allowUsageStats()
}
startNotification()
monitorApp()
}
private fun monitorApp() {
workerThread = Thread.currentThread()
var endTime = System.currentTimeMillis()
running = true
do {
val beginTime = endTime
endTime = System.currentTimeMillis()
getForegroundApps(beginTime, endTime).lastOrNull()?.let {
Log.i(TAG, it)
}
sleepMonitor()
} while (running)
}
private fun sleepMonitor() {
try {
Thread.sleep(1000)
}
catch (e : InterruptedException) {
}
}
private fun startNotification() {
val activityIntent = Intent(this, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, activityIntent, 0)
val notification = Notification.Builder(this)
.setContentTitle(AppMonitorService::class.simpleName)
.setContentText("Service is running.")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher) // required for setContentIntent
.build()
startForeground(notificationId, notification)
}
private fun getForegroundApps(beginTime: Long, endTime: Long): List<String> {
val foregroundApps = mutableListOf<String>()
val statsService = getSystemService(Context.USAGE_STATS_SERVICE)
if (statsService is UsageStatsManager) {
val events = statsService.queryEvents(beginTime, endTime)
val e = UsageEvents.Event()
while (events.getNextEvent(e)) {
if (e.eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
foregroundApps.add(e.packageName)
}
}
} else {
Log.e(TAG, "UsageStatsManager could not get.")
}
return foregroundApps
}
private fun isUsageStatsAllowed(): Boolean {
val opsService = getSystemService(Context.APP_OPS_SERVICE)
if (opsService is AppOpsManager) {
val mode = opsService.checkOpNoThrow(
AppOpsManager.OPSTR_GET_USAGE_STATS, android.os.Process.myUid(), packageName)
return mode == AppOpsManager.MODE_ALLOWED
} else {
Log.e(TAG, "AppOpsManager could not get.")
return false
}
}
private fun allowUsageStats() {
startActivity(Intent("android.settings.USAGE_ACCESS_SETTINGS")
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
}
}
package xxx
import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startService(Intent(this, AppMonitorService::class.java))
}
}
package xxx
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
class StartupReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
context.startService(Intent(context, AppMonitorService::class.java))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment