mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 07:36:10 -04:00
Add Advertiser and Discoverer to the Swift layer
PiperOrigin-RevId: 490301361
This commit is contained in:
committed by
Copybara-Service
parent
808611f316
commit
defd5e03e7
@@ -12,6 +12,135 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import NearbyCoreAdapter
|
||||
|
||||
public class Advertiser {}
|
||||
/// Publishes an advertisement and notifies its delegate about connection requests from nearby
|
||||
/// endpoints.
|
||||
public class Advertiser {
|
||||
|
||||
/// The delegate object that handles advertising-related events.
|
||||
public weak var delegate: AdvertiserDelegate?
|
||||
|
||||
/// The connection manager for this instance.
|
||||
public let connectionManager: ConnectionManager
|
||||
|
||||
lazy var connection: InternalConnection? = {
|
||||
let connection = InternalConnection()
|
||||
connection.delegate = self
|
||||
return connection
|
||||
}()
|
||||
|
||||
/// Initializes the discoverer object.
|
||||
///
|
||||
/// - Parameter connectionManager: The connection manager for this instance.
|
||||
public init(connectionManager: ConnectionManager) {
|
||||
self.connectionManager = connectionManager
|
||||
}
|
||||
|
||||
/// Starts advertising the local endpoint.
|
||||
///
|
||||
/// After this method is called (until you call `stopAdvertising()`), the framework calls your
|
||||
/// delegate’s `advertiser(_:didReceiveConnectionRequestFrom:with:connectionRequestHandler:)`
|
||||
/// method when remote endpoints request a connection.
|
||||
public func startAdvertising(using context: Data) {
|
||||
let options = GNCAdvertisingOptions(strategy: connectionManager.strategy.objc)
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.startAdvertising(
|
||||
asService: connectionManager.serviceID, endpointInfo: context,
|
||||
options: options, delegate: connection)
|
||||
}
|
||||
|
||||
/// Stops advertising the local endpoint.
|
||||
public func stopAdvertising() {
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.stopAdvertising()
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopAdvertising()
|
||||
}
|
||||
}
|
||||
|
||||
extension Advertiser: InternalConnectionDelegate {
|
||||
|
||||
func connected(
|
||||
toEndpoint endpointID: String, withEndpointInfo info: Data, authenticationToken: String
|
||||
) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.delegate?.advertiser(self, didReceiveConnectionRequestFrom: endpointID, with: info) {
|
||||
(accept) in
|
||||
guard accept else {
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.rejectConnectionRequest(fromEndpoint: endpointID)
|
||||
return
|
||||
}
|
||||
self.connectionManager.delegate?.connectionManager(
|
||||
self.connectionManager, didChangeTo: .connecting, for: endpointID)
|
||||
self.connectionManager.delegate?.connectionManager(
|
||||
self.connectionManager, didReceive: authenticationToken, from: endpointID
|
||||
) { accept in
|
||||
guard accept else {
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.rejectConnectionRequest(fromEndpoint: endpointID)
|
||||
return
|
||||
}
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.acceptConnectionRequest(
|
||||
fromEndpoint: endpointID, delegate: self.connectionManager.payload)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acceptedConnection(toEndpoint endpointID: String) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .connected, for: endpointID)
|
||||
}
|
||||
}
|
||||
|
||||
func rejectedConnection(toEndpoint endpointID: String, with status: GNCStatus) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .rejected, for: endpointID)
|
||||
}
|
||||
}
|
||||
|
||||
func disconnected(fromEndpoint endpointID: String) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .disconnected, for: endpointID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `AdvertiserDelegate` protocol defines methods that an `Advertiser` object’s delegate can
|
||||
/// implement to handle advertising-related events.
|
||||
///
|
||||
/// Delegate methods are executed on the `.main` queue by default, but a specific `DispatchQueue` on
|
||||
/// which to call the delegate methods can be passed to `ConnectionManager`.
|
||||
public protocol AdvertiserDelegate: AnyObject {
|
||||
|
||||
/// Called when a connection request is received from a nearby endpoint.
|
||||
///
|
||||
/// Important: Accepting a connection request will not yet establish a connection that allows
|
||||
/// data transference. The connection must first be verified by both parties via the
|
||||
/// `ConnectionManagerDelegate`, before data can flow freely.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - advertiser: The advertiser object that received a connection request.
|
||||
/// - endpointID: The endpoint ID of the nearby enpoint that requested the connection.
|
||||
/// - info: An arbitrary piece of data received from the nearby endpoint. This can be used to
|
||||
/// provide further information to the user about the nature of the invitation.
|
||||
/// - connectionRequestHandler: A block that your code must call to indicate whether the
|
||||
/// advertiser should accept or decline the connection request.
|
||||
func advertiser(
|
||||
_ advertiser: Advertiser, didReceiveConnectionRequestFrom endpointID: EndpointID,
|
||||
with context: Data, connectionRequestHandler: @escaping (Bool) -> Void)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,171 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import NearbyCoreAdapter
|
||||
|
||||
public class Discoverer {}
|
||||
/// Searches for nearby endpoints and provides the ability to request connections to them.
|
||||
public class Discoverer {
|
||||
|
||||
/// The delegate object that handles discovery-related events.
|
||||
public weak var delegate: DiscovererDelegate?
|
||||
|
||||
/// The connection manager for this instance.
|
||||
public let connectionManager: ConnectionManager
|
||||
|
||||
lazy var connection: InternalConnection? = {
|
||||
let connection = InternalConnection()
|
||||
connection.delegate = self
|
||||
return connection
|
||||
}()
|
||||
|
||||
lazy var discovery: InternalDiscovery? = {
|
||||
let discovery = InternalDiscovery()
|
||||
discovery.delegate = self
|
||||
return discovery
|
||||
}()
|
||||
|
||||
/// Initializes the discoverer object.
|
||||
///
|
||||
/// - Parameter connectionManager: The connection manager for this instance.
|
||||
public init(connectionManager: ConnectionManager) {
|
||||
self.connectionManager = connectionManager
|
||||
}
|
||||
|
||||
/// Starts searching for nearby remote endpoints.
|
||||
///
|
||||
/// After this method is called (until you call `stopDiscovery()`), the framework calls your
|
||||
/// delegate’s `discoverer(_:didFind:with:)` and `discoverer(_:didLose:)` methods as new endpoints
|
||||
/// are found and lost.
|
||||
public func startDiscovery() {
|
||||
let options = GNCDiscoveryOptions(strategy: connectionManager.strategy.objc)
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.startDiscovery(
|
||||
asService: connectionManager.serviceID, options: options, delegate: discovery)
|
||||
}
|
||||
|
||||
/// Stops searching for nearby remote endpoints.
|
||||
public func stopDiscovery() {
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.stopDiscovery()
|
||||
}
|
||||
|
||||
/// Requests a connection to a discovered remote endpoint.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - endpointID: The ID of the endpoint to request a connection to.
|
||||
/// - context: An arbitrary piece of data that is passed to the nearby endpoint. This can be
|
||||
/// used to provide further information to the user about the nature of the invitation.
|
||||
public func requestConnection(to endpointID: EndpointID, using context: Data) {
|
||||
let options = GNCConnectionOptions()
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.requestConnection(
|
||||
toEndpoint: endpointID, endpointInfo: context,
|
||||
options: options, delegate: connection)
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopDiscovery()
|
||||
}
|
||||
}
|
||||
|
||||
extension Discoverer: InternalConnectionDelegate {
|
||||
|
||||
func connected(
|
||||
toEndpoint endpointID: String, withEndpointInfo info: Data, authenticationToken: String
|
||||
) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .connecting, for: endpointID)
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didReceive: authenticationToken, from: endpointID
|
||||
) { accept in
|
||||
guard accept else {
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.rejectConnectionRequest(fromEndpoint: endpointID)
|
||||
return
|
||||
}
|
||||
// TODO(b/257824412): Handle errors from completion handler.
|
||||
GNCCoreAdapter.shared.acceptConnectionRequest(
|
||||
fromEndpoint: endpointID, delegate: connectionManager.payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func acceptedConnection(toEndpoint endpointID: String) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .connected, for: endpointID)
|
||||
}
|
||||
}
|
||||
|
||||
func rejectedConnection(toEndpoint endpointID: String, with status: GNCStatus) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .rejected, for: endpointID)
|
||||
}
|
||||
}
|
||||
|
||||
func disconnected(fromEndpoint endpointID: String) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let connectionManager = self?.connectionManager else { return }
|
||||
connectionManager.delegate?.connectionManager(
|
||||
connectionManager, didChangeTo: .disconnected, for: endpointID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Discoverer: InternalDiscoveryDelegate {
|
||||
|
||||
func foundEndpoint(_ endpointID: String, withEndpointInfo info: Data) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.delegate?.discoverer(self, didFind: endpointID, with: info)
|
||||
}
|
||||
}
|
||||
|
||||
func lostEndpoint(_ endpointID: String) {
|
||||
connectionManager.queue.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.delegate?.discoverer(self, didLose: endpointID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `DiscovererDelegate` protocol defines methods that a `Discoverer` object’s delegate can
|
||||
/// implement to handle discovery-related events.
|
||||
///
|
||||
/// Delegate methods are executed on the `.main` queue by default, but a specific `DispatchQueue` on
|
||||
/// which to call the delegate methods can be passed to `ConnectionManager`.
|
||||
public protocol DiscovererDelegate: AnyObject {
|
||||
|
||||
/// Called when a nearby endpoint is found.
|
||||
///
|
||||
/// The endpoint ID provided to this delegate method can be used to request a connection with the
|
||||
/// nearby endpoint.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - discoverer: The discoverer object that found the nearby endpoint.
|
||||
/// - endpointID: The unique ID of the endpoint that was found.
|
||||
/// - context: An arbitrary piece of data received from the nearby endpoint. This can be used to
|
||||
/// provide further information to the user about the nature of the invitation.
|
||||
func discoverer(_ discoverer: Discoverer, didFind endpointID: EndpointID, with context: Data)
|
||||
|
||||
/// Called when a nearby endpoint is lost.
|
||||
///
|
||||
/// This callback informs your app that connection requests can no longer be sent to an endpoint,
|
||||
/// and that your app should remove that endpoint from its user interface.
|
||||
///
|
||||
/// Important: Because there is a delay between when a discovered endpoint disappears and when
|
||||
/// Nearby Connections detects that it has left, the fact that your app has not yet received a
|
||||
/// disappearance callback does not guarantee that it can communicate with the endpoint
|
||||
/// successfully.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - discoverer: The discoverer object that lost the nearby endpoint.
|
||||
/// - endpointID: The unique ID of the nearby endpoint that was lost.
|
||||
func discoverer(_ discoverer: Discoverer, didLose endpointID: EndpointID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user