Sharing watchOS 2 Media Files Using App Groups

From Techotopia
Jump to: navigation, search
PreviousTable of ContentsNext
A WatchKit WKInterfacePicker Coordinated Animation ExamplePlaying Movies and Audio on watchOS 2 using the WKInterfaceMovie Class


Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy eBook Buy Print


It has already been established in previous chapters that both the WatchKit app and WatchKit extension are installed and execute on the Apple Watch device. Regardless of this fact, however, the WatchKit extension and the WatchKit app each run within separate processes. This process separation (sometimes referred to as “sandboxing”) means that the WatchKit app and WatchKit extension do not, by default, have access to each other’s file storage. While this is not generally a problem, it can become an issue when working with media files.

The responsibility for playing back video content, for example, lies within the WatchKit app. This raises the question of how the WatchKit app would gain access to the video file to be played if it has been downloaded into the container of the WatchKit extension, an area to which the WatchKit app has no access. A similar problem arises when recording audio content. Once again the WatchKit app is responsible for the recording and will, by default, save that to a media file within its own container where the WatchKit extension will be unable to access it. The solution to this problem can be found in app groups.

This chapter will explore the use of app groups to enable a WatchKit extension and the corresponding WatchKit app to share access to files. In a later chapter entitled Recording and Playing Audio in a watchOS 2 WatchKit App this particular use of app groups will be demonstrated in a practical example.




Sandboxes, Containers and User Defaults

Although both the containing WatchKit app and the extension for a WatchKit app both execute on the same physical Apple Watch device they are said to run in separate sandbox environments. Sandboxes are a security mechanism that enforce sets of rules in terms of what an app can and cannot do when running on an Apple Watch device. Sandboxing, for example, prevents one app on a device from interfering with, or accessing files and data belonging to another app installed on the same device.

Included within the sandbox of each app is a container. This is essentially a file system area containing directories into which the app can store and access files. These can be any type of file including images, videos, plain text files or even SQLite or Core Data databases. The sandbox rules dictate that an app in one sandbox cannot access the files in the container of a second app and these same rules apply equally to the relationship between a WatchKit extension and the corresponding WatchKit app.

Sharing Data Using App Groups

The sharing of files between a WatchKit extension and the WatchKit app can be achieved through the use of shared app groups. When the WatchKit app and WatchKit extension are enrolled in the same app group they are given access to a shared container. This allows files to be shared between the WatchKit app and the extension. The diagram in Figure 25-1 illustrates this concept:


Watchkit app group diagram.png

Figure 25-1


Adding the WatchKit App and Extension to an App Group

App Group settings are contained in entitlement files using the com.apple.security.application-groups key. Both the WatchKit extension and the WatchKit app must include this entitlement. The value assigned to the com.apple.security.application-groups key indicates the app group to which membership is required. This value is typically set to the package name of the app prefixed with “group.” and must match in both the WatchKit app and extension entitlement files.

While it is possible to manually create the necessary entitlement files, by far the easiest way to configure app group membership is to do so through the Xcode Capabilities panel. To configure app group support for the WatchKit app, select the target located at the top of the Project Navigator panel and click on the Capabilities tab in the main panel. Within the capabilities panel, locate the App Groups section and switch it to the On position:


Watchkit enable app groups.png

Figure 25-2


When app groups have been enabled in the Capabilities screen, any existing app groups associated with your Apple developer account will be listed. To make the current app a member of any of those groups simply enable the checkbox next to the group name:


Watchkit join app group.png

Figure 25-3

Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy eBook Buy Print

To add a new app group to your account, simply click on the + button and enter the new app group name. Add the current app to the newly added app group by enabling the checkbox next to the group name. The app group will subsequently appear as an option in all other project targets within the Xcode Capabilities panel.

With the WatchKit app added to the app group, the WatchKit extension must also be added as a member of the same group in order to gain access to the shared container. To access the capability settings for the WatchKit Extension, use the menu located in the top left-hand corner of the Capabilities panel as indicated in Figure 25-4:


Watchkit capabilities select extension.png

Figure 25-4


When clicked, this menu will present a list of targets contained within the current project as shown in Figure 25 5, one of which will be the WatchKit extension. Select this option and repeat the steps followed for the WatchKit app to enable and configure app group support, making sure to select the same group name as that chosen for the WatchKit app.


Watchkit extension app group.png

Figure 25-5


A review of the files in the Project Navigator panel will reveal that entitlement files have been added for each of the two targets, the contents of which will read as follows (allowing for differences in the app group name):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>com.apple.security.application-groups</key>
        <array>
                <string>group.com.ebookfrenzy.SharingData</string>
        </array>
</dict>
</plist>

With both the parent WatchKit app and the WatchKit extension added to the same app group, code can now be written to access the shared data container.

App Group File Sharing

The first step in terms of sharing files via an app group is to identify the URL of the shared container. This can be achieved by obtaining a reference to the app’s default NSFileManager instance and making a call to the containerURLForSecurityApplicationGroupIdentifier method of that object, passing through as an argument the name of the app group. For example:

let fileManager = NSFileManager.defaultManager()

let url =    
   fileManager.containerURLForSecurityApplicationGroupIdentifier(
				"group.com.ebookfrenzy.SharingData")

Once the URL has been obtained, it can be used to share files. When writing data to flat files in a container shared by two processes, Apple advices against using the standard file coordination techniques and recommends using atomic write operations to avoid deadlocks occurring. An atomic write operation writes new data to a temporary file and then renames it to replace the original file. The following code, for example, obtains a reference to the shared container, appends a file name (datafile.dat) to the URL, checks that the file exists and then atomically writes a string to it:

let fileManager = NSFileManager.defaultManager()

let url = 
   fileManager.containerURLForSecurityApplicationGroupIdentifier(
		"group.com.ebookfrenzy.SharingData")

let dirPath = url?.path
let filePath = dirPath?.stringByAppendingPathComponent("datafile.dat")

if fileManager.fileExistsAtPath(filePath!) {
    let databuffer = ("hello world" 
         as NSString).dataUsingEncoding(NSUTF8StringEncoding)
    databuffer?.writeToFile(filePath!, atomically: true)
}

Summary

The WatchKit extension and WatchKit app are separate processes that execute within individual sandbox environments. The purpose of sandboxing is to prevent one process from accessing the files and data stored by another process. In order for media files to be shared between the WatchKit app and the WatchKit extension, both must belong to the same app group. App groups allow processes to share files through a shared container.


Purchase the full edition of this watchOS 2 App Development Essentials book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy eBook Buy Print



PreviousTable of ContentsNext
A WatchKit WKInterfacePicker Coordinated Animation ExamplePlaying Movies and Audio on watchOS 2 using the WKInterfaceMovie Class