Skip to content

Commit

Permalink
[DeviceDiscoveryUI] Added bindings for DeviceDiscoveryUI. (#20271)
Browse files Browse the repository at this point in the history
Follow-up of #15762.

---------

Co-authored-by: Israel Soto <[email protected]>
  • Loading branch information
rolfbjarne and Israel Soto committed Mar 8, 2024
1 parent e462d9e commit 58e382e
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 8 deletions.
62 changes: 62 additions & 0 deletions src/DeviceDiscoveryUI/DDDevicePickerViewController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// Custom methods for DDDevicePickerViewController
//
// Authors:
// Israel Soto <[email protected]>
//
// Copyright 2022 Microsoft Corporation.
//

#nullable enable

using ObjCRuntime;
using Foundation;
using Network;
using System;

using OS_nw_endpoint = System.IntPtr;
using OS_nw_error = System.IntPtr;

namespace DeviceDiscoveryUI {

public partial class DDDevicePickerViewController {
/// <summary>
/// The type of the delegate that will be called when the user selects a device in the list of devices.
/// </summary>
public delegate void DevicePickerCompletionHandler (NWEndpoint? endpoint, NWError? error);

/// <summary>
/// Checks if device discovery is supported for the current device
/// </summary>
public static bool IsSupported (NWBrowserDescriptor browseDescriptor, NWParameters? parameters) =>
_IsSupported (browseDescriptor.GetNonNullHandle (nameof (browseDescriptor)), parameters.GetHandle ());

/// <summary>
/// A view controller that lists other devices on your network.
/// </summary>
/// <remarks>
/// Verify if this controller is supported by calling DDDevicePickerViewController.IsSupported before creating an instance, as this will crash if not supported.
/// </remarks>
[DesignatedInitializer]
public DDDevicePickerViewController (NWBrowserDescriptor browseDescriptor, NWParameters? parameters) : base (NSObjectFlag.Empty) =>
InitializeHandle (
_InitWithBrowseDescriptorAndParameters (browseDescriptor.GetNonNullHandle (nameof (browseDescriptor)), parameters.GetHandle ()),
"initWithBrowseDescriptor:parameters:");

/// <summary>
/// Set the delegate that will be called when the user selects a device in list of devices.
/// </summary>
public void SetDevicePicker (DevicePickerCompletionHandler devicePickerCompletionHandler)
{
_SetDevicePicker (InternalDevicePickerCompletionHandler);

void InternalDevicePickerCompletionHandler (OS_nw_endpoint endpoint, OS_nw_error error)
{
NWEndpoint? ep = endpoint != IntPtr.Zero ? new NWEndpoint (endpoint, false) : null;
NWError? er = error != IntPtr.Zero ? new NWError (error, false) : null;

devicePickerCompletionHandler (ep, er);
}
}
}
}
3 changes: 3 additions & 0 deletions src/build/generator-frameworks.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ partial class Frameworks {
"CoreText",
"CoreVideo",
"DeviceCheck",
"DeviceDiscoveryUI",
"ExternalAccessory",
"Foundation",
"GameController",
Expand Down Expand Up @@ -603,6 +604,7 @@ partial class Frameworks {
bool? _CoreVideo;
bool? _CoreWlan;
bool? _DeviceCheck;
bool? _DeviceDiscoveryUI;
bool? _EventKit;
bool? _EventKitUI;
bool? _ExecutionPolicy;
Expand Down Expand Up @@ -768,6 +770,7 @@ partial class Frameworks {
public bool HaveCoreVideo { get { if (!_CoreVideo.HasValue) _CoreVideo = GetValue ("CoreVideo"); return _CoreVideo.Value; } }
public bool HaveCoreWlan { get { if (!_CoreWlan.HasValue) _CoreWlan = GetValue ("CoreWlan"); return _CoreWlan.Value; } }
public bool HaveDeviceCheck { get { if (!_DeviceCheck.HasValue) _DeviceCheck = GetValue ("DeviceCheck"); return _DeviceCheck.Value; } }
public bool HaveDeviceDiscoveryUI { get { if (!_DeviceDiscoveryUI.HasValue) _DeviceDiscoveryUI = GetValue ("DeviceDiscoveryUI"); return _DeviceDiscoveryUI.Value; } }
public bool HaveEventKit { get { if (!_EventKit.HasValue) _EventKit = GetValue ("EventKit"); return _EventKit.Value; } }
public bool HaveEventKitUI { get { if (!_EventKitUI.HasValue) _EventKitUI = GetValue ("EventKitUI"); return _EventKitUI.Value; } }
public bool HaveExecutionPolicy { get { if (!_ExecutionPolicy.HasValue) _ExecutionPolicy = GetValue ("ExecutionPolicy"); return _ExecutionPolicy.Value; } }
Expand Down
46 changes: 46 additions & 0 deletions src/devicediscoveryui.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// DeviceDiscoveryUI C# bindings
//
// Authors:
// Israel Soto <[email protected]>
//
// Copyright 2022 Microsoft Corporation.
//

using System;
using Foundation;
using ObjCRuntime;
using UIKit;

using OS_nw_browse_descriptor = System.IntPtr;
using OS_nw_parameters = System.IntPtr;
using OS_nw_endpoint = System.IntPtr;
using OS_nw_error = System.IntPtr;

#if !NET
using NativeHandle = System.IntPtr;
#endif

namespace DeviceDiscoveryUI {

[Internal]
delegate void _DevicePickerCompletionHandler ([NullAllowed] OS_nw_endpoint endpoint, [NullAllowed] OS_nw_error error);

[NoMac, NoiOS, NoMacCatalyst, NoWatch, TV (16, 0)]
[BaseType (typeof (UIViewController))]
[DisableDefaultCtor]
interface DDDevicePickerViewController {
[Internal]
[Static]
[Export ("isSupportedForBrowseDescriptor:parameters:")]
bool _IsSupported (OS_nw_browse_descriptor browseDescriptor, [NullAllowed] OS_nw_parameters parameters);

[Internal]
[Export ("initWithBrowseDescriptor:parameters:")]
NativeHandle _InitWithBrowseDescriptorAndParameters (OS_nw_browse_descriptor browseDescriptor, [NullAllowed] OS_nw_parameters parameters);

[Internal]
[Export ("setDevicePickerCompletionHandler:")]
void _SetDevicePicker (_DevicePickerCompletionHandler devicePickerCompletionHandler);
}
}
6 changes: 6 additions & 0 deletions src/frameworks.sources
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,11 @@ COREWLAN_SOURCES = \
CoreWlan/CWInterface.cs \
CoreWlan/CWKeychain.cs \

# DeviceDiscoveryUI

DEVICEDISCOVERYUI_SOURCES = \
DeviceDiscoveryUI/DDDevicePickerViewController.cs \

# EventKit

EVENTKIT_API_SOURCES = \
Expand Down Expand Up @@ -2318,6 +2323,7 @@ TVOS_FRAMEWORKS = \
CoreLocation \
CoreSpotlight \
CoreText \
DeviceDiscoveryUI \
ExternalAccessory \
GLKit \
GameController \
Expand Down
1 change: 1 addition & 0 deletions src/rsp/dotnet/tvos-defines-dotnet.rsp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
-d:HAS_CORETEXT
-d:HAS_COREVIDEO
-d:HAS_DEVICECHECK
-d:HAS_DEVICEDISCOVERYUI
-d:HAS_EXTERNALACCESSORY
-d:HAS_FOUNDATION
-d:HAS_GAMECONTROLLER
Expand Down
1 change: 1 addition & 0 deletions src/rsp/tvos-defines.rsp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
-d:HAS_CORETEXT
-d:HAS_COREVIDEO
-d:HAS_DEVICECHECK
-d:HAS_DEVICEDISCOVERYUI
-d:HAS_EXTERNALACCESSORY
-d:HAS_FOUNDATION
-d:HAS_GAMECONTROLLER
Expand Down
10 changes: 10 additions & 0 deletions tests/cecil-tests/Documentation.KnownFailures.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17555,6 +17555,7 @@ F:ObjCRuntime.Constants.CoreVideoLibrary
F:ObjCRuntime.Constants.CoreWlanLibrary
F:ObjCRuntime.Constants.CryptoTokenKitLibrary
F:ObjCRuntime.Constants.DeviceCheckLibrary
F:ObjCRuntime.Constants.DeviceDiscoveryUILibrary
F:ObjCRuntime.Constants.EventKitLibrary
F:ObjCRuntime.Constants.EventKitUILibrary
F:ObjCRuntime.Constants.ExecutionPolicyLibrary
Expand Down Expand Up @@ -60018,6 +60019,14 @@ M:DeviceCheck.DCDeviceGenerateTokenCompletionHandler.BeginInvoke(Foundation.NSDa
M:DeviceCheck.DCDeviceGenerateTokenCompletionHandler.EndInvoke(System.IAsyncResult)
M:DeviceCheck.DCDeviceGenerateTokenCompletionHandler.Invoke(Foundation.NSData,Foundation.NSError)
M:DeviceCheck.DCErrorExtensions.GetDomain(DeviceCheck.DCError)
M:DeviceDiscoveryUI.DDDevicePickerViewController.#ctor(Foundation.NSCoder)
M:DeviceDiscoveryUI.DDDevicePickerViewController.#ctor(Foundation.NSObjectFlag)
M:DeviceDiscoveryUI.DDDevicePickerViewController.#ctor(ObjCRuntime.NativeHandle)
M:DeviceDiscoveryUI.DDDevicePickerViewController.DevicePickerCompletionHandler.#ctor(System.Object,System.IntPtr)
M:DeviceDiscoveryUI.DDDevicePickerViewController.DevicePickerCompletionHandler.BeginInvoke(Network.NWEndpoint,Network.NWError,System.AsyncCallback,System.Object)
M:DeviceDiscoveryUI.DDDevicePickerViewController.DevicePickerCompletionHandler.EndInvoke(System.IAsyncResult)
M:DeviceDiscoveryUI.DDDevicePickerViewController.DevicePickerCompletionHandler.Invoke(Network.NWEndpoint,Network.NWError)
M:DeviceDiscoveryUI.DDDevicePickerViewController.get_ClassHandle
M:EventKit.EKAlarm.#ctor(Foundation.NSObjectFlag)
M:EventKit.EKAlarm.#ctor(ObjCRuntime.NativeHandle)
M:EventKit.EKAlarm.get_ClassHandle
Expand Down Expand Up @@ -127615,6 +127624,7 @@ P:DeviceCheck.DCAppAttestService.Supported
P:DeviceCheck.DCDevice.ClassHandle
P:DeviceCheck.DCDevice.CurrentDevice
P:DeviceCheck.DCDevice.Supported
P:DeviceDiscoveryUI.DDDevicePickerViewController.ClassHandle
P:EventKit.EKAlarm.AbsoluteDate
P:EventKit.EKAlarm.ClassHandle
P:EventKit.EKAlarm.EmailAddress
Expand Down
2 changes: 2 additions & 0 deletions tests/introspection/ApiSelectorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,8 @@ protected virtual bool SkipInit (string selector, MethodBase m)
// CloudKit
case "initWithExcludedZoneIDs:":
case "initWithZoneIDs:":
// DDDevicePickerViewController
case "initWithBrowseDescriptor:parameters:":
return true;
default:
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//
// Unit tests for DDDevicePickerViewController
//
// Authors:
// Israel Soto <[email protected]>
//
// Copyright 2022 Microsoft Corporation.
//

#if __TVOS__

using System;
using DeviceDiscoveryUI;
using Foundation;
using ObjCRuntime;
using Network;
using NUnit.Framework;
using Xamarin.Utils;

namespace MonoTouchFixtures.DeviceDiscoveryUI {

[TestFixture]
[Preserve (AllMembers = true)]
public class DDDevicePickerViewControllerTest {

const string serviceName = "MyAppService";

[OneTimeSetUp]
public void Init () => TestRuntime.AssertXcodeVersion (14, 0);

[Test]
public void IsSupportedTest ()
{
var browserDescriptor = NWBrowserDescriptor.CreateApplicationServiceName (serviceName);
var parameters = NWParameters.CreateApplicationService ();
var isSupported = DDDevicePickerViewController.IsSupported (browserDescriptor, parameters);

// DDDevicePickerViewController seems to work only for devices
if (TestRuntime.IsSimulator)
Assert.IsFalse (isSupported, "IsSupported");
else
Assert.IsTrue (isSupported, "IsSupported");
}

[Test]
public void InitWithBrowseDescriptorAndParametersTest ()
{
// DDDevicePickerViewController seems to work only for devices
TestRuntime.AssertNotSimulator ();

var browserDescriptor = NWBrowserDescriptor.CreateApplicationServiceName (serviceName);
var parameters = NWParameters.CreateApplicationService ();
var isSupported = DDDevicePickerViewController.IsSupported (browserDescriptor, parameters);

// If this fails, please, double check that MyAppService is registered within the Info.plist
// https://developer.apple.com/documentation/bundleresources/information_property_list/nsapplicationservices
Assert.IsTrue (isSupported, $"The {serviceName} key might not be registered in the Info.plist.");

Assert.DoesNotThrow (() => { var devicePicker = new DDDevicePickerViewController (browserDescriptor, parameters); },
"InitWithBrowseDescriptorAndParameters");
}

[Test]
public void SetDevicePickerTest ()
{
// DDDevicePickerViewController seems to work only for devices
TestRuntime.AssertNotSimulator ();

var browserDescriptor = NWBrowserDescriptor.CreateApplicationServiceName (serviceName);
var parameters = NWParameters.CreateApplicationService ();
var isSupported = DDDevicePickerViewController.IsSupported (browserDescriptor, parameters);

// If this fails, please, double check that MyAppService is registered within the Info.plist
// https://developer.apple.com/documentation/bundleresources/information_property_list/nsapplicationservices
Assert.IsTrue (isSupported, $"The {serviceName} key might not be registered in the Info.plist.");

Assert.DoesNotThrow (() => {
var devicePicker = new DDDevicePickerViewController (browserDescriptor, parameters);
devicePicker.SetDevicePicker ((endpoint, error) => { });
},
"SetDevicePicker");
}
}
}

#endif // __TVOS__
17 changes: 17 additions & 0 deletions tests/monotouch-test/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,22 @@
<array>
<string>processing</string>
</array>
<key>NSApplicationServices</key>
<dict>
<key>Browses</key>
<array>
<dict>
<key>NSApplicationServiceIdentifier</key>
<string>MyAppService</string>
<key>NSApplicationServicePlatformSupport</key>
<array>
<string>iPadOS</string>
<string>iOS</string>
</array>
<key>NSApplicationServiceUsageDescription</key>
<string>You can control this app using an iOS device.</string>
</dict>
</array>
</dict>
</dict>
</plist>
1 change: 1 addition & 0 deletions tests/monotouch-test/monotouch-test.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
<Folder Include="NearbyInteraction\" />
<Folder Include="MetricKit\" />
<Folder Include="SharedWithYouCore\" />
<Folder Include="DeviceDiscoveryUI\" />
</ItemGroup>
<ItemGroup>
<Content Include="AudioToolbox\1.caf" />
Expand Down

This file was deleted.

4 changes: 0 additions & 4 deletions tests/xtro-sharpie/tvOS-DeviceDiscoveryUI.todo

This file was deleted.

1 change: 1 addition & 0 deletions tools/common/Frameworks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ public static Frameworks TVOSFrameworks {
#if !NET
{ "Chip", "CHIP", new Version (15, 0), NotAvailableInSimulator /* no headers in beta 2 */ },
#endif
{ "DeviceDiscoveryUI", "DeviceDiscoveryUI", 16,0 },
{ "OSLog", "OSLog", 15,0 },
{ "CoreMidi", "CoreMIDI", 15,0 },
{ "ShazamKit", "ShazamKit", new Version (15, 0), NotAvailableInSimulator},
Expand Down

8 comments on commit 58e382e

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.