Skip to Content
Technical Articles
Author's profile photo Kevin Muessig

Enhance your Business apps with Widget Extensions

Bringing your business to smartphones and other mobile devices became crucially important over the last years. As mobile devices are powerful, fast and easy to use they are a perfect fit for on-the-go business apps covering not only simple use cases but also highly feature-heavy workflows including on-device machine learning, Augmented Reality, working with offline data and more.

SAP%20Fiori%20for%20iOS%20Design%20Language%20-%20Get%20Started

SAP Fiori for iOS Design Language – Get Started
https://experience.sap.com/fiori-design-ios/get-started/

Because mobile business apps are mostly used while on-the-go a user might want to complete and proceed certain tasks as easy and fast as possible. With native technologies like Swift & SwiftUI on iOS this can be achieved very easily. Using Widget Extensions can be a way to fulfil the requirement of bringing features to your home screen of the iOS device.

Unfortunately, in the past it was architecturally not possible to create Widget Extensions in combination with your SAP BTP Fiori for iOS SDK based apps. This has changed with the SAP BTP Fiori for iOS SDK version 6.x. It is now possible to simply let the SAP BTP Fiori for iOS SDK Assistant generate a fundamental Widget Extension for you. Without writing any code the SDK provides you a fully functioning base for further work on Widget Extensions.

SAP%20BTP%20SDK%20for%20iOS%20Assistent%20generated%20Widget

SAP BTP SDK for iOS Assistent generated Widget

With this blog post we take a bit of a deeper look at what the SAP BTP SDK for iOS Assistant generates and how we can change what the widget is showing.

We won’t look into detail how Apple’s Widget Extensions work, if you’re interested in this see the link mentioned above.

What does the SAP BTP SDK for iOS Assistant generate?

In the process of generating an app with the SAP BTP SDK for iOS Assistant you can select to enable Widget Extensions. If selected the SAP BTP SDK for iOS Assistant generates all the needed code in our extension for the Widget to work. Not only the widget’s code will be generated but also all the security related code for fetching the data and checking on the authentication status of the main app.

SAP%20BTP%20SDK%20for%20iOS%20Assistant%20-%20Widget%20Extension

SAP BTP SDK for iOS Assistant – Widget Extension

A typical Widget Extension when added as target to your Xcode project needs the following components to work:

  • Widget: A SwiftUI file complying to the Widget protocol determining whether or not the widget has user-configurable properties.
    • StaticConfiguration: Using no user-configurable properties. Static content.
    • IntentConfiguration: Using user-configurable properties by SiriKit custom intent. For Widgets with dynamic content depending on parameter like location.
  • TimelineProvider: A timeline provider can also be an IntentTimelineProvider in case of the need of user defined properties. In all cases a TimelineProvider helps the system to know when to update the Widget.
  • TimelineEntry: A timeline provider generates a timeline consisting of timeline entries. These specifying the date and time to update the widget’s content.
  • View: A SwiftUI View representing the UI of your Widget

Note: If you have multiple Widgets they all can be placed in one extension rather than having multiple extension targets. You can have multiple extension targets but most of the time this is not necessary.

The SAP BTP SDK for iOS Assistant generates exactly these files and populates them with the needed code to display a Widget like seen in the image above.

Widget

import SwiftUI
import WidgetKit

@main
struct BusinessWidgetEnhancmentWidget: Widget {
    var widgetConfig = WidgetConfigurationProvider()
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: widgetConfig.kind(), intent: DynamicDestinationSelectionIntent.self, provider: WidgetIntentTimelineProvider()) { entry in
            BusinessWidgetEnhancmentWidgetEntryView(entry: entry)
        }
        .configurationDisplayName(widgetConfig.configurationDisplayName())
        .description(widgetConfig.description())
        .supportedFamilies(widgetConfig.supportedFamilies)
    }
}

As we can see above the generated code defines a Widget containing a WidgetConfigurationProvider which is a custom class conforming to the WidgetConfigurationProviding which is also a custom protocol defining the Widget’s attributes itself.

In the body you can see that the IntentConfiguration is been done to enable the user to use SiriKit to customize the widget. In the block of the IntentConfiguration the view itself is created and passed in, the WidgetEntryView.

And on the IntentConfiguration the display name, description and supported families are defined. The supported families define the sizes the Widget supports.

TimelineEntry

import Foundation
import UIKit
import WidgetKit

struct WidgetEntry: TimelineEntry {
    var date: Date
    let values: [WidgetRowViewModel]
    var title: String
    var listPath = ""

    init(date: Date = Date(),
         title: String,
         values: [WidgetRowViewModel]) {
        self.date = date
        self.values = values
        self.title = title
    }
}

The TimelineEntry defines as the name describes the entry on the widget timeline. You can find a date, the values to be displayed and a title. This all is very straight forward as it just defines the model of the Widget’s timeline entry.

protocol WidgetRowViewModel {
    var value: String { get }
    var key: String { get }
    var image: String? { get }
}

The WidgetRowViewModel again is just a model defining further details of the values defined in the timeline entry.

IntentTimelineProvider

    func placeholder(in _: Context) -> WidgetEntry {
        return WidgetEntry(date: Date(), title: "Collections", values: WidgetIntentTimelineProvider.previewData)
    }

    func getSnapshot(for _: DynamicDestinationSelectionIntent, in _: Context, completion: @escaping (WidgetEntry) -> Void) {
        let entry = WidgetEntry(date: Date(), title: "Collections", values: WidgetIntentTimelineProvider.previewData)
        completion(entry)
    }

The timeline provider is the struct where everything comes together. This is the place the Widget gets told what the data is it should show, what the placeholder should be in case of the data is nil or not loaded yet. Further methods are implemented like the getSnapshot and getTimeline. The snapshot returns a WidgetEntry with dummy data so a proper snapshot can be provided to the system.

func getTimeline(for configuration: DynamicDestinationSelectionIntent, in _: Context, completion: @escaping (Timeline<WidgetEntry>) -> Void) {
        guard AuxiliaryOnboardingUtil().isWidgetInitialized() else {
            // User has not onboarded, show login screen
            let entry = WidgetEntry(date: Date(), title: "", values: [])
            let timeline = Timeline(entries: [entry], policy: .atEnd)
            completion(timeline)
            return
        }

        let entry = getData(forEntity: configuration.selectedEntity, inDestination: configuration.selectedDestination)
        let timeline = Timeline(entries: [entry], policy: .atEnd)
        completion(timeline)
    }

The getTimeline does a lot of custom checks and setups as with the security of the SAP BTP SDK for iOS Assistants generated code these are necessary to safely access the data. As we know the data can only be retrieved after the onboarding process was successful and the user is logged in. If both is not true the placeholder is going to be displayed, and the widget will tell the user to log in. The getTimeline method does exactly this check, it uses the AuxiliaryOnboardingUtil to ask if the widget itself is initialized, if not the user is not onboarded and the login screen is shown when the user taps on the widget itself. In the case the user has logged in the data gets loaded and displayed in the timeline.

Change the entities on the Widget

The code generated by the SAP BTP SDK for iOS lets you choose the entity you want to be displayed in the Widget itself.

Simply use Force Touch on the widget to open the settings of the widget. There you can choose the entity you want to have displayed in the Widget Timeline. This is a great way to quickly access different entities of your backend service right from your home screen.

Conclusion

Widget Extensions are really helpful tool to ease up the process of displaying or working with your app through having certain features right there on the home screen. The possibility to directly integrate into SiriKit is a great advantage when you have users wanting to work with Siri to execute certain tasks.

Using the SAP BTP SDK for iOS allows you to get your project started with an advanced Widget Extension already in place. Not only eases up the process of creating a Widget Extension but also eases development because of the generated code you get. Checking on security, authentication and available data is done for you and the code can be used as template or base for further development. Even if you throw out all the view code of the extension, which is most likely the case, you have all the underlying plumbing already done and ready to use.

I would encourage your to generate an app with the SAP BTP SDK for iOS Assistant and look into Widget Extensions more closely as they can lift up your app to the next level in terms of UX. If you are interested in building your own little Widget, a SAP Tech Bytes video is currently in the making by myself and will be ready soon!

 

Happy Coding, and until next time!

 

Ressources:

Assigned tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Anna Opoka
      Anna Opoka

      Hi Kevin! Will you also cover adding the widget extension to already existing applications?

      Author's profile photo Kevin Muessig
      Kevin Muessig
      Blog Post Author

      Hi Anna, I've added it to my list.
      If the post is ready I will post on Twitter/LinkedIn.

      Thanks