Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DeviceDiscoveryUI] Added bindings for DeviceDiscoveryUI. #20271

Merged
merged 12 commits into from
Mar 8, 2024
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
Loading