GITHUB_TOKEN
or through creation a Personal Access Token. However, when the tools that your GitHub Action interacts with require to authenticate, injecting that personal access token can become challenging.
Here I show two easy ways to enable your GitHub Actions to interact with private repositories for:
In both of these examples, it’s incredibly important to use GitHub Action’s secrets to store the personal access token, and then inject that token into the environment of the job that requires it. This ensures it is redacted in any runner logs and not visible in plain text.
There’s an obscure variable that Bundler uses to authenticate with GitHub, BUNDLE_GITHUB__COM
:
Specify the variable BUNDLE_GITHUB__COM: x-access-token:${{ secrets.$SOME_PAT }}
in your job
’s env` key and ensure the URL to clone the ruby gem is using https.
gem 'private-dependency', git: 'https://github.com/your-org/private-repo'
name: "Deploy"
on:
workflow_dispatch:
jobs:
deploy-beta:
name: "Deploy Beta"
runs-on: ubuntu-latest
timeout-minutes: 10
env:
BUNDLE_GITHUB__COM: x-access-token:${{ secrets.PRIVATE_GITHUB_PAT }}
steps:
- name: "Checkout ${{ github.ref }} in ${{ github.repository }}"
uses: actions/checkout@v4
- name: "Install dependencies"
run: |
bundle install
When Xcode clones dependencies through Swift Package Manager, because it is using the machines git configuration, we can harness that and the insteadOf key to modify the remote URL.
Use the following step
in your GitHub Action to modify the git config remote URL:
- name: "Setup Authenticated URL"
shell: bash
env:
GIT_AUTH_TOKEN: ${{ secrets.GIT_AUTH_TOKEN }}
run: |
git config --global --add url."https://oauth2:${GIT_AUTH_TOKEN}@github.com/".insteadOf "https://github.com/"
git config --global user.name "$GIT_AUTHOR_NAME"
git config --global user.email "$GIT_AUTHOR_EMAIL"
git config --global credential.username "$GIT_USERNAME"
Recently, as part of my release workflow with the new Xcode Cloud, I found myself wanting to ensure that the app version was automatically updated based on the version number specified in my git branch, for example, release/1.2.0
. I was constantly running into the dreaded App Store Connect failure where your app version (CFBundleShortVersionString
) was not greater than the previous release - because I kept forgetting to manually change it in my Info.plist!
To stop making this mistake I wanted to build the following:
release/*
In a more concrete scenario - when I wish to generate my next release candidate for TestFlight from my work-in-progress, I can create a new branch with the appropriate version from my changes and then rely solely on Xcode Cloud to execute my app version script and automatically bump the build number.
Xcode Cloud supports custom build scripts. We can use these scripts to run specific tasks that augment our build pipelines - Xcode Cloud provides 3 entry points:
ci_post_clone
ci_pre_xcodebuild
ci_post_xcodebuild
For this specific problem, we could use either ci_post_clone
and ci_pre_xcodebuild
, I opted for ci_post_clone
as I want the pipeline to fail as early on as possible if it ran into issues with my script - this reduces build time and therefore cost and reducing the feedback cycle during development.
To get started, we create a directory in the root of our repository named ci_scripts
and create an empty file inside it named ci_post_clone.sh
What language should we use for our script?
By default, Xcode Cloud uses zsh
, but as you’d expect, I am far more comfortable writing Swift. Luckily, we’re able to use Swift within these scripts by specifying the following shebang at the top of the ci_post_clone.sh
file,
#!/usr/bin/env swift
Note: the only behaviour I have in my
ci_post_clone
file is for the app versioning, but it’s likely that you will be handling many scenarios within the 3 available entry point scripts, so it’s important to consider this when structuring your script and the exit points and error points within it - you can read more in the documentation under the “Writing resilient scripts” section.
Let’s jump into the script bit-by-bit:
func appVersionBumpIfNeeded() throws {
let dictionary = ProcessInfo.processInfo.environment
// ...
We start with a simple function signature that throws - this will allow us to exit the script gracefully in the event of an error - and in future handle errors more easily. We also grab a reference to the ProcessInfo
environment
property to access the environment variables on the machine, we’ll be using these to extract information and make conditional decisions.
guard let branch = dictionary["CI_BRANCH"],
branch.starts(with: "release/") else {
return
}
let version = branch.replacingOccurrences(of: "release/", with: "")
// ...
There are a number of Xcode Cloud pre-defined environment variables available to you, these are all prefixed with
CI_
- the full reference can be found here
We extract the branch name, and verify it starts with the prefix (and therefore workflow) we are interested in, if it doesn’t we bail out with no error. We could also take a very thorough approach here and inspect the CI_WORKFLOW
environment variable - but perhaps this is better handled by the caller and the top-level of the script.
let version = branch.replacingOccurrences(of: "release/", with: "").replacingOccurrences(of: "ci_testing/", with: "")
let components = version.components(separatedBy: ".")
guard components.count <= 3 else {
print("Version invalid length: \(version)")
throw PostCloneErrors.invalidBranchVersion
}
let values = components.compactMap { Int($0) }
guard components.count == values.count else {
print("Version contains invalid characters: \(version)")
throw PostCloneErrors.invalidBranchVersion
}
The next part is all about validating the version number meets the format expected by App Store Connect.
/release
1.2.3
If any of the above fails, we want to be throwing an error at this point for the caller to handle or for the script to bail out.
let infoPlistURL = URL(fileURLWithPath: "path/to/Info.plist")
let infoPlistData = try Data(contentsOf: infoPlistURL)
let infoPlist = try PropertyListSerialization.propertyList(from: infoPlistData,
options: .mutableContainersAndLeaves,
format: nil) as? NSDictionary
let mutableInfoPlist = infoPlist?.mutableCopy() as? NSMutableDictionary
print("Updating version to: \(version)")
mutableInfoPlist?["CFBundleShortVersionString"] = version
let modifiedInfoPlistData = try PropertyListSerialization.data(fromPropertyList: mutableInfoPlist as Any, format: .xml, options: 0)
try modifiedInfoPlistData.write(to: infoPlistURL)
Now that we know the version number matches a valid format, we need to write value that to the CFBundleShortVersionString
key within the Info.plist file in your repository. We do not need to modify the CFBundleVersion
at all, e.g. your build number - as this can be handled in your Xcode Cloud workflow directly.
CFBundleShortVersionString
to the version
we captured earlierAnd that’s it - I’ll paste the full script below, you’ll need to modify it for your project differences - let me know your thoughts on Twitter and if you’ve made any useful Swift scripts for Xcode Cloud.
#!/usr/bin/env swift
import Foundation
enum PostCloneErrors: Error {
case invalidBranchVersion
case invalidInfoPlistPath
}
func appVersionBumpIfNeeded() throws {
let dictionary = ProcessInfo.processInfo.environment
guard let branch = dictionary["CI_BRANCH"],
branch.starts(with: "release/") else {
return
}
let version = branch.replacingOccurrences(of: "release/", with: "")
let components = version.components(separatedBy: ".")
guard !components.isEmpty, components.count <= 3 else {
print("Version invalid length: \(version)")
throw PostCloneErrors.invalidBranchVersion
}
let values = components.compactMap { Int($0) }
guard components.count == values.count else {
print("Version contains invalid characters: \(version)")
throw PostCloneErrors.invalidBranchVersion
}
let infoPlistURL = URL(fileURLWithPath: "/your/path/to/Info.plist")
let infoPlistData = try Data(contentsOf: infoPlistURL)
let infoPlist = try PropertyListSerialization.propertyList(from: infoPlistData,
options: .mutableContainersAndLeaves,
format: nil) as? NSDictionary
let mutableInfoPlist = infoPlist?.mutableCopy() as? NSMutableDictionary
print("Updating version to: \(version)")
mutableInfoPlist?["CFBundleShortVersionString"] = version
let modifiedInfoPlistData = try PropertyListSerialization.data(fromPropertyList: mutableInfoPlist as Any, format: .xml, options: 0)
try modifiedInfoPlistData.write(to: infoPlistURL)
}
try appVersionBumpIfNeeded()
As mentioned earlier - there’s definitely an opportunity at the call-site (try appVersionBumpIfNeeded()
) to inspect the CI_WORKFLOW
name and decide what sequence of functions you wish to call as part of your ci_post_clone
script, e.g.
enum Workflow: String {
case release
}
guard let workflow = Workflow(rawValue: ProcessInfo.processInfo.environment["CI_WORKFLOW"] ?? "") else {
return
}
switch workflow {
case .release:
try appVersionBumpIfNeeded()
}
Best of luck!
]]>apple-app-site-association
file for the Apple CDN to pull.
This blog is actually running on a static site generator called Jekyll, and it’s hosted by GitHub Pages. There’s an excellent guide from GitHub if you’d like to do something similar - I’m also using it to satisfy the App Store privacy policy requirement too.
For the AASA file, I had two requirements:
apple-app-site-association
to the .well-known
directoryIt turned out to be really simple, all that was needed was to create the folder and file in my root directory and then the key part - specify in my _config.yml
file to include that location:
include:
- .well-known
There was some misleading information out there that lead me away from this simple approach initially - this works. You can find the commit here
]]>UITextField
that back the SwiftUI TextField
. The reason I was using the library was because, at the time (iOS 14), there was no first-party support in SwiftUI for either adding a Toolbar
to the keyboard or customising the focus state of the TextField
in the form.
I’m not going to regurgitate Paul Hudson’s excellent articles - so for more detailed information please see:
This article is to quickly demonstrate a generalised solution I’ve come up with to adding quick keyboard toolbar based navigation to a form - a must-have for any app that utilises the .numberPad
or .decimalPad
keyboard styles.
I’ve built a simple type conforming to View
, that takes the current FocusState
from your parent view (where your TextField
’s live) and the array of all the available field types you have on that particular view:
protocol InputField: Hashable, CaseIterable {
var index: Int { get }
}
struct TextFieldNavigationView<FieldType: InputField>: View {
var focusedField: FocusState<FieldType?>.Binding
let allFields: [FieldType]
var body: some View {
Group {
Spacer()
Button {
if let f = focusedField.wrappedValue {
focusedField.wrappedValue = allFields[f.index - 1]
}
} label: {
Image(systemName: "chevron.up")
}
.disabled(focusedField.wrappedValue?.index == 0)
Button {
if let f = focusedField.wrappedValue {
focusedField.wrappedValue = allFields[f.index + 1]
}
} label: {
Image(systemName: "chevron.down")
}
.disabled(focusedField.wrappedValue == allFields.last)
}
}
}
This view simply enables or disables a chevron icon in the toolbar based on how many fields are before or after - utilising the CaseIterable
protocol and the allCases
property. So, what does an implementation on your form look like?
enum MyCustomInputField: Int, InputField {
case testing1
case testing2
case testing3
var index: Int {
rawValue
}
}
This enum conforms to the InputField
protocol we previously defined, and adds cases for each of the text fields I have on one of my screens, I’m using the Int
as a backing type to easily provide the index, but this can easily be defined in a custom manner within the index
property itself.
We then use the advice from Paul Hudson’s articles and harness the .focused
and the toolbar
view modifier. It’s worth noting, you only need one view modifier for the .toolbar
on the parent of your TextField
, e.g.
@FocusState var field: MyCustomerInputField?
/// ...
ScrollView {
VStack {
TextField("Testing 1", text: $foo)
.focused($field, equals: .testing1)
TextField("Testing 2", text: $bar)
.focused($field, equals: .testing2)
TextField("Testing 3", text: $test)
.focused($field, equals: .testing3)
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
TextFieldNavigationView<MyCustomInputField>(
focusedField: $field,
allFields: MyCustomInputField.allCases
)
}
}
And that’s all there is to it! Let me know your thoughts on Twitter
]]>For the most part, Stickers are dominating the Apple Messages media coverage. Apple are also chiefly focusing their own marketing efforts on these stickers by branding them as a way to allow “people [to] express themselves in richer ways”. This is in spite of them being a blatant feature poach direct from apps such as Facebook Messenger, Snapchat and Google Allo.
Why would Apple gear their marketing this way? It could be that they believe the demographic that are using stickers on competitor platforms would be easily swayed to use iMessage if they matched this functionality. Or ostensibly it could be because they genuinely think this is the most exciting update to be made to iMessage. Regardless, it is diluting and cheapening the impact that iMessage apps are having and undermining how they could potentially revolutionise how people view and use messenger applications. iMessage can finally be considered a full-blown platform on iOS with doors now wide-open for developers to utilise.
At Apple’s Worldwide Developer Conference (WWDC) this year the updates to the Messages app were announced. Despite the sheer size of the update to Messages, developers were educated on the new functionality and APIs available to them in only two sessions, dubbed “iMessage Apps and Stickers Part 1 & 2”. The talks mainly focused on the new Stickers functionality and when the iMessages Apps themselves were discussed and demoed; it was purely from a collaborative sticker sharing (image building) experience. It did not really incite much inspiration or show the true power of the new APIs. However, they did conclude the talk with the overworked, “…we can’t wait to see what you do with it!”. Again, it wasn’t clear whether Apple were intending for iMessage Apps not to be the focus or if they just had not come up with any innovative applications of the technology themselves yet - myself, as an attendee, was certainly underwhelmed after attending the talk.
“Messages apps allow people to collaborate by using your app. […] people can work together to accomplish a task within the conversation.”
As of 23 September 2016, there have been 1,251 sticker packs and 402 iMessage apps uploaded to the new Apple iMessage App Store; with games actually being the largest category at 91 games. Premium Stickers packs are the majority with over 75% being paid for. According to SensorTower, “Just one week in, there are nearly as many iMessage enabled apps as there were apps of any kind on the App Store when it launched in 2008.”.
“…1,251 Sticker packs and 402 apps uploaded to the new Apple iMessage App Store”
The premise of the iMessage app from a development standpoint is that it allows a user within the Messages application to access functionality from a regular app (or act as a standalone iMessage app) that they have installed on their device. This app functionality should allow them to collaborate with their chosen contact(s) and “accomplish a task”. These tasks could be anything from decision-making, content sharing, playing games and even making payments - all within the Messages application.
As mentioned, Sticker packs and iMessage apps can exist as standalone packs/apps that are available for direct download from the App Store for iMessage. They can also exist as extensions of other apps that a user may choose to download from the standard App Store, indicated by the badge ‘Offers iMessage App’, or one that they already have installed on their device. This badging approach is identical to the approach taken for Apple Watch app extensions. Standalone iMessage apps are a great surprise from Apple, in the past we generally have not seen extension functionality of other system apps available for download as standalone applications, for example, see how Apple approached the release of watchOS apps and Notification Center widgets.
App extensions were introduced with the release of iOS 8 in 2014; the goal of them was to enable an app user to access an “app’s functionality and content throughout iOS [and macOS]”. Since then, year-on-year, Apple have expanded the app extension offering available to developers (and by proxy to users) to break down the “walled-garden” and expose more of the system to third-party iOS apps - drastically improving app usability in a secure and safe way. iMessage apps are one of these app extensions.
Outside of iOS it is quite common for an operating system to allow software more liberal access to the other system libraries and data - and although this allows for more rich functionality to be available to the end-user it does pose security concerns. Part of the reason app extensions and iMessage apps themselves have been slow to fruition within the iOS ecosystem is because of Apple’s security and privacy concerns. Apple puts securing personal user information at the forefront of all of their new features and decisions. Because of this, it has a taken a considerable amount of time for Apple to slowly roll out new extensions and integrations, such as Siri, Maps and of course Messages. These security concerns are also clearly visible within the iMessage app APIs that are available to developers. iMessage apps do not have direct access to any personal information or the ability to determine who a user is talking to. Apple have used an approach where the app can only access Universally Unique Identifiers (UUIDs) that act as placeholders for an app to use. When the system runs the application and acts on these identifiers it will replace them with the relevant personal content. For example, a developer has access to a property localParticipantIdentifier
and remoteParticipantIdentifiers
on the MSConversation
class, these act as placeholders representing the name of the sender and the name(s) of the receiver(s) of the respective messages being sent.
Apple’s care about the user’s privacy is a huge market differentiator for them and over the past two years, particularly since the celebrity iCloud leaks and the FBI-Apple encryption dispute after the 2015 San Bernardino attack, they have been singing the privacy and security anthem loud and clear. This includes Messages - an app where most of us have highly personal information and Apple are making it clear that iMessage apps do not compromise this data.
“People have entrusted us with their most personal information. We owe them nothing less than the best protections that we can possibly provide.” - Tim Cook
Part of adding any new feature to an existing application requires thorough User Experience (UX) considerations and this is where I believe, and I am not alone, iMessage apps and Sticker packs have fallen short.
“I had over 60 negative written reviews of Phoneys, and several more 1-star reviews, on its app store page, ranging from people not knowing how to find iMessage apps, to people not understanding how to peel stickers” - Adam Howell, Developer of #1 sticker pack ‘Phoneys’
There are now two additional buttons on the iMessage interface, one is to access the new digital touch/drawing functionality. The other, indicated by the classic App Store ‘A’, gives them access to a new app drawer, which by default will contain some stickers and a selection of apps the user can swipe between. It is by no means obvious how a user can add more apps, even though the user has just pressed a button with an App Store icon. There is also a toolbar at the bottom of this new panel, which allows you to expand to fullscreen or open a tray which contains all of your iMessage apps. You can then select the ‘Store’ button, which is visualised with a ‘+’ symbol. This now opens a full-featured App Store which resembles the layout of a standard App Store - where you can also ‘manage’ your existing apps. The key oversight for me is that by default, the option to ‘Automatically Add Apps’, is disabled - I feel this is an oversight because it will make initial iMessage app discovery that little bit slower for users with apps already supporting an iMessage app.
SensorTower have also reported that it is not the larger number of apps and sticker packs that are available that are confusing the user, but “user complaints we’ve seen so far have focused more on its confusing interface than an overwhelming number of choices.”. I think that we can expect vast changes in the interface, interaction and information architecture for iMessages apps and Stickers come iOS 11 - or maybe even sooner via a minor release of iOS 10.
The question now is how far will Apple (and third-parties) take this? There is large scope for what these apps can do and achieve; we are currently less than one month into their debut, and they are already gaining massive traction. A major factor in innovation will be around Apple Pay and payments within iMessage Apps; payments are already supported, but we are still yet to see many innovative uses of payments within a collaborative experience on iMessage - perhaps concert tickets, collaboratively chosen and individually purchased all within a single iMessage group chat.
As mentioned previously, it is also possible to release an iMessage app as a standalone app rather than just as an extension of an existing fully-featured iOS app. I think there is a very good chance we will now enter an era of standalone iMessage apps that solve a separate and specific problem related to messaging and collaborative communication rather than just being an additional piece of functionality to an existing app. Currently, games are dominating this category on the App Store but productivity and utility based apps will almost certainly begin to gain popularity. This makes Apple, again, the creator of an entirely new market of niche apps to solve specific problems.
There is now an interesting opportunity for companies to start pushing their brand through the use of Stickers. Although this doesn’t benefit the user (or consumer) directly, this has never stopped the advertising industry from trying, but I think we can expect marketing campaigns being angled towards stickers within iMessage very soon. We are already seeing sticker packs for games, such as Super Mario and Fallout. Will we soon see McDonald’s and Starbucks in there? Will they become the next stage of evolution for emojis where we start using particular brands and their stickers to articulate and express ourselves in Messages? This will be the ultimate goal for a brand’s identity within the new iMessage platform.
Message applications have not just been revamped by Apple - Apple’s other key competitors in this field have also put their messaging apps and platforms on steroids over the past year - this probably being the driving force in such a drastic change to the iMessage platform overall. Facebook Messenger is definitely a key competitor and probably the industry catalyst for adding such seemingly dated sticker (cast your mind back to MSN Messenger) functionality to the modern messaging client - but it worked, and now Facebook Messenger has over 1 billion users with a platform allowing developers to build chatbots - Facebook’s answer to integrating with other applications, brands and industries. Google Allo is one of the main competitors, announced at Google I/O in May 2016 and released in September 2016, it introduced the majority of the new features that Apple Messages has replicated - excluding the third-party app extensions. The commonalities between the platforms are extensive. Even interactions such as determining how ‘loud’ you want your message to be are accessed via essentially the same buttons across both applications. Google’s strength however, as always, is data analysis. Their implicit disregard for user privacy has the strong perk that their machine learning algorithms and message analysis are far stronger than Apple’s Messages application and always will be leaps ahead in terms of intelligence. This allows features such as predictive and suggestive text, handwriting analysis and quick response options - e.g. TapBack, to be far superior. As cliché as it sounds however, with great power comes great responsibility and Allo still has a lot of refinement to go in terms of suggestions (interruptions) that it is offering mid-conversation for its users. Allo is also coming under heavy criticism within encryption circles, due to their encouragement of only using the offered ‘Incognito mode’ for sensitive information - not quite the goal that privacy evangelists would advocate for. This is because Allo’s rich feature-set is reliant on being able to observe messages in transit in order to perform the contextual analysis - this can’t be done if there is end-to-end encryption, a feature of the incognito mode.
2016 has been huge for messaging clients and despite apps’ like WhatsApp and Facebook Messenger holding such a huge portion of the market share, I do not think we have seen the end of this and Google and Apple’s answer to Facebook’s acquisition and dominance has certainly not gone unnoticed.
In conclusion, third-party app vendors should certainly be focusing on integrating their existing apps with iMessage. It is a brand-new marketplace and there is still plenty of opportunities for everyone to capitalise on. There are countless ways companies could bolster their marketing and advertising campaigns through the use of the sticker packs. Games companies should certainly be getting their hands dirty and getting great, collaborative in-message games created. Games are currently the largest category on the iMessage App store for both extensions and standalone apps (free and premium) and I am sure this will be the case for quite some time. Over the next year, we can expect to see UX and UI overhauls of the messaging interface in order to reduce its complexity and make features more discoverable and accessible - this could potentially be seen as early as iOS 10.2.
Are iMessage apps and Stickers the most important aspect of iOS 10? Probably not, but it definitely was the largest update to any individual feature in the Apple ecosystem this year.
References
]]>Currently, we can observe numerous scenarios where P2P technology is attempting to solve a communication-based ‘problem’, here is a limited list of some of the major implementations aimed at regular consumers:
Sending files, images and videos quickly, with zero prior configuration, to your nearby peers. Apple’s solution is AirDrop; an integrated file transfer tool, working on both OS X and iOS, within Finder or at the app level on iOS. Since iOS8 and Yosemite, it now also works between these two platforms. AirDrop allows users to send files to a nearby machine or mobile device without any need for worrying about connecting to the same network, knowing email addresses or pairing machines, or even having a network connection. This lack of prior configuration and simplicity is what makes AirDrop so alluring and rapid to use.
Contacting other people (or groups of people) within your own vicinity, when a network connection is either unavailable or an unsuitable medium for transmitting data. The primary example being the mobile application FireChat - a P2P iOS application allowing its users to create chatrooms that utilise ‘mesh networking’ to exchange messages through each of the network’s peers using ad-hoc Wi-Fi or Bluetooth connections. FireChat is currently averaging 2.5 stars out of 5 on the App Store; arguably quite a poor score. Is this the curse of being first to market with an innovative idea or has it just been inadequately executed? Rather than the medium of communication being to blame I feel that the approach taken by the developers is actually at fault for its negative public reception. Do people want ephemeral chatrooms overflowing with information in a crowded city or do they want ephemeral one-to-one conversations with designated purpose? FireChat doesn’t seem to know who or what it is currently and this is reflected by their users reviews.
As stated, this is a tiny example of how modern P2P technology is all around us, perhaps even without many users realising it. We have moved far beyond the original intentions of BitTorrent and basic peer-based file sharing, and it is slowly becoming more integrated in our own personal technology toolbox utilised in our day-to-day lives.
Currently native mobile applications are occupying a huge share of software development efforts globally, across multiple platforms, so it would follow that P2P software is now being rolled out by third-party developers. As outlined above, we can observe this increased interest in P2P technologies, both by developers and technology providers. For example, in the past 18 months Apple have released their own framework to enable iOS apps to support and utilise P2P networks. FireChat, mentioned previously, has been developed natively using this framework from Apple. MCMultipeerConnectivity was released for iOS7 in 2013 at WWDC.
The Multipeer Connectivity framework provides support for discovering services provided by nearby iOS devices using infrastructure Wi-Fi networks, peer-to-peer Wi-Fi, and Bluetooth personal area networks and subsequently communicating with those services by sending message-based data, streaming data, and resources (such as files).
For me, this framework release was an exciting one; finally a high-level abstraction and implementation of P2P networking for iOS devices existed. MCMultipeerConnectivity is a simple, albeit limiting, framework for a developer to connect multiple iOS devices through Wi-Fi and/or Bluetooth and exchange data. These peer networks can be chained and create a ‘mesh network’. A key selling point of this framework is that the underlying mechanism for how the peer-to-peer network is implemented is completely abstracted away from the developer. The developer deals solely with the abstract concept of peers and invitations and iOS handles the underlying Bluetooth or Wi-Fi communication.
Unfortunately there is one main limiting factor that Apple are yet to address - the framework is unable to work in the background on a device, any existing connections are killed when an app moves to the background. In my opinion, this severely limits the use-cases where this kind of app would be useful in solving certain proximity related problems. Perhaps this limitation is preventing the adoption of P2P as an alternative medium for exchanging data, and also putting off developers from experimenting and innovating with the technology - FireChat was well received by the technology media as an innovator, it was covered extensively by multiple outlets as an ephemeral, to-the-wire, real-time chatroom, yet the buzz surrounding it has since faded into insignificance.
Another limitation in P2P mobile communication is a lack of support from the main vendors for a cross-platform solution. Multipeer Connectivity does not officially support any sort of communication with Android and iOS does not support the Wi-Fi Direct standard that Android uses for P2P communication. Ostensibly some apps have overcome this but have not publicly disclosed their mechanism for doing so, but it is likely to be based around Bluetooth LE technology, the only common ground between the platforms.
I personally believe that P2P technology will have a profound impact on how we communicate, exchange and consume data as time progresses; however big hitters like Apple and Google need to start supporting it in their SDKs at a higher level to ensure that app developers have the tools at their disposal. For me, due to a cacophony of procrastination, perfectionism and sheer disappointment in Apple’s framework, I personally have still yet to release a mobile application utilising peer-to-peer networking.
]]>The simple premise is that hundreds of millions of people have a powerful computer in their pocket that has the untapped ability of rapidly increasing the reach and efficacy of medical studies in ways currently not possible.
The framework, which Apple plan to open-source, will become available to developers in April 2015. It is being peddled as platform-agnostic following Apple’s belief that anyone should be able to collaborate and contribute to the next potential medical breakthrough.
It will have full integration with Apple’s health tool, HealthKit. HealthKit is currently being used in over 900 applications currently live on the App Store - this figure is being pushed as a great achievement by Apple. 900 apps is disappointing and misleading. At a glance, the market for health related apps is extremely bloated and several big contenders still have not integrated with HealthKit.
Medical studies will be able to have full access to a consenting user’s HealthKit data and mine numerous amounts of useful health related metrics; pedometer data, calorific intake and heart rates. Perhaps this increased integration with HealthKit will encourage more apps to use the service - which will greatly enrich the data it stores and the experience for its users.
ResearchKit already has five applications supporting research studies that cover a broad range of conditions. Unfortunately the apps are currently restricted to limited App Store locations, but users from the USA can opt in to these studies today and begin contributing their own metrics and start performing a range of specialist in-app tests. The diseases and conditions being covered currently are:
Mobile applications are used by millions of individuals on a daily basis. Medical studies do not currently have this exposure. The greater the sample size you have for a source of data on any topic, the more relevant and useful that data will be. As described during the video portion of the keynote, breast cancer researchers sent out over 10,000 letters to potential study participants and only received a little over 300 responses. Bloomberg reported that Stanford University woke up the day after the event to find over 11,000 sign-ups to their cardiovascular disease application. This is an incredible feat and truly shows the good intentions behind this framework.
The technical goal of ResearchKit is to make it simple for medical researchers to create mobile applications that expose the iPhone’s various sensors in a structured format in order to measure and track study participants.
Based around the concept of customisable ‘Modules’, the developer can work with the researcher to construct an application suitable for gathering relevant information. The ‘out-of-the-box’ modules available are:
Surveys - a simple Q+A based, customisable interface. The survey module is also fully localized, allowing a developer just to provide a localized strings file for the questions and answers.
Informed Consent - Consent templates that cover a variety of scenarios allow for researchers to ensure that their participants are fully-aware and in agreement to what information they will be sharing with the study. (Ostensibly these templates will have to be customised heavily in order to allow for all the intricacies and ethical concerns regarding starting a medical study).
Active Tasks - Beyond the collection of “passive” data from the device’s HealthKit and co-motion processor sources, developer’s can utilise Active Tasks to retrieve data from the device’s sensors. Categorised under four headings: motor activities, fitness, cognition, voice.
These modules are completely customisable and developers will also be able to create their own. Due to the open-source nature of the framework I am envisioning collaboration between medical authorities, researchers and developers to enhance and augment the existing modules into a much larger and broad platform as time passes.
Neither Apple, nor ResearchKit itself provides any sort of mechanism to transmit data between the app itself and the backend - the onus is on the developer to implement this mechanism. This clearly reaffirms what Apple mentioned during the Spring Forward and their stance on data privacy that Apple will never see the user’s data.
As mentioned, the framework currently is not available publicly to developers, so it isn’t possible to go into a more detailed analysis, so rather than regurgitating it please do read the Technical Overview for further detail.
Numerous ethical and validity concerns have been raised by journalists who have been testing the available applications since the announcement of ResearchKit. It’s been reported that users have been able to modify their age during the study, fabricate information and erroneously complete tests. The quality of the data that will be obtained by researcher’s deploying ResearchKit-based apps is yet to be seen - will researcher’s be able to filter out nonsensical data, anomalies, mistakes and perhaps most importantly, intentional sabotage by online trolls?
It is currently unclear how researchers can recruit new participants into their research studies - if the current App Store marketing process is used to draw parallels the future is not bright. It is fantastic that Stanford have benefited greatly from the exposure of the Apple event, but how will small, independent research groups ‘advertise’ their ResearchKit apps and follow suit and recruit 10,000 participants?
In conclusion, Apple have undeniably, but perhaps naively, broadened their involvement in their customer’s personal health. Through ResearchKit they have enabled a standard approach for researchers around the world to increase their sample size, increase the amount of they receive from that sample and yet again allow the prospect of Big Data to have a larger impact on our day-to-day lives.
]]>