Skip to content

Commit 324de3b

Browse files
joe-henkeAnkaalrikai
authored
feat: Release 2.1.0 (#15)
* Release 2.1.0 * add Info.plist for Example app * ✨ (project.pbxproj, Info.plist): add Info.plist file reference to project configuration to ensure proper resource management ♻️ (Info.plist): remove empty key-value pairs to clean up the plist file and improve readability * ♻️ (project.pbxproj, Info.plist): remove duplicate Info.plist references and update plist structure to ensure proper configuration and avoid conflicts in the project settings. --------- Co-authored-by: Anka <[email protected]> Co-authored-by: Alrik Firl <[email protected]>
1 parent 3ccf883 commit 324de3b

File tree

3 files changed

+95
-16
lines changed

3 files changed

+95
-16
lines changed

Example/Example/Info.plist

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key></key>
6+
<string></string>
7+
<key>UIBackgroundModes</key>
8+
<array>
9+
<string>processing</string>
10+
</array>
11+
</dict>
12+
</plist>

Package.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,33 @@ let package = Package(
3232

3333
.binaryTarget(
3434
name: "ObjcExceptionBridging",
35-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762128.zip",
36-
checksum: "9291aff529fbfd935c37581f49cc8a2365b6aa144e1aa60dc4b9ecc42e217c3f"
35+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114078.zip",
36+
checksum: "a0b4d874f3552b4d956e3cf317246ca819b19fc182cfc3c69cc5b3a0552aed26"
3737
),
3838
.binaryTarget(
3939
name: "_HoverSDK",
40-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762141.zip",
41-
checksum: "ec11f0b3aaed3991d8d9d4224d271fba16e3c0edb8edf99094d49c69b222c128"
40+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114089.zip",
41+
checksum: "92e20a80fff4e804b7de504d33d5f8ab82151cc09ebebff6e3b119cef8c8c5fc"
4242
),
4343
.binaryTarget(
4444
name: "_HVAVCamera",
45-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762129.zip",
46-
checksum: "d463a2cfccc8ca1f6dd41def241aa834657d2e2730f104a00439d4e7004db683"
45+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114083.zip",
46+
checksum: "1719b5d83334946c1b9014b3248a6cab6a003a7a27667257dedb281181d6d189"
4747
),
4848
.binaryTarget(
4949
name: "_HVCore",
50-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762139.zip",
51-
checksum: "65f8e171057a1376a07b9a3dd9a83aacff7842d14484c3f1ac0bb7f532ba7c3a"
50+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114085.zip",
51+
checksum: "39622b20cdc009204fb6f6ab08f5e7851e27df321a4412e00c2598c720488f81"
5252
),
5353
.binaryTarget(
5454
name: "_HVCVPixelBufferHelper",
55-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762130.zip",
56-
checksum: "52450bd150674d69d90acdc375777b765262c86ff546d80672fda1bb78764b62"
55+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114084.zip",
56+
checksum: "6dadefab1a5785cb6834c07de10d4bb2f1796d3f91d877b4ba85b543e16f384a"
5757
),
5858
.binaryTarget(
5959
name: "_XCGLogger",
60-
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/205762148.zip",
61-
checksum: "5c7560658e11b11708b11144b507deb219d33f4dd97703a8429318fa1fd45d01"
60+
url: "https://api.github.com/repos/hoverinc/hover-capture-ios/releases/assets/211114092.zip",
61+
checksum: "6394cefd4625c3f249395faf9a8c9d1140e106c2c743580478f50debd044eb27"
6262
),
6363
]
6464
)

Sources/HVCaptureSDK/HVCaptureSDK.docc/GettingStarted.md

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,72 @@ struct FooView: View {
8080

8181
Note that the SDK executes asynchronously, and the task that calls ``HVPartnerSDK/startCaptureSession(settings:info:)`` will suspend until the capture flow completes. As such, there's a very linear flow to interacting with the SDK, and once the call's `await` returns, the host app knows the SDK's capture session is complete (as seen with the `captureSessionCompleted` function above). If the capture session encountered a fatal error, it will raise the error as an exception.
8282

83+
### Starting an offline Capture & supplying the Job ID later
84+
85+
The host app can launch the SDK without supplying a remote job ID by following these steps:
86+
1. Create a local job using ``HVPartnerSDK/createLocalJob(uuid:)``.
87+
2. Start the capture session using the same local ID from before and setting ``JobIdentifier/jobID`` as well as the ``CaptureJobInformation/uploadSecret`` properties to `nil`.
88+
89+
Once the job ID becomes available use ``HVPartnerSDK/associateClientToRemoteJob(using:)`` to link the local job to its remote counterpart in order for uploads to start.
90+
91+
### Example:
92+
93+
```swift
94+
import SwiftUI
95+
96+
struct FooView: View {
97+
// Create a local job
98+
let jobIdentifier = try HVPartnerSDK.sharedInstance.createLocalJob()
99+
// Or alternatively using a custom local ID
100+
// let jobIdentifier = try HVPartnerSDK.sharedInstance.createLocalJob(uuid: localID)
101+
let info = CaptureJobInformation(
102+
firstTimeUser: false,
103+
// Job identifier has jobID property set to nil
104+
identifier: jobIdentifier,
105+
// Set upload secret to nil
106+
uploadSecret: nil
107+
)
108+
let sessionSettings: HVCameraSettings
109+
110+
// ... populate settings, etc.
111+
112+
var body: some View {
113+
Button("Start Capture") {
114+
let captureTask = Task {
115+
do {
116+
try await HVPartnerSDK.sharedInstance.startCaptureSession(
117+
settings: sessionSettings,
118+
info: jobInfo
119+
)
120+
try await HVPartnerSDK.sharedInstance.startCaptureFlow()
121+
} catch let error as HVSessionError {
122+
// TODO: handle the known errors here
123+
print("Known capture flow error: \(error.localizedDescription)")
124+
} catch {
125+
// TODO: handle unknown errors, who knows what to do
126+
print("Unknown Capture Flow Error: \(error.localizedDescription)")
127+
}
128+
Task {
129+
try await captureSessionCompleted()
130+
}
131+
132+
}
133+
}
134+
}
135+
136+
func captureSessionCompleted() async throws {
137+
// Assuming we have a job id available here
138+
// ...
139+
let input = AssociateClientToRemoteJobInput(
140+
remoteIdentifier: remoteID,
141+
uploadSecret: uploadSecret,
142+
localIdentifier: localID
143+
)
144+
try await HVPartnerSDK.sharedInstance.associateClientToRemoteJob(using: input)
145+
}
146+
}
147+
```
148+
83149
#### Cancelling a Capture Session
84150

85151
Since we execute asynchronously within a Swift `Task`, we also honor its cancellation functionality and stop the capture session and capture flow UI if the task is cancelled.
@@ -107,15 +173,16 @@ DispatchQueue.main.asyncAfter(deadline: .now() + 10, execute: {
107173

108174
Since the capture flow proceeds asynchronously, the host app may want to monitor the local job status as the capture proceeds. There are a few methods for obtaining Job status:
109175

110-
1. on-demand: The ``HVPartnerSDK`` class exposes a public method ``HVPartnerSDK/getClientJobStatus(for:)``. This is an `async` method that will return what the requested `Job`'s current status as a ``JobStatus``. If the requested ``Job`` doesn't exist locally, then it will raise a ``HVJobError`` exception.
176+
1. on-demand: The ``HVPartnerSDK`` class exposes a public method ``HVPartnerSDK/getClientJobStatus(for:)``. This is an `async` method that will return what the requested `Job`'s current status as a ``JobStatus``. If the requested ``Job`` doesn't exist locally, then it will raise a ``HVJobError`` exception.
111177
2. streaming: The ``HVPartnerSDK`` class also exposes a public method ``HVPartnerSDK/getJobStateObservable(for:)`` that returns a `Combine` publisher for the requested `Job`. The publisher will emit ``JobStatus`` instances whenever there's a change in the `Job`'s status. Additionally, `startCaptureSession` will return what the current `Job`'s status is when called, so together with `getJobStateObservable` you can track the whole status history for the `Job` (n.b. the initial state won't be published for a `Job`, so to get the complete status history you need to use the initial state returned from ``HVPartnerSDK/startCaptureSession(settings:info:)`` in conjunction with the publisher from `getJobStateObservable`). The initial Job state will generally be ``JobStatus.Created`` if newly created, or ``JobStatus.Draft`` if resuming an existing Job.
112178

113179
For example, adapting the previous example to monitor the `Job` status and build a complete `JobStatus` history for the capture session, you can do:
114180

115181
```swift
116182
import Combine
117-
import SwiftUI
118183
import HVCaptureSDK
184+
import SwiftUI
185+
import Combine
119186

120187
struct FooView: View {
121188
let jobInfo: CaptureJobInformation
@@ -136,7 +203,7 @@ struct FooView: View {
136203
// check if we have a listener for the job already, so we don't make duplicate listeners each time the view is created
137204
if jobCancellables[jobInfo.identifier] == nil {
138205
let cancellable = HVPartnerSDK.sharedInstance.getJobStateObservable(for: jobInfo.identifier).sink(receiveValue: { (jobState: JobStatus) in
139-
// NOTE: you can take various actions here based on the status change
206+
// NOTE: you can t ake various actions here based on the status change
140207
if case let .uploadProgress(_, uploadStatus) = jobState {
141208
print("Job@State: \(jobState) --> File@State: \(String(describing: uploadStatus))")
142209
} else if case let .error(_, error) = jobState {
@@ -192,4 +259,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
192259

193260
> Warning: Since we use `BGTaskScheduler` for our background processing, we need to call ``HVPartnerSDK/registerForBackgroundJobs()`` **before** the application finishes launching. If not, then the application will raise an `NSInternalInconsistencyException` exception with the reason: `'All launch handlers must be registered before application finishes launching'`. This is a constraint imposed by the [BGTaskScheduler framework itself](https://developer.apple.com/documentation/backgroundtasks/bgtaskscheduler/register(fortaskwithidentifier:using:launchhandler:)#Discussion) and if ignored will likely crash the application.
194261

195-
While using `registerForBackgroundJobs` enables the SDK to schedule background tasks on its own as needed, it's also possible to disable automatic background task scheduling and have more manual control over background task scheduling. This can be useful for applications that want closer control over background tasks spawned from the SDK and which already have their own background task scheduling. This can be achieved by **not** calling ``HVPartnerSDK/registerForBackgroundJobs()``, and instead calling ``HVPartnerSDK/initializeForBackground(parameters:)`` from within a [BGProcessingTask](https://developer.apple.com/documentation/backgroundtasks/bgprocessingtask). Under the hood, this will check if there are pending uploads. If there are no pending uploads, then it will exit and do nothing. If there are, then it'll run asynchronously and attempt to complete the pending uploads, performing a single upload at a time and exiting once the pending upload queue has been completed.
262+
While using `registerForBackgroundJobs` enables the SDK to schedule background tasks on its own as needed, it's also possible to disable automatic background task scheduling and have more manual control over background task scheduling. This can be useful for applications that want closer control over background tasks spawned from the SDK and which already have their own background task scheduling. This can be achieved by **not** calling ``HVPartnerSDK/registerForBackgroundJobs()``, and instead calling ``HVPartnerSDK/initializeForBackground(parameters:)`` from within a [BGProcessingTask](https://developer.apple.com/documentation/backgroundtasks/bgprocessingtask). Under the hood, this will check if there are pending uploads. If there are no pending uploads, then it will exit and do nothing. If there are, then it'll run asynchronously and attempt to complete the pending uploads, performing a single upload at a time and exiting once the pending upload queue has been completed.

0 commit comments

Comments
 (0)