Android's Enterprise APIs related to device administration offer many interesting features.
With a device owner app, you are able to perform many privileged tasks that are normally not available to regular apps. You can lock your app to the screen to create a kiosk app, update your app without user interaction, or even perform a device reboot.
Android 7 offers some new interesting features that allow you to monitor various information related to device's health.
I played a bit with this feature and in this post I'll show a quick guide on how to use it and what experience I had.
Make Your App a Device Owner
I showed how to create and activate a device owner app in my previous post. Therefore, the steps in this section will only be a quick summarization.
This step is necessary before you'll be able to use any of the functionality in the following sections.
You can start by implementing a DeviceAdminReceiver
class DevAdminReceiver: DeviceAdminReceiver() {
override fun onEnabled(context: Context?, intent: Intent?) {
super.onEnabled(context, intent)
Log.d(TAG, "Device Owner Enabled")
}
}
Create device_admin.xml
resource file inside of res/xml
with metadata that contains information related to device administration
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
</uses-policies>
</device-admin>
Declare your DevAdminReceiver
component inside of AndroidManifest.xml
<application
android:testOnly="true"
...>
...
<receiver
android:name="eu.sisik.kioskbrowser.DevAdminReceiver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
</receiver>
...
</application>
Please note that I also added the testOnly flag to the <application>
tag. If you are enabling device owner via ADB, this flag is necessary since Android 7.0.
Once you're app is complete and installed on the device, you can activate it as device owner via ADB by executing the following shell command
adb shell dpm set-device-owner eu.sisik.kioskbrowser/.DevAdminReceiver
This command will only succeed when there are no other accounts configured on the device. So ideally you execute this right after the first boot or after a fresh factory reset.
Measuring Temperature
The main class that gives you access to device monitoring features is the HardwarePropertiesManager.
Executing methods from HardwarePropertiesManager class will thrown a SecurityException
, if you didn't configure your app as a device owner.
Before calling any methods, you can first try to check if your app is a device owner app
val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
if (dpm.isDeviceOwnerApp(packageName)) {
// Great, we are device owner. We can call HardwarePropertiesManager methods
// ...
}
To measure the temperature, you first get an instance of the HardwarePropertiesManager
system service and call getDeviceTemperatures()
val hpm = getSystemService(HardwarePropertiesManager::class.java)
val temperatures = hpm.getDeviceTemperatures(DEVICE_TEMPERATURE_CPU,
TEMPERATURE_CURRENT)
for (temperature in temperatures)
Log.d(TAG, "temperature Celsius = " + temperature)
This can give you the temperature of parts like CPU, GPU, or Battery. The returned array can also be empty if the device doesn't provide these values (which was the case on all of the devices that I've played with).
Measuring CPU Usage
The getCpuUsages()
gives you CpuUsageInfo. This will allow you to get the number of milliseconds since system boot - either total
time which includes idle CPU time, or only the active
time.
It should return null for each offline core
val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
for (i in 0 until hpm.cpuUsages.size) {
val usageInfo = hpm.cpuUsages.getOrNull(i)
if (usageInfo != null) {
Log.d(TAG, "Minutes since last boot " + (usageInfo!!.active / 1000 / 60))
Log.d(TAG, "Minutes since last boot (including idle CPU) "
+ (usageInfo!!.total / 1000 / 60) + " minutes")
}
}
Luckily, I was able to get some values on my Nokia 6.
Fan Speed
getFanSpeeds()
returns the speed in RPM, but I again didn't have any device that would actually support this
val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
for (speed in hpm.fanSpeeds)
Log.d(TAG, "speed RPM = " + speed)