Time After (Screen) Time, part 2. The Device Activity Report Extension.

letvar
5 min readApr 24, 2024

--

Photo by Andy Makely on Unsplash

What’s the Device Activity Report Extension

The Device Activity Report Extension allows you to show the device usage to the user, by getting data from Screen Time and customising the appearance on a view which is placed inside of an app extension due to privacy constraints. Some examples of what can be done with the extension are shown below, taken from the WWDC22 session “What’s new in Screen Time API”:

Some examples of user interfaces using the Device Activity Report Extension. Source: Apple.

In order to allow the extension to read the device usage from the Screen Time API, you have to request the Screen Time permission first (see here), and then show the Family Activity picker, which is as simple as adding a modifier to your SwiftUI view:


import SwiftUI
import FamilyControls

struct ContentView: View {
@State var isPresented = false
@State var screenTimeSelection = FamilyActivitySelection()

var body: some View {
Button("Authorize Screen Time Items") {
isPresented = true
}
.familyActivityPicker(isPresented: $isPresented,
selection: $screenTimeSelection)
}
}

How it’s done

If you want to show data from your extension, you have to add it first to the Project (File > New > Target > Device Activity Report Extension).

The extension already comes with some sample code that you can use out of the box. Inside the

func makeConfiguration(representing data: DeviceActivityResults<DeviceActivityData>) async -> String {
// ...
}

function, you’re able to prepare a view model for your extension, so you can show the information you need. FYI, data is stored in async sequences, and here you have access to the values for the categories, apps and web domains the user has chosen before.

Choose a custom value for the context (DeviceActivityReport.Context ). Finally, you can include the extension in your parent view with a DeviceActivityReport view.

DeviceActivityReport(
DeviceActivityReport.Context(rawValue: "DeviceReportActivity"), // the context of your extension
filter: DeviceActivityFilter(
segment: .hourly(during: DateInterval(start: Date(timeIntervalSinceNow: 60 * 60 * 24), end: Date())),
users: .all, // or .children
devices: .init([.iPhone]), // .iPad, .mac, .iPod are also available
applications: screenTimeSelection.applicationTokens,
categories: screenTimeSelection.categoryTokens,
webDomains: screenTimeSelection.webDomainTokens
// you can decide which kind of data to show - apps, categories, and/or web domains
)
)

A challenging blackbox

The Device Activity Report extension has been a challenging blackbox to work with. It’s an extension — that means it’s a separate process that has something to share with the main app: in this case, it is embedded within the parent app.

In order to preserve privacy, this extension is severely sandboxed, which means that data can only flow in from the outside (e.g. by sharing a database or a user default from the main app), and data produced by the extension cannot be shared, read or written outside. You can still save some data inside the extension, but it won’t be visible from the outside and, if you are attempting to save something somewhere else — like a database in the main app — that will simply fail.

Other ways to communicate with the main app will fail as well, for example by using notifications via NotificationCenter or with the underlying Darwin Notification APIs. Network requests are not permitted as well.

Test the limits

Another limit is the consumption of RAM, which should level below 100 MB. Reaching or pushing this limit will cause your extension to lag and, in the wurst-käse scenario, to be terminated by the system. In this case, you most probably will see a black screen in place of the expected Device Activity Report extension.

So, try to keep your memory footprint way below this threshold. Because, even if you spare memory, you might always incur in crashes or unexpected behaviours of the extension. One amongst the other, which we also have noticed in similar apps that make use of the Device Activity Report extension, is that sometimes it crashes at the first time. For whatever no reason (probably a bug in the framework). Kaboom, Rico. A suggestion which partially solved the problems on our side, as suggested on the Apple Developer Forums, was to switch from daily to hourly data intervals.

And, since the parent app doesn’t know anything about the lifecycle of the extension, you won’t even be able to catch these crashes in the main app. Especially since, if you want to debug the app, you have to attach it at runtime (Debug > Attach to process > your Device Activity Extension process, once it’s shown on screen).

Finally, good luck with your print() statements: they won’t work.

Probably you (and us) at this point of the story. Wait ‘til the end: it’s not over.

Exploiting the boundaries

These are the tools you have if you want to use Screen Time data in your apps. Sometimes limited by design, sometimes buggy. So how to overcome these limits?

On the design, you have to exploit the limitations of this framework, and design a user interface and user experience that makes the most out of what the APIs provide to you. That’s also true for topics like navigation and routing in the extension. Might sound a bit boring and frustrating, but for sure thinking out of the box in these situations will greatly help you.

On the bugs, the most common solution that Apple will tell you is to file a radar… ehm, submit a feedback in the Feedback Assistant. But, let’s face it: your app will be shipped in a timeframe which is usually shorter than the resolution of a radar. Then, try to do your best to “hide” these bugs in the interface by using workarounds and by providing tools to reduce friction (e.g. loaders, reload buttons, etc.)

(my two cents: fill feedbacks anyway, hoping they will be solved in iOS 18!)

Stay tuned

We’ll publish more insights on the Screen Time APIs in the future— stay tuned and make sure to follow our Medium and our social channels (@letvarhq)!

Photo by Kenny Eliason on Unsplash

The author

Nicola Giancecchi
Co-founder, CEO and Apple Platforms Engineer @ letvar

Feedbacks are welcome! hello@letvar.io

--

--

letvar
letvar

Written by letvar

We are a team of creatives and focused on crafting apps for any device.