├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── global.json └── src ├── essential-interfaces-generator ├── Helpers │ ├── DeclarationSyntaxWalker.cs │ ├── Ext.cs │ └── KnownEnvironmentVariable.cs ├── Models │ ├── ApiMemberModel.cs │ ├── ApiModel.cs │ ├── GeneratorContext.cs │ ├── ImplementationGenerationMode.cs │ └── MemberKind.cs ├── Program.cs ├── Tasks │ ├── ImplementationGenerator.cs │ ├── NugetPackageMetadataProvider.cs │ ├── ProjectMutator.cs │ └── RoslynModelGenerator.cs └── essential-interfaces-generator.csproj ├── essential-interfaces.sln └── output └── Essential.Interfaces ├── Essential.Interfaces.csproj ├── Essential.Interfaces.csproj.DotSettings ├── Essentials.cs ├── IEssentialsImplementation.cs ├── LinkerSafe.cs └── Maui └── MauiEssentials.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodule/Essentials"] 2 | path = submodule/Essentials 3 | url = https://github.com/xamarin/Essentials.git 4 | branch = main 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ryan Davis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # essential-interfaces-generator 2 | Generates interfaces for the [Xamarin.Essentials](https://github.com/xamarin/Essentials) library. 3 | 4 | 📝️ **For .NET MAUI Users**: the base MAUI library includes the originally-separate Essentials APIs, and they come with interfaces out of the box - hurrah! 5 | So you don't need to use this any more. If you install a recent version of Xamarin.Essentials.Interfaces into a MAUI app, you'll get 'compatibility interfaces'. 6 | These match the 'shape' of Xamarin.Essentials interfaces, but also implement and delegate to the MAUI interfaces and implementations, 7 | [which have been moved into various different namespaces](https://github.com/dotnet/maui/pull/5562). This gives you the option of deferring the namespace changes, 8 | or (with the help of a few global usings) keeping your code compatible with both XF and MAUI for the time being. 9 | 10 | If you're after the interfaces themselves, you can install them from [NuGet](https://www.nuget.org/packages/Xamarin.Essentials.Interfaces): 11 | 12 | ` 13 | Install-Package Xamarin.Essentials.Interfaces 14 | ` 15 | 16 | You can also grab the raw source outputs from [here](https://essential-interfaces.azurewebsites.net/) (see the end of this readme for a few more details). 17 | 18 | #### Why would I want this? 19 | The Xamarin.Essentials library is a great initiative by the Xamarin team to provide a simple, consolidated, endorsed and low-overhead set of cross-platform apis for mobile applications. As a core design decision, the Essentials library does not include any interfaces - [for several reasons](https://github.com/xamarin/Essentials/wiki/FAQ-%7C-Essentials#where-are-the-interfaces) - and all features are accessed via static methods, properties and events. If you use dependency injection in your mobile apps, you may miss the interfaces that the 'old skool' plugins for Xamarin typically shipped with - fret not, essential-interfaces-generator is here! 20 | 21 | #### How does it work? 22 | essential-interface-generator reads the Xamarin.Essentials source and generates an intermediate model representing the apis exposed by Xamarin.Essentials (`RoslynModelGenerator`). It then uses that model to generate C# code containing matching interface definitions for the apis, and implementations for interfaces that forward members on to the static classes provided by Xamarin Essentials (`ImplementationGenerator`). These are dropped into an output project with some basic version information (`ProjectMutator`) and packed for NuGet. 23 | 24 | #### How do I use the interfaces? 25 | Install the NuGet package and get registering! Each Xamarin.Essentials api has a matching interface and implementation in the `Xamarin.Essentials.Interfaces` and `Xamarin.Essentials.Implementation` namespaces respectively. These follow a basic pattern: 26 | 27 | *Xamarin.Essentials API*: `Thing` 28 | *Interface*: `IThing` 29 | *Implementation*: `ThingImplementation` 30 | 31 | Knowing this, you can register each implementation you need with its matching interface. For example: 32 | 33 | ```cs 34 | using Xamarin.Essentials.Implementation; 35 | using Xamarin.Essentials.Interfaces; 36 | 37 | builder.Register(); 38 | builder.Register(); 39 | ``` 40 | 41 | Alternatively, you can use the marker interface `IEssentialsImplementation` (adopted by all implementation classes) and reflection to find and register all implementation classes at once. When using this approach, you may need to hint the linker to preserve the implementations (since they are never directly referenced). The technique typically used for this purpose is [falseflagging](https://docs.microsoft.com/en-us/xamarin/android/deploy-test/linker#falseflag). 42 | 43 | For mocking, just work as you would with any other mocks: 44 | ```cs 45 | var mockGeo = new Mock(); 46 | mockGeo.Setup(x => x.GetPlacemarksAsync(It.IsAny(), It.IsAny())) 47 | .ReturnsAsync(Enumerable.Empty()); 48 | // etc. 49 | ``` 50 | 51 | #### Does it play nice with the Mono Linker? 52 | Yes. The generated assembly is marked with the `LinkerSafe` attribute, making it eligible for linking regardless of the link level of your consuming project. Only the types and members you invoke from your application are included in compiled outputs, even if you register them all. You can verify this using a dissassembler like dotPeek. 53 | 54 | #### Is reading from the source directly a bit brittle? 55 | Probably. The generator makes assumptions based on the current conventions in the repo. Since it is being run against each commit in the Xamarin.Essentials repo, any breaking changes should become clear quickly enough. 56 | 57 | #### I just want to get the raw output! 58 | No problems, you totally can! The interfaces and implementations being generated off each commit to Xamarin.Essentials are available [here](https://essential-interfaces.azurewebsites.net/). That's a mono/WASM page so give it a few seconds to load. 59 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "6.0.304" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Helpers/DeclarationSyntaxWalker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Microsoft.CodeAnalysis; 3 | 4 | namespace EssentialInterfaces.Helpers 5 | { 6 | public class DeclarationSyntaxWalker : SyntaxWalker 7 | where T : SyntaxNode 8 | { 9 | public bool Descend { get; set; } 10 | public List Members { get; private set; } = new List(); 11 | 12 | public override void Visit(SyntaxNode node) 13 | { 14 | if (node is T) 15 | { 16 | Members.Add(node as T); 17 | 18 | if (Descend) 19 | base.Visit(node); 20 | } 21 | else 22 | base.Visit(node); 23 | } 24 | 25 | public List Visit(SyntaxTree tree) 26 | { 27 | Members = new List(); 28 | Visit(tree.GetRoot()); 29 | return Members; 30 | } 31 | 32 | public List VisitNode(SyntaxNode node) 33 | { 34 | Members = new List(); 35 | Visit(node); 36 | return Members; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Helpers/Ext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using EssentialInterfaces.Models; 5 | using Microsoft.CodeAnalysis; 6 | using Microsoft.CodeAnalysis.CSharp; 7 | using Microsoft.CodeAnalysis.CSharp.Syntax; 8 | using Newtonsoft.Json; 9 | using CSharpExtensions = Microsoft.CodeAnalysis.CSharpExtensions; 10 | 11 | namespace EssentialInterfaces.Helpers 12 | { 13 | public static class Ext 14 | { 15 | public static List GetDeclarations(this SyntaxTree tree, bool nest = false) 16 | where T : SyntaxNode 17 | => new DeclarationSyntaxWalker 18 | { 19 | Descend = nest 20 | } 21 | .Visit(tree); 22 | 23 | public static List GetDeclarations(this SyntaxNode tree, bool nest = false) 24 | where T : SyntaxNode 25 | => new DeclarationSyntaxWalker 26 | { 27 | Descend = nest 28 | } 29 | .VisitNode(tree); 30 | 31 | public static bool Contains(this SyntaxTokenList list, SyntaxKind modifier) 32 | => list.Any(x => CSharpExtensions.IsKind((SyntaxToken) x, modifier)); 33 | 34 | public static bool IsPublicSettable(this PropertyDeclarationSyntax p) 35 | => p.AccessorList?.Accessors.Any(x => x.IsKind(SyntaxKind.SetAccessorDeclaration) 36 | && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))) ?? false; 37 | 38 | public static bool HasTypeConstraintClauses(this ApiMemberModel m) 39 | => !String.IsNullOrWhiteSpace(m.TypeConstraints); 40 | 41 | public static SyntaxToken GetIdentifier(this EventFieldDeclarationSyntax evt) 42 | => evt.Declaration.Variables[0].Identifier; 43 | 44 | public static string Indent(this string s) 45 | => String.Join(Environment.NewLine, 46 | s.Split(new[] { Environment.NewLine }, StringSplitOptions.None).Select(str => $"\t{str}")); 47 | 48 | public static T Dump(this T obj, string heading = null) 49 | { 50 | if (heading != null) 51 | Console.WriteLine(heading); 52 | 53 | Console.WriteLine(obj is string ? $"{obj}" : JsonConvert.SerializeObject(obj, Formatting.Indented)); 54 | 55 | return obj; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Helpers/KnownEnvironmentVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace EssentialInterfaces.Helpers 6 | { 7 | public class KnownEnvironmentVariable 8 | { 9 | public const string FORCE_DEPENDENCY_VERSION = "FORCE_DEPENDENCY_VERSION"; 10 | public const string FORCE_NUPKG_VERSION = "FORCE_NUPKG_VERSION"; 11 | public const string ADDITIONAL_RELEASENOTES = "ADDITIONAL_RELEASENOTES"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Models/ApiMemberModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System; 4 | using System.Linq; 5 | 6 | namespace EssentialInterfaces.Models 7 | { 8 | public class ApiMemberModel 9 | { 10 | [JsonConverter(typeof(StringEnumConverter))] 11 | public MemberKind Kind { get; set; } 12 | public string ReturnType { get; set; } 13 | public string Identifier { get; set; } 14 | public string TypeParameters { get; set; } 15 | public string TypeConstraints { get; set; } 16 | public string ArgsString { get; set; } 17 | internal string ArgsArgs => // hehe xd pls dont @ me 18 | String.Join(", ", 19 | ArgsString 20 | .Split(',') 21 | .Select(a => a.Replace("(", "").Replace(")", "").Replace("params", "").Trim()) 22 | .Select(a => a == "" ? "" : a.Split(' ')[1])); 23 | } 24 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Models/ApiModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EssentialInterfaces.Models 4 | { 5 | public class ApiModel 6 | { 7 | public string Namespace { get; set; } 8 | public string Api { get; set; } 9 | public string Interface => $"I{Api}"; 10 | public List Declarations { get; set; } = new List(); 11 | public List OtherTypes { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Models/GeneratorContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using EssentialInterfaces.Tasks; 5 | using LibGit2Sharp; 6 | 7 | namespace EssentialInterfaces.Models 8 | { 9 | public class GeneratorContext 10 | { 11 | // inputs 12 | public string XamarinEssentialsRepoPath { get; } 13 | public string XamarinEssentialsCommitSha { get; set; } 14 | public string XamarinEssentialsPackageVersion { get; set; } 15 | public string EssentialInterfacesProjectPath { get; } 16 | 17 | public string XamarinEssentialsImplementationsPath 18 | => Path.Combine(XamarinEssentialsRepoPath, "Xamarin.Essentials"); 19 | 20 | public GeneratorContext(string essentialsRoot, string outputProjectRoot) 21 | { 22 | XamarinEssentialsRepoPath = essentialsRoot; 23 | EssentialInterfacesProjectPath = outputProjectRoot; 24 | 25 | XamarinEssentialsCommitSha = GetEssentialsCommitSha(); 26 | XamarinEssentialsPackageVersion = GetEssentialsPackageVersion(); 27 | 28 | Console.WriteLine( 29 | $"Using Essentials repo at {XamarinEssentialsRepoPath} (SHA {XamarinEssentialsCommitSha})" + 30 | Environment.NewLine + 31 | $"Current version of Xamarin.Essentials nuget is {XamarinEssentialsPackageVersion}" 32 | + Environment.NewLine + 33 | $"Writing to Essential.Interfaces placeholder at {EssentialInterfacesProjectPath}"); 34 | } 35 | 36 | private string GetEssentialsCommitSha() 37 | { 38 | using (var repo = new Repository(XamarinEssentialsRepoPath)) 39 | return repo.Commits.First().Sha; 40 | } 41 | 42 | private string GetEssentialsPackageVersion() 43 | { 44 | var pmp = new NugetPackageMetadataProvider(); 45 | var package = pmp.GetLatestVersionForPackage("Xamarin.Essentials"); 46 | 47 | return $"{package.Version}"; 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Models/ImplementationGenerationMode.cs: -------------------------------------------------------------------------------- 1 | namespace EssentialInterfaces.Models 2 | { 3 | public enum ImplementationGenerationMode 4 | { 5 | Combined, 6 | ImplementationPerInterface 7 | } 8 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Models/MemberKind.cs: -------------------------------------------------------------------------------- 1 | namespace EssentialInterfaces.Models 2 | { 3 | public enum MemberKind 4 | { 5 | Method, 6 | Property, 7 | PropertyGetOnly, 8 | PropertySetOnly, 9 | Event, 10 | } 11 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using EssentialInterfaces.Models; 6 | using EssentialInterfaces.Tasks; 7 | 8 | namespace EssentialInterfaces 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | var context = GetContext(args); 15 | 16 | var apiModels = new RoslynModelGenerator().Generate(context); 17 | var generatedCode = new ImplementationGenerator().Generate(context, apiModels); 18 | var success = new ProjectMutator().Mutate(context, generatedCode); 19 | 20 | Console.WriteLine( 21 | $"Generated interfaces for {apiModels.Count} types:{Environment.NewLine}" + 22 | String.Join(Environment.NewLine, apiModels.Select(x => $" - {x.Api} ({x.Declarations.Count} members)"))); 23 | 24 | if (Debugger.IsAttached) 25 | Console.ReadLine(); 26 | } 27 | 28 | private static GeneratorContext GetContext(string [] args) 29 | { 30 | if ((args?.Length ?? 0) < 2) 31 | throw new Exception("Provide path to Xamarin.Essentials root and the Essential.Interfaces root to run."); 32 | 33 | var (essentialsRoot, outputProjectRoot) = (args[0], args[1]); 34 | 35 | if (!Directory.Exists(essentialsRoot)) 36 | throw new Exception($"Didn't find Xamarin.Essentials implementations at ${essentialsRoot}."); 37 | 38 | if (!Directory.Exists(outputProjectRoot)) 39 | throw new Exception($"Didn't find Essential.Interfaces project at {outputProjectRoot}."); 40 | 41 | return new GeneratorContext(essentialsRoot, outputProjectRoot); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Tasks/ImplementationGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using EssentialInterfaces.Helpers; 5 | using EssentialInterfaces.Models; 6 | 7 | namespace EssentialInterfaces.Tasks 8 | { 9 | public class ImplementationGenerator 10 | { 11 | private ImplementationGenerationMode GenerationMode = ImplementationGenerationMode.ImplementationPerInterface; 12 | 13 | private const string InterfacesNamespace = "Xamarin.Essentials.Interfaces"; 14 | private const string ImplementationNamespace = "Xamarin.Essentials.Implementation"; 15 | private const string ImplementationClass = "EssentialsImplementation"; 16 | private const string BaseImplementationInterface = "IEssentialsImplementation"; 17 | 18 | private readonly List _usings 19 | = new[] { "System", "System.Collections.Generic", "System.IO", "System.Threading", "System.Threading.Tasks", "Essential.Interfaces", InterfacesNamespace }.ToList(); 20 | 21 | public string Generate(GeneratorContext context, List models) 22 | { 23 | Console.WriteLine($"Using implementation generation mode '{GenerationMode}'"); 24 | 25 | var interfaces = GetInterfacesCode(models); 26 | var implementation = 27 | GenerationMode == ImplementationGenerationMode.Combined 28 | ? GetCombinedImplementationCode(models) 29 | : GetMultiImplementationCode(models); 30 | 31 | var output = 32 | $"{String.Join(Environment.NewLine, _usings.Select(u => $"using {u};"))}{Environment.NewLine}{Environment.NewLine}" + 33 | $"namespace {InterfacesNamespace}{{{Environment.NewLine}{interfaces.Indent()}{Environment.NewLine}}}{Environment.NewLine}{Environment.NewLine}" + 34 | $"namespace {ImplementationNamespace}{{{Environment.NewLine}{implementation.Indent()}{Environment.NewLine}}}"; 35 | 36 | return output; 37 | } 38 | 39 | public string GetInterfacesCode(List models) 40 | => String.Join(Environment.NewLine, 41 | models.Select(m => 42 | $"public interface {m.Interface} {{ {Environment.NewLine}" + 43 | String.Join(Environment.NewLine, m.Declarations.Select(GetInterfacePrototype)).Indent() + 44 | Environment.NewLine + 45 | $"}}" 46 | )); 47 | 48 | public string GetMultiImplementationCode(List models) 49 | => String.Join(Environment.NewLine, models.Select(GetSingleApiImplementationCode)); 50 | 51 | public string GetCombinedImplementationCode(List models) 52 | => $"public class {ImplementationClass} : {BaseImplementationInterface}, {String.Join(", ", models.Select(i => i.Interface))} {{ {Environment.NewLine}{Environment.NewLine}" + 53 | $"[Preserve(Conditional=true)]{Environment.NewLine}public {ImplementationClass}() {{}}{Environment.NewLine}{Environment.NewLine}".Indent() + 54 | String.Join($"{Environment.NewLine}{Environment.NewLine}", models.SelectMany(x => x.Declarations, GetForwardedImplementation)) + Environment.NewLine + 55 | $"}}"; 56 | 57 | public string GetSingleApiImplementationCode(ApiModel m) 58 | { 59 | return $"public class {m.Api}Implementation : {BaseImplementationInterface}, {m.Interface} {{ {Environment.NewLine}{Environment.NewLine}" + 60 | $"[Preserve(Conditional=true)]{Environment.NewLine}public {m.Api}Implementation() {{}}{Environment.NewLine}{Environment.NewLine}".Indent() + 61 | String.Join($"{Environment.NewLine}{Environment.NewLine}", m.Declarations.Select(d => GetForwardedImplementation(m, d))) + Environment.NewLine + 62 | $"}}"; 63 | } 64 | 65 | public string GetInterfacePrototype(ApiMemberModel model) 66 | { 67 | switch (model.Kind) 68 | { 69 | case MemberKind.Method when model.HasTypeConstraintClauses(): 70 | return $"{model.ReturnType} {model.Identifier}{model.TypeParameters}{model.ArgsString} {model.TypeConstraints};"; 71 | 72 | case MemberKind.Method: 73 | return $"{model.ReturnType} {model.Identifier}{model.TypeParameters}{model.ArgsString};"; 74 | 75 | case MemberKind.Event: 76 | return $"event {model.ReturnType} {model.Identifier};"; 77 | 78 | case MemberKind.Property: 79 | return $"{model.ReturnType} {model.Identifier} {{ get; set; }}"; 80 | 81 | case MemberKind.PropertyGetOnly: 82 | return $"{model.ReturnType} {model.Identifier} {{ get; }}"; 83 | 84 | default: 85 | throw new NotImplementedException($"Don't know how to generate prototype for {model.Kind}"); 86 | } 87 | } 88 | 89 | private string GetForwardedImplementation(ApiModel m, ApiMemberModel d) 90 | { 91 | switch (d.Kind) 92 | { 93 | case MemberKind.Method: 94 | return $"{d.ReturnType} {m.Interface}.{d.Identifier}{d.TypeParameters}{d.ArgsString}{Environment.NewLine}" + 95 | $"\t => {m.Namespace}.{m.Api}.{d.Identifier}{d.TypeParameters}({d.ArgsArgs});"; 96 | 97 | case MemberKind.Event: 98 | return $"event {d.ReturnType} {m.Interface}.{d.Identifier}{Environment.NewLine}{{{Environment.NewLine}" + 99 | $"\t add => {m.Namespace}.{m.Api}.{d.Identifier} += value; {Environment.NewLine}" + 100 | $"\t remove => {m.Namespace}.{m.Api}.{d.Identifier} -= value; {Environment.NewLine} }}"; 101 | 102 | case MemberKind.Property: 103 | return $"{d.ReturnType} {m.Interface}.{d.Identifier}{Environment.NewLine}{{{Environment.NewLine}" + 104 | $"\t get {{ return {m.Namespace}.{m.Api}.{d.Identifier}; }}{Environment.NewLine}" + 105 | $"\t set {{ {m.Namespace}.{m.Api}.{d.Identifier} = value; }}{Environment.NewLine}}}"; 106 | 107 | case MemberKind.PropertyGetOnly: 108 | return $"{d.ReturnType} {m.Interface}.{d.Identifier}{d.ArgsString}{Environment.NewLine}" + 109 | $"\t => {m.Namespace}.{m.Api}.{d.Identifier};"; 110 | 111 | default: 112 | throw new NotImplementedException($"Don't know how to generate forwarding implementation for {d.Kind}"); 113 | } 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Tasks/NugetPackageMetadataProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using EssentialInterfaces.Helpers; 6 | using NuGet.Configuration; 7 | using NuGet.Protocol; 8 | using NuGet.Protocol.Core.Types; 9 | 10 | namespace EssentialInterfaces.Tasks 11 | { 12 | public class NugetPackageMetadataProvider 13 | { 14 | // t h a n k you daveaglick 15 | public PackageSearchMetadata GetLatestVersionForPackage(string package) 16 | { 17 | var logger = new NugetLogger(); 18 | 19 | var providers = new List>(); 20 | providers.AddRange(Repository.Provider.GetCoreV3()); 21 | 22 | var packageSource = new PackageSource("https://api.nuget.org/v3/index.json"); 23 | var sourceRepository = new SourceRepository(packageSource, providers); 24 | var packageMetadataResource = sourceRepository.GetResourceAsync().Result; 25 | 26 | var searchMetadata = 27 | packageMetadataResource.GetMetadataAsync(package, true, true, logger, CancellationToken.None).Result; 28 | 29 | return 30 | searchMetadata 31 | .OfType() 32 | .OrderByDescending(x => x.Published) 33 | .First(); 34 | } 35 | 36 | class NugetLogger : NuGet.Common.ILogger 37 | { 38 | public void LogDebug(string data) => $"DEBUG: {data}".Dump(); 39 | public void LogVerbose(string data) => $"VERBOSE: {data}".Dump(); 40 | public void LogInformation(string data) => $"INFORMATION: {data}".Dump(); 41 | public void LogMinimal(string data) => $"MINIMAL: {data}".Dump(); 42 | public void LogWarning(string data) => $"WARNING: {data}".Dump(); 43 | public void LogError(string data) => $"ERROR: {data}".Dump(); 44 | public void LogInformationSummary(string data) => $"SUMMARY: {data}".Dump(); 45 | public void LogErrorSummary(string data) => $"ERROR SUMMARY: {data}".Dump(); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Tasks/ProjectMutator.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System; 3 | using System.IO; 4 | using System.Xml.Linq; 5 | using System.Xml.XPath; 6 | using EssentialInterfaces.Helpers; 7 | using EssentialInterfaces.Models; 8 | 9 | namespace EssentialInterfaces.Tasks 10 | { 11 | public class ProjectMutator 12 | { 13 | public bool Mutate(GeneratorContext context, string generatedCode) 14 | { 15 | WriteEssentialsFile(context.EssentialInterfacesProjectPath, generatedCode); 16 | WriteCsproj(context.EssentialInterfacesProjectPath, context.XamarinEssentialsPackageVersion, context.XamarinEssentialsCommitSha); 17 | 18 | return true; 19 | } 20 | 21 | private void WriteEssentialsFile(string interfacesProjPath, string output) 22 | { 23 | var essentialsFilePath = Path.Combine(interfacesProjPath, "Essentials.cs"); 24 | File.WriteAllText(essentialsFilePath, output); 25 | } 26 | 27 | private void WriteCsproj(string interfacesProjPath, string essentialsPackageVersion, string commitSha) 28 | { 29 | var csprojPath = Path.Combine(interfacesProjPath, "Essential.Interfaces.csproj"); 30 | var xDoc = XDocument.Load(csprojPath); 31 | 32 | var dependencyVersion = GetDependencyVersion(essentialsPackageVersion); 33 | var nupkgVersion = GetNupkgVersion(essentialsPackageVersion); 34 | var releaseNotes = GetReleaseNotes(commitSha); 35 | 36 | SetEssentialsDependencyVersion(xDoc, dependencyVersion); 37 | SetPropertyGroupValue(xDoc, "Version", nupkgVersion); 38 | SetPropertyGroupValue(xDoc, "PackageReleaseNotes", releaseNotes); 39 | 40 | xDoc.Save(csprojPath); 41 | } 42 | 43 | private string GetDependencyVersion(string essentialsPackageVersion) => 44 | !String.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(KnownEnvironmentVariable.FORCE_DEPENDENCY_VERSION)) 45 | ? Environment.GetEnvironmentVariable(KnownEnvironmentVariable.FORCE_DEPENDENCY_VERSION) 46 | : essentialsPackageVersion; 47 | 48 | private string GetNupkgVersion(string essentialsPackageVersion) => 49 | !String.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(KnownEnvironmentVariable.FORCE_NUPKG_VERSION)) 50 | ? Environment.GetEnvironmentVariable(KnownEnvironmentVariable.FORCE_NUPKG_VERSION) 51 | : essentialsPackageVersion; 52 | 53 | private string GetReleaseNotes(string commitSha) 54 | { 55 | var additionalReleaseNotes = Environment.GetEnvironmentVariable(KnownEnvironmentVariable.ADDITIONAL_RELEASENOTES); 56 | var releaseNotes = $"Generated from Xamarin.Essentials commit {commitSha}"; 57 | 58 | if (!String.IsNullOrWhiteSpace(additionalReleaseNotes)) 59 | releaseNotes += Environment.NewLine + Environment.NewLine + additionalReleaseNotes; 60 | 61 | return releaseNotes; 62 | } 63 | 64 | private void SetEssentialsDependencyVersion(XDocument doc, string version) 65 | { 66 | // only good while there's a single packageref 67 | var element = doc.XPathSelectElement($"/Project[@Sdk=\"Microsoft.NET.Sdk\"]/ItemGroup/PackageReference"); 68 | element.SetAttributeValue("Version", version); 69 | } 70 | 71 | private void SetPropertyGroupValue(XDocument doc, string name, string value) 72 | { 73 | var element = doc.XPathSelectElement($"/Project[@Sdk=\"Microsoft.NET.Sdk\"]/PropertyGroup/{name}"); 74 | element.Value = value; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/Tasks/RoslynModelGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using EssentialInterfaces.Helpers; 7 | using EssentialInterfaces.Models; 8 | using Microsoft.CodeAnalysis; 9 | using Microsoft.CodeAnalysis.CSharp; 10 | using Microsoft.CodeAnalysis.CSharp.Syntax; 11 | 12 | namespace EssentialInterfaces.Tasks 13 | { 14 | public class RoslynModelGenerator 15 | { 16 | private readonly List _masks = new[] { ".netstandard.cs", ".shared.cs" }.ToList(); 17 | 18 | public List Generate(GeneratorContext context) 19 | => 20 | Directory 21 | .GetFiles(context.XamarinEssentialsImplementationsPath, "*.cs", SearchOption.AllDirectories) 22 | .Where(f => _masks.Any(f.EndsWith)) 23 | .GroupBy(Path.GetDirectoryName, f => (f, contents: File.ReadAllText(f))) 24 | .Select(a => 25 | { 26 | var api = Path.GetFileName(a.Key); 27 | var tree = CSharpSyntaxTree.ParseText(String.Join(Environment.NewLine, a.Select(f => f.contents))); 28 | var ns = $"{tree.GetDeclarations().FirstOrDefault()?.Name.ToString()}"; 29 | 30 | var apiModel = new ApiModel 31 | { 32 | Namespace = ns, 33 | Api = api, 34 | Declarations = 35 | tree.GetDeclarations() 36 | .Where(x => x.Identifier.Text == api) 37 | .SelectMany(GetQualifyingDeclarations) 38 | .Select(GetModelForDeclaration) 39 | .Where(m => m != null) 40 | .ToList(), 41 | OtherTypes = 42 | tree.GetDeclarations(true) 43 | .Where(x => x.Identifier.Text != api) 44 | .Select(x => $"{x.Identifier.Text}") 45 | .ToList() 46 | }; 47 | 48 | foreach (var declarationWithConstraint in apiModel.Declarations.Where(x => x.HasTypeConstraintClauses())) 49 | QualifyNestedTypeConstraintIfNecessary(declarationWithConstraint, apiModel); 50 | 51 | return apiModel; 52 | }) 53 | .Where(a => a.Declarations.Any() || $"Ignoring {a.Api} which has no qualifying implementations".Dump() == null) 54 | .ToList() 55 | .Dump("Generated Models:"); 56 | 57 | public IEnumerable GetQualifyingDeclarations(ClassDeclarationSyntax cls) 58 | { 59 | // we care about public static methods, properties and events 60 | var methods = 61 | cls.GetDeclarations() 62 | .Where(m => m.Modifiers.Contains(SyntaxKind.PublicKeyword) 63 | && m.Modifiers.Contains(SyntaxKind.StaticKeyword)) 64 | .Select(m => m.WithModifiers(new SyntaxTokenList())); 65 | 66 | var properties = 67 | cls.GetDeclarations() 68 | .Where(m => m.Modifiers.Contains(SyntaxKind.PublicKeyword) 69 | && m.Modifiers.Contains(SyntaxKind.StaticKeyword)); 70 | 71 | var events = 72 | Enumerable.Concat 73 | ( 74 | cls.GetDeclarations().Where(m => m.Modifiers.Contains(SyntaxKind.StaticKeyword)), 75 | cls.GetDeclarations() 76 | ); 77 | 78 | return Enumerable.Concat(methods, properties).Concat(events); 79 | } 80 | 81 | public ApiMemberModel GetModelForDeclaration(T syntaxNode) 82 | where T : SyntaxNode 83 | { 84 | switch (syntaxNode) 85 | { 86 | case MethodDeclarationSyntax m when m.TypeParameterList?.Parameters.Any() ?? false: 87 | return new ApiMemberModel 88 | { 89 | Kind = MemberKind.Method, 90 | Identifier = $"{m.Identifier}", 91 | TypeParameters = $"{m.TypeParameterList}", 92 | TypeConstraints = $"{m.ConstraintClauses}", 93 | ReturnType = $"{m.ReturnType}", 94 | ArgsString = $"{m.ParameterList.ToFullString().Trim()}" 95 | }; 96 | 97 | case MethodDeclarationSyntax m: 98 | return new ApiMemberModel 99 | { 100 | Kind = MemberKind.Method, 101 | Identifier = $"{m.Identifier}", 102 | TypeParameters = $"{m.TypeParameterList}", 103 | ReturnType = $"{m.ReturnType}", 104 | ArgsString = $"{m.ParameterList.ToFullString().Trim()}" 105 | }; 106 | 107 | case EventDeclarationSyntax evt: 108 | return new ApiMemberModel 109 | { 110 | Kind = MemberKind.Event, 111 | Identifier = $"{evt.Identifier}", 112 | ReturnType = $"{evt.Type}" 113 | }; 114 | 115 | case EventFieldDeclarationSyntax evt 116 | when !$"{evt.GetIdentifier()}".EndsWith("Internal"): 117 | return new ApiMemberModel 118 | { 119 | Kind = MemberKind.Event, 120 | Identifier = $"{evt.GetIdentifier()}", 121 | ReturnType = $"{evt.Declaration.Type}" 122 | }; 123 | 124 | // we don't want to exposed internal event handlers 125 | case EventFieldDeclarationSyntax evt 126 | when $"{evt.GetIdentifier()}".EndsWith("Internal"): 127 | return null; 128 | 129 | case PropertyDeclarationSyntax p 130 | when p.AccessorList?.Accessors.Any(x => x.IsKind(SyntaxKind.SetAccessorDeclaration) && !x.Modifiers.Any(m => m.IsKind(SyntaxKind.PrivateKeyword))) ?? false: 131 | return new ApiMemberModel 132 | { 133 | Kind = MemberKind.Property, 134 | ReturnType = $"{p.Type}", 135 | Identifier = $"{p.Identifier}" 136 | }; 137 | 138 | case PropertyDeclarationSyntax p: 139 | return new ApiMemberModel 140 | { 141 | Kind = MemberKind.PropertyGetOnly, 142 | ReturnType = $"{p.Type}", 143 | Identifier = $"{p.Identifier}" 144 | }; 145 | 146 | default: 147 | throw new NotImplementedException($"Don't know how to generate model from {syntaxNode.GetType()}"); 148 | } 149 | } 150 | 151 | // some type constraints against member methods (so far, just permissions ones) refer to types nested within the api 152 | // this is difficult to detect using a non-semantic model, so compare all nested types with the type constraint to 153 | // detect any matches. 154 | // since this could result in unexpected things in the future, let's throw for anything we don't expect 155 | private readonly string[] _expectedNestedTypeConstraintApis = { "Permissions" }; 156 | private readonly string[] _ignoreNestedTypeConstraintApis = { }; 157 | private void QualifyNestedTypeConstraintIfNecessary(ApiMemberModel declarationWithConstraint, ApiModel api) 158 | { 159 | var matchingInternalType = 160 | api.OtherTypes 161 | .FirstOrDefault(x => declarationWithConstraint.TypeConstraints.Contains(x)); 162 | 163 | if (matchingInternalType is null || _ignoreNestedTypeConstraintApis.Contains(api.Api)) 164 | return; 165 | 166 | if (!_expectedNestedTypeConstraintApis.Contains(api.Api)) 167 | throw new Exception( 168 | $"Found a potentially nested type in member '{declarationWithConstraint.Identifier}', " + 169 | $"but the containing api '{api.Api}' was not listed in {nameof(_expectedNestedTypeConstraintApis)} or {nameof(_ignoreNestedTypeConstraintApis)}"); 170 | 171 | $"Replacing '{matchingInternalType}' found in type constraint for member '{api.Api}.{declarationWithConstraint.Identifier}' with fully qualified nested name." 172 | .Dump(); 173 | 174 | declarationWithConstraint.TypeConstraints = 175 | declarationWithConstraint.TypeConstraints.Replace(matchingInternalType, 176 | $"{api.Namespace}.{api.Api}.{matchingInternalType}"); 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /src/essential-interfaces-generator/essential-interfaces-generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | latest 7 | EssentialInterfaces 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/essential-interfaces.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27825.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "essential-interfaces-generator", "essential-interfaces-generator\essential-interfaces-generator.csproj", "{054F6455-687D-4059-B025-5A41C2FA88C6}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "output", "output", "{1E421FB5-3798-4DE0-9B24-C445ED9E6EAA}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Essential.Interfaces", "output\Essential.Interfaces\Essential.Interfaces.csproj", "{2BD08A33-EDFE-4C27-9835-CD477C3F54B4}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {054F6455-687D-4059-B025-5A41C2FA88C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {054F6455-687D-4059-B025-5A41C2FA88C6}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {054F6455-687D-4059-B025-5A41C2FA88C6}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {054F6455-687D-4059-B025-5A41C2FA88C6}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {2BD08A33-EDFE-4C27-9835-CD477C3F54B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {2BD08A33-EDFE-4C27-9835-CD477C3F54B4}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {2BD08A33-EDFE-4C27-9835-CD477C3F54B4}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {2BD08A33-EDFE-4C27-9835-CD477C3F54B4}.Release|Any CPU.Build.0 = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | {2BD08A33-EDFE-4C27-9835-CD477C3F54B4} = {1E421FB5-3798-4DE0-9B24-C445ED9E6EAA} 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {666C5F37-CC00-4D26-83DE-F879EE2BB891} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/Essential.Interfaces.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net6.0;net6.0-ios;net6.0-android 5 | true 6 | Ryan Davis 7 | 8 | Unofficial automatically-generated interfaces for the cross platform APIs exposed by Xamarin.Essentials. Suitable for mocking and for applications using dependency injection. 9 | latest 10 | 0.0.0 11 | 12 | Xamarin.Essentials.Interfaces 13 | Xamarin.Essentials.Interfaces 14 | https://raw.githubusercontent.com/rdavisau/essential-interfaces/master/LICENSE 15 | https://github.com/rdavisau/essential-interfaces 16 | 2022 Ryan Davis 17 | https://github.com/rdavisau/essential-interfaces 18 | xamarin, Xamarin.Essentials, interfaces, maui, Maui.Essentials 19 | 20 | 21 | 22 | true 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | All 34 | 35 | 36 | All 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/Essential.Interfaces.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | CSharp71 -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/Essentials.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rdavisau/essential-interfaces/f1f6c46ba11d80d88f059dd7c16fe7dee48ef366/src/output/Essential.Interfaces/Essentials.cs -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/IEssentialsImplementation.cs: -------------------------------------------------------------------------------- 1 | namespace Xamarin.Essentials.Interfaces 2 | { 3 | public interface IEssentialsImplementation { } 4 | } 5 | 6 | -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/LinkerSafe.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using Essential.Interfaces; 4 | 5 | [assembly: LinkerSafe] 6 | namespace Essential.Interfaces 7 | { 8 | class LinkerSafeAttribute : System.Attribute { } 9 | 10 | [AttributeUsage(AttributeTargets.All)] 11 | internal sealed class PreserveAttribute : Attribute 12 | { 13 | public bool AllMembers; 14 | public bool Conditional; 15 | 16 | public PreserveAttribute(bool allMembers, bool conditional) 17 | { 18 | AllMembers = allMembers; 19 | Conditional = conditional; 20 | } 21 | 22 | public PreserveAttribute() 23 | { 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/output/Essential.Interfaces/Maui/MauiEssentials.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Essential.Interfaces; 7 | using Microsoft.Maui.Accessibility; 8 | using Microsoft.Maui.ApplicationModel; 9 | using Microsoft.Maui.ApplicationModel.Communication; 10 | using Microsoft.Maui.ApplicationModel.DataTransfer; 11 | using Microsoft.Maui.Authentication; 12 | using Microsoft.Maui.Devices; 13 | using Microsoft.Maui.Devices.Sensors; 14 | using Microsoft.Maui.Dispatching; 15 | using Microsoft.Maui.Media; 16 | using Microsoft.Maui.Networking; 17 | using Microsoft.Maui.Storage; 18 | using Xamarin.Essentials.Interfaces; 19 | 20 | namespace Xamarin.Essentials.Implementation 21 | { 22 | public class AccelerometerImplementation : Xamarin.Essentials.Interfaces.IAccelerometer, Microsoft.Maui.Devices.Sensors.IAccelerometer, IEssentialsImplementation 23 | { 24 | [Preserve(Conditional = true)] 25 | public AccelerometerImplementation() 26 | { 27 | } 28 | 29 | private Microsoft.Maui.Devices.Sensors.IAccelerometer _accelerometerImplementation 30 | => Accelerometer.Default; 31 | 32 | public void Start(SensorSpeed sensorSpeed) => 33 | _accelerometerImplementation.Start(sensorSpeed); 34 | 35 | public void Stop() => 36 | _accelerometerImplementation.Stop(); 37 | 38 | public bool IsSupported => _accelerometerImplementation.IsSupported; 39 | 40 | public bool IsMonitoring => _accelerometerImplementation.IsMonitoring; 41 | 42 | public event EventHandler ReadingChanged 43 | { 44 | add => _accelerometerImplementation.ReadingChanged += value; 45 | remove => _accelerometerImplementation.ReadingChanged -= value; 46 | } 47 | 48 | public event EventHandler ShakeDetected 49 | { 50 | add => _accelerometerImplementation.ShakeDetected += value; 51 | remove => _accelerometerImplementation.ShakeDetected -= value; 52 | } 53 | } 54 | 55 | public class AppActionsImplementation : Xamarin.Essentials.Interfaces.IAppActions, Microsoft.Maui.ApplicationModel.IAppActions, IEssentialsImplementation 56 | { 57 | [Preserve(Conditional = true)] 58 | public AppActionsImplementation() 59 | { 60 | } 61 | 62 | private Microsoft.Maui.ApplicationModel.IAppActions _appActionsImplementation 63 | => AppActions.Current; 64 | 65 | public Task> GetAsync() => 66 | _appActionsImplementation.GetAsync(); 67 | 68 | public Task SetAsync(params AppAction[] actions) => 69 | _appActionsImplementation.SetAsync(actions); 70 | 71 | public Task SetAsync(IEnumerable actions) => 72 | _appActionsImplementation.SetAsync(actions); 73 | 74 | public bool IsSupported => _appActionsImplementation.IsSupported; 75 | 76 | public event EventHandler AppActionActivated 77 | { 78 | add => _appActionsImplementation.AppActionActivated += value; 79 | remove => _appActionsImplementation.AppActionActivated -= value; 80 | } 81 | 82 | public event EventHandler OnAppAction 83 | { 84 | add => _appActionsImplementation.AppActionActivated += value; 85 | remove => _appActionsImplementation.AppActionActivated -= value; 86 | } 87 | } 88 | 89 | public class AppInfoImplementation : Xamarin.Essentials.Interfaces.IAppInfo, Microsoft.Maui.ApplicationModel.IAppInfo, IEssentialsImplementation 90 | { 91 | [Preserve(Conditional = true)] 92 | public AppInfoImplementation() 93 | { 94 | } 95 | 96 | private Microsoft.Maui.ApplicationModel.IAppInfo _appInfoImplementation 97 | => AppInfo.Current; 98 | 99 | public void ShowSettingsUI() => 100 | _appInfoImplementation.ShowSettingsUI(); 101 | 102 | public string PackageName => _appInfoImplementation.PackageName; 103 | public string Name => _appInfoImplementation.Name; 104 | public string VersionString => _appInfoImplementation.VersionString; 105 | public Version Version => _appInfoImplementation.Version; 106 | public string BuildString => _appInfoImplementation.BuildString; 107 | 108 | AppTheme Microsoft.Maui.ApplicationModel.IAppInfo.RequestedTheme => _appInfoImplementation.RequestedTheme; 109 | public AppPackagingModel PackagingModel => _appInfoImplementation.PackagingModel; 110 | public LayoutDirection RequestedLayoutDirection => _appInfoImplementation.RequestedLayoutDirection; 111 | public AppTheme RequestedTheme => _appInfoImplementation.RequestedTheme; 112 | } 113 | 114 | public class BarometerImplementation : Xamarin.Essentials.Interfaces.IBarometer, Microsoft.Maui.Devices.Sensors.IBarometer, IEssentialsImplementation 115 | { 116 | [Preserve(Conditional = true)] 117 | public BarometerImplementation() 118 | { 119 | } 120 | 121 | private Microsoft.Maui.Devices.Sensors.IBarometer _barometerImplementation 122 | => Barometer.Default; 123 | 124 | public void Start(SensorSpeed sensorSpeed) => 125 | _barometerImplementation.Start(sensorSpeed); 126 | 127 | public void Stop() => 128 | _barometerImplementation.Stop(); 129 | 130 | public bool IsSupported => _barometerImplementation.IsSupported; 131 | public bool IsMonitoring => _barometerImplementation.IsMonitoring; 132 | 133 | public event EventHandler ReadingChanged 134 | { 135 | add => _barometerImplementation.ReadingChanged += value; 136 | remove => _barometerImplementation.ReadingChanged -= value; 137 | } 138 | } 139 | 140 | public class BatteryImplementation : Xamarin.Essentials.Interfaces.IBattery, Microsoft.Maui.Devices.IBattery, IEssentialsImplementation 141 | { 142 | [Preserve(Conditional = true)] 143 | public BatteryImplementation() 144 | { 145 | } 146 | 147 | private Microsoft.Maui.Devices.IBattery _batteryImplementation 148 | => Battery.Default; 149 | 150 | public double ChargeLevel => _batteryImplementation.ChargeLevel; 151 | public BatteryState State => _batteryImplementation.State; 152 | public BatteryPowerSource PowerSource => _batteryImplementation.PowerSource; 153 | public EnergySaverStatus EnergySaverStatus => _batteryImplementation.EnergySaverStatus; 154 | 155 | public event EventHandler BatteryInfoChanged 156 | { 157 | add => _batteryImplementation.BatteryInfoChanged += value; 158 | remove => _batteryImplementation.BatteryInfoChanged -= value; 159 | } 160 | 161 | public event EventHandler EnergySaverStatusChanged 162 | { 163 | add => _batteryImplementation.EnergySaverStatusChanged += value; 164 | remove => _batteryImplementation.EnergySaverStatusChanged -= value; 165 | } 166 | } 167 | 168 | public class BrowserImplementation : Xamarin.Essentials.Interfaces.IBrowser, Microsoft.Maui.ApplicationModel.IBrowser, IEssentialsImplementation 169 | { 170 | [Preserve(Conditional = true)] 171 | public BrowserImplementation() 172 | { 173 | } 174 | 175 | private Microsoft.Maui.ApplicationModel.IBrowser _browserImplementation 176 | => Browser.Default; 177 | 178 | public Task OpenAsync(string uri) => 179 | _browserImplementation.OpenAsync(uri); 180 | 181 | public Task OpenAsync(string uri, BrowserLaunchMode launchMode) => 182 | _browserImplementation.OpenAsync(uri, launchMode); 183 | 184 | public Task OpenAsync(string uri, BrowserLaunchOptions options) => 185 | _browserImplementation.OpenAsync(uri, options); 186 | 187 | public Task OpenAsync(Uri uri) => 188 | _browserImplementation.OpenAsync(uri); 189 | 190 | public Task OpenAsync(Uri uri, BrowserLaunchMode launchMode) => 191 | _browserImplementation.OpenAsync(uri, launchMode); 192 | 193 | public Task OpenAsync(Uri uri, BrowserLaunchOptions options) => 194 | _browserImplementation.OpenAsync(uri, options); 195 | } 196 | 197 | public class ClipboardImplementation : Xamarin.Essentials.Interfaces.IClipboard, Microsoft.Maui.ApplicationModel.DataTransfer.IClipboard, IEssentialsImplementation 198 | { 199 | [Preserve(Conditional = true)] 200 | public ClipboardImplementation() 201 | { 202 | } 203 | 204 | private Microsoft.Maui.ApplicationModel.DataTransfer.IClipboard _clipboardImplementation 205 | => Clipboard.Default; 206 | 207 | public Task SetTextAsync(string text) => 208 | _clipboardImplementation.SetTextAsync(text); 209 | 210 | public Task GetTextAsync() => 211 | _clipboardImplementation.GetTextAsync(); 212 | 213 | public bool HasText => _clipboardImplementation.HasText; 214 | 215 | public event EventHandler ClipboardContentChanged 216 | { 217 | add => _clipboardImplementation.ClipboardContentChanged += value; 218 | remove => _clipboardImplementation.ClipboardContentChanged -= value; 219 | } 220 | } 221 | 222 | public class CompassImplementation : Xamarin.Essentials.Interfaces.ICompass, Microsoft.Maui.Devices.Sensors.ICompass, IEssentialsImplementation 223 | { 224 | [Preserve(Conditional = true)] 225 | public CompassImplementation() 226 | { 227 | } 228 | 229 | private Microsoft.Maui.Devices.Sensors.ICompass _compassImplementation 230 | => Compass.Default; 231 | 232 | public void Start(SensorSpeed sensorSpeed) => 233 | _compassImplementation.Start(sensorSpeed); 234 | 235 | public void Start(SensorSpeed sensorSpeed, bool applyLowPassFilter) => 236 | _compassImplementation.Start(sensorSpeed, applyLowPassFilter); 237 | 238 | public void Stop() => 239 | _compassImplementation.Stop(); 240 | 241 | public bool IsSupported => _compassImplementation.IsSupported; 242 | public bool IsMonitoring => _compassImplementation.IsMonitoring; 243 | 244 | public event EventHandler ReadingChanged 245 | { 246 | add => _compassImplementation.ReadingChanged += value; 247 | remove => _compassImplementation.ReadingChanged -= value; 248 | } 249 | } 250 | 251 | public class ConnectivityImplementation : Xamarin.Essentials.Interfaces.IConnectivity, Microsoft.Maui.Networking.IConnectivity, IEssentialsImplementation 252 | { 253 | [Preserve(Conditional = true)] 254 | public ConnectivityImplementation() 255 | { 256 | } 257 | 258 | private Microsoft.Maui.Networking.IConnectivity _connectivityImplementation 259 | => Connectivity.Current; 260 | 261 | public IEnumerable ConnectionProfiles => _connectivityImplementation.ConnectionProfiles; 262 | public NetworkAccess NetworkAccess => _connectivityImplementation.NetworkAccess; 263 | 264 | public event EventHandler ConnectivityChanged 265 | { 266 | add => _connectivityImplementation.ConnectivityChanged += value; 267 | remove => _connectivityImplementation.ConnectivityChanged -= value; 268 | } 269 | } 270 | 271 | public class ContactsImplementation : Xamarin.Essentials.Interfaces.IContacts, Microsoft.Maui.ApplicationModel.Communication.IContacts, IEssentialsImplementation 272 | { 273 | [Preserve(Conditional = true)] 274 | public ContactsImplementation() 275 | { 276 | } 277 | 278 | private Microsoft.Maui.ApplicationModel.Communication.IContacts _contactsImplementation 279 | => Microsoft.Maui.ApplicationModel.Communication.Contacts.Default; 280 | 281 | public Task PickContactAsync() => 282 | _contactsImplementation.PickContactAsync(); 283 | 284 | public Task> GetAllAsync(CancellationToken cancellationToken = new CancellationToken()) => 285 | _contactsImplementation.GetAllAsync(cancellationToken); 286 | } 287 | 288 | public class DeviceDisplayImplementation : Xamarin.Essentials.Interfaces.IDeviceDisplay, Microsoft.Maui.Devices.IDeviceDisplay, IEssentialsImplementation 289 | { 290 | [Preserve(Conditional = true)] 291 | public DeviceDisplayImplementation() 292 | { 293 | } 294 | 295 | private Microsoft.Maui.Devices.IDeviceDisplay _deviceDisplayImplementation 296 | => DeviceDisplay.Current; 297 | 298 | public bool KeepScreenOn 299 | { 300 | get => _deviceDisplayImplementation.KeepScreenOn; 301 | set => _deviceDisplayImplementation.KeepScreenOn = value; 302 | } 303 | 304 | public DisplayInfo MainDisplayInfo => _deviceDisplayImplementation.MainDisplayInfo; 305 | 306 | public event EventHandler MainDisplayInfoChanged 307 | { 308 | add => _deviceDisplayImplementation.MainDisplayInfoChanged += value; 309 | remove => _deviceDisplayImplementation.MainDisplayInfoChanged -= value; 310 | } 311 | } 312 | 313 | public class DeviceInfoImplementation : Xamarin.Essentials.Interfaces.IDeviceInfo, Microsoft.Maui.Devices.IDeviceInfo, IEssentialsImplementation 314 | { 315 | [Preserve(Conditional = true)] 316 | public DeviceInfoImplementation() 317 | { 318 | } 319 | 320 | private Microsoft.Maui.Devices.IDeviceInfo _deviceInfoImplementation 321 | => DeviceInfo.Current; 322 | 323 | public string Model => _deviceInfoImplementation.Model; 324 | public string Manufacturer => _deviceInfoImplementation.Manufacturer; 325 | public string Name => _deviceInfoImplementation.Name; 326 | public string VersionString => _deviceInfoImplementation.VersionString; 327 | public Version Version => _deviceInfoImplementation.Version; 328 | public DevicePlatform Platform => _deviceInfoImplementation.Platform; 329 | public DeviceIdiom Idiom => _deviceInfoImplementation.Idiom; 330 | public DeviceType DeviceType => _deviceInfoImplementation.DeviceType; 331 | } 332 | 333 | public class EmailImplementation : Xamarin.Essentials.Interfaces.IEmail, Microsoft.Maui.ApplicationModel.Communication.IEmail, IEssentialsImplementation 334 | { 335 | [Preserve(Conditional = true)] 336 | public EmailImplementation() 337 | { 338 | } 339 | 340 | private Microsoft.Maui.ApplicationModel.Communication.IEmail _emailImplementation 341 | => Email.Default; 342 | 343 | public Task ComposeAsync() => 344 | _emailImplementation.ComposeAsync(); 345 | 346 | public Task ComposeAsync(string subject, string body, params string[] to) => 347 | _emailImplementation.ComposeAsync(subject, body, to); 348 | 349 | public Task ComposeAsync(EmailMessage message) => 350 | _emailImplementation.ComposeAsync(message); 351 | 352 | public bool IsComposeSupported => _emailImplementation.IsComposeSupported; 353 | } 354 | 355 | public class FilePickerImplementation : Xamarin.Essentials.Interfaces.IFilePicker, Microsoft.Maui.Storage.IFilePicker, IEssentialsImplementation 356 | { 357 | [Preserve(Conditional = true)] 358 | public FilePickerImplementation() 359 | { 360 | } 361 | 362 | private Microsoft.Maui.Storage.IFilePicker _filePickerImplementation 363 | => FilePicker.Default; 364 | 365 | public Task PickAsync(PickOptions options = null) 366 | => _filePickerImplementation.PickAsync(options); 367 | 368 | public Task> PickMultipleAsync(PickOptions options = null) 369 | => _filePickerImplementation.PickMultipleAsync(options); 370 | } 371 | 372 | public class FileSystemImplementation : Xamarin.Essentials.Interfaces.IFileSystem, Microsoft.Maui.Storage.IFileSystem, IEssentialsImplementation 373 | { 374 | [Preserve(Conditional = true)] 375 | public FileSystemImplementation() 376 | { 377 | } 378 | 379 | private Microsoft.Maui.Storage.IFileSystem _fileSystemImplementation 380 | => FileSystem.Current; 381 | 382 | public Task OpenAppPackageFileAsync(string filename) => 383 | _fileSystemImplementation.OpenAppPackageFileAsync(filename); 384 | 385 | public Task AppPackageFileExistsAsync(string filename) => 386 | _fileSystemImplementation.AppPackageFileExistsAsync(filename); 387 | 388 | public string CacheDirectory => _fileSystemImplementation.CacheDirectory; 389 | public string AppDataDirectory => _fileSystemImplementation.AppDataDirectory; 390 | } 391 | 392 | public class FlashlightImplementation : Xamarin.Essentials.Interfaces.IFlashlight, Microsoft.Maui.Devices.IFlashlight, IEssentialsImplementation 393 | { 394 | [Preserve(Conditional = true)] 395 | public FlashlightImplementation() 396 | { 397 | } 398 | 399 | private Microsoft.Maui.Devices.IFlashlight _flashlightImplementation 400 | => Flashlight.Default; 401 | 402 | public Task TurnOnAsync() => 403 | _flashlightImplementation.TurnOnAsync(); 404 | 405 | public Task TurnOffAsync() => 406 | _flashlightImplementation.TurnOffAsync(); 407 | } 408 | 409 | public class GeocodingImplementation : Xamarin.Essentials.Interfaces.IGeocoding, Microsoft.Maui.Devices.Sensors.IGeocoding, IEssentialsImplementation 410 | { 411 | [Preserve(Conditional = true)] 412 | public GeocodingImplementation() 413 | { 414 | } 415 | 416 | private Microsoft.Maui.Devices.Sensors.IGeocoding _geocodingImplementation 417 | => Geocoding.Default; 418 | 419 | public Task> GetPlacemarksAsync(Location location) 420 | => _geocodingImplementation.GetPlacemarksAsync(location); 421 | 422 | public Task> GetPlacemarksAsync(double latitude, double longitude) => 423 | _geocodingImplementation.GetPlacemarksAsync(latitude, longitude); 424 | 425 | public Task> GetLocationsAsync(string address) => 426 | _geocodingImplementation.GetLocationsAsync(address); 427 | } 428 | 429 | public class GeolocationImplementation : Xamarin.Essentials.Interfaces.IGeolocation, Microsoft.Maui.Devices.Sensors.IGeolocation, IEssentialsImplementation 430 | { 431 | [Preserve(Conditional = true)] 432 | public GeolocationImplementation() 433 | { 434 | } 435 | 436 | private Microsoft.Maui.Devices.Sensors.IGeolocation _geolocationImplementation 437 | => Geolocation.Default; 438 | 439 | public Task GetLastKnownLocationAsync() => 440 | _geolocationImplementation.GetLastKnownLocationAsync(); 441 | 442 | public Task GetLocationAsync() => 443 | _geolocationImplementation.GetLocationAsync(); 444 | 445 | public Task GetLocationAsync(GeolocationRequest request) 446 | => _geolocationImplementation.GetLocationAsync(request); 447 | 448 | public Task GetLocationAsync(GeolocationRequest request, CancellationToken cancelToken) => 449 | _geolocationImplementation.GetLocationAsync(request, cancelToken); 450 | } 451 | 452 | public class GyroscopeImplementation : Xamarin.Essentials.Interfaces.IGyroscope, Microsoft.Maui.Devices.Sensors.IGyroscope, IEssentialsImplementation 453 | { 454 | [Preserve(Conditional = true)] 455 | public GyroscopeImplementation() 456 | { 457 | } 458 | 459 | private Microsoft.Maui.Devices.Sensors.IGyroscope _gyroscopeImplementation 460 | => Gyroscope.Default; 461 | 462 | public void Start(SensorSpeed sensorSpeed) => 463 | _gyroscopeImplementation.Start(sensorSpeed); 464 | 465 | public void Stop() => 466 | _gyroscopeImplementation.Stop(); 467 | 468 | public bool IsSupported => _gyroscopeImplementation.IsSupported; 469 | public bool IsMonitoring => _gyroscopeImplementation.IsMonitoring; 470 | 471 | public event EventHandler ReadingChanged 472 | { 473 | add => _gyroscopeImplementation.ReadingChanged += value; 474 | remove => _gyroscopeImplementation.ReadingChanged -= value; 475 | } 476 | } 477 | 478 | public class HapticFeedbackImplementation : Xamarin.Essentials.Interfaces.IHapticFeedback, Microsoft.Maui.Devices.IHapticFeedback, IEssentialsImplementation 479 | { 480 | [Preserve(Conditional = true)] 481 | public HapticFeedbackImplementation() 482 | { 483 | } 484 | 485 | private Microsoft.Maui.Devices.IHapticFeedback _hapticFeedbackImplementation 486 | => HapticFeedback.Default; 487 | 488 | public void Perform(HapticFeedbackType type) => 489 | _hapticFeedbackImplementation.Perform(type); 490 | 491 | public bool IsSupported => _hapticFeedbackImplementation.IsSupported; 492 | } 493 | 494 | public class LauncherImplementation : Xamarin.Essentials.Interfaces.ILauncher, Microsoft.Maui.ApplicationModel.ILauncher, IEssentialsImplementation 495 | { 496 | [Preserve(Conditional = true)] 497 | public LauncherImplementation() 498 | { 499 | } 500 | 501 | private Microsoft.Maui.ApplicationModel.ILauncher _launcherImplementation 502 | => Launcher.Default; 503 | 504 | public Task CanOpenAsync(string uri) => 505 | _launcherImplementation.CanOpenAsync(uri); 506 | 507 | public Task CanOpenAsync(Uri uri) => 508 | _launcherImplementation.CanOpenAsync(uri); 509 | 510 | public Task OpenAsync(string uri) => 511 | _launcherImplementation.OpenAsync(uri); 512 | 513 | Task Xamarin.Essentials.Interfaces.ILauncher.OpenAsync(Uri uri) => 514 | _launcherImplementation.OpenAsync(uri); 515 | 516 | Task Xamarin.Essentials.Interfaces.ILauncher.OpenAsync(OpenFileRequest request) => 517 | _launcherImplementation.OpenAsync(request); 518 | 519 | public Task TryOpenAsync(string uri) => 520 | _launcherImplementation.TryOpenAsync(uri); 521 | 522 | public Task OpenAsync(Uri uri) => 523 | _launcherImplementation.OpenAsync(uri); 524 | 525 | public Task OpenAsync(OpenFileRequest request) => 526 | _launcherImplementation.OpenAsync(request); 527 | 528 | public Task TryOpenAsync(Uri uri) => 529 | _launcherImplementation.TryOpenAsync(uri); 530 | } 531 | 532 | public class MagnetometerImplementation : Xamarin.Essentials.Interfaces.IMagnetometer, Microsoft.Maui.Devices.Sensors.IMagnetometer, IEssentialsImplementation 533 | { 534 | [Preserve(Conditional = true)] 535 | public MagnetometerImplementation() 536 | { 537 | } 538 | 539 | private Microsoft.Maui.Devices.Sensors.IMagnetometer _magnetometerImplementation 540 | => Magnetometer.Default; 541 | 542 | public void Start(SensorSpeed sensorSpeed) => 543 | _magnetometerImplementation.Start(sensorSpeed); 544 | 545 | public void Stop() => 546 | _magnetometerImplementation.Stop(); 547 | 548 | public bool IsSupported => _magnetometerImplementation.IsSupported; 549 | public bool IsMonitoring => _magnetometerImplementation.IsMonitoring; 550 | 551 | public event EventHandler ReadingChanged 552 | { 553 | add => _magnetometerImplementation.ReadingChanged += value; 554 | remove => _magnetometerImplementation.ReadingChanged -= value; 555 | } 556 | } 557 | 558 | [Obsolete] 559 | public class MainThreadImplementation : Xamarin.Essentials.Interfaces.IMainThread, IEssentialsImplementation 560 | { 561 | [Preserve(Conditional = true)] 562 | public MainThreadImplementation() 563 | { 564 | } 565 | 566 | [Obsolete] 567 | public void BeginInvokeOnMainThread(Action action) 568 | => Microsoft.Maui.Controls.Device.BeginInvokeOnMainThread(action); 569 | 570 | [Obsolete] 571 | public Task InvokeOnMainThreadAsync(Action action) 572 | => Microsoft.Maui.Controls.Device.InvokeOnMainThreadAsync(action); 573 | 574 | [Obsolete] 575 | public Task InvokeOnMainThreadAsync(Func func) 576 | => Microsoft.Maui.Controls.Device.InvokeOnMainThreadAsync(func); 577 | 578 | [Obsolete] 579 | public Task InvokeOnMainThreadAsync(Func funcTask) 580 | => Microsoft.Maui.Controls.Device.InvokeOnMainThreadAsync(funcTask); 581 | 582 | [Obsolete] 583 | public Task InvokeOnMainThreadAsync(Func> funcTask) 584 | => Microsoft.Maui.Controls.Device.InvokeOnMainThreadAsync(funcTask); 585 | 586 | [Obsolete] 587 | public Task GetMainThreadSynchronizationContextAsync() 588 | => Microsoft.Maui.Controls.Device.GetMainThreadSynchronizationContextAsync(); 589 | 590 | [Obsolete] 591 | public bool IsMainThread 592 | => !Microsoft.Maui.Controls.Device.IsInvokeRequired; 593 | } 594 | 595 | public class MapImplementation : Xamarin.Essentials.Interfaces.IMap, Microsoft.Maui.ApplicationModel.IMap, IEssentialsImplementation 596 | { 597 | [Preserve(Conditional = true)] 598 | public MapImplementation() 599 | { 600 | } 601 | 602 | private Microsoft.Maui.ApplicationModel.IMap _mapImplementation 603 | => Map.Default; 604 | 605 | public Task OpenAsync(Location location) => 606 | _mapImplementation.OpenAsync(location); 607 | 608 | public Task OpenAsync(Location location, MapLaunchOptions options) => 609 | _mapImplementation.OpenAsync(location, options); 610 | 611 | public Task OpenAsync(double latitude, double longitude) => 612 | _mapImplementation.OpenAsync(latitude, longitude); 613 | 614 | public Task OpenAsync(double latitude, double longitude, MapLaunchOptions options) => 615 | _mapImplementation.OpenAsync(latitude, longitude, options); 616 | 617 | public Task OpenAsync(Placemark placemark) => 618 | _mapImplementation.OpenAsync(placemark); 619 | 620 | public Task OpenAsync(Placemark placemark, MapLaunchOptions options) => 621 | _mapImplementation.OpenAsync(placemark, options); 622 | 623 | // shrug 624 | public async Task TryOpenAsync(double latitude, double longitude, MapLaunchOptions options) 625 | { 626 | try { await _mapImplementation.OpenAsync(latitude, longitude, options); return true; } 627 | catch { return false; } 628 | } 629 | 630 | // shrug 631 | public async Task TryOpenAsync(Placemark placemark, MapLaunchOptions options) 632 | { 633 | try { await _mapImplementation.OpenAsync(placemark, options); return true; } 634 | catch { return false; } 635 | } 636 | } 637 | 638 | public class MediaPickerImplementation : Xamarin.Essentials.Interfaces.IMediaPicker, Microsoft.Maui.Media.IMediaPicker, IEssentialsImplementation 639 | { 640 | [Preserve(Conditional = true)] 641 | public MediaPickerImplementation() 642 | { 643 | } 644 | 645 | private Microsoft.Maui.Media.IMediaPicker _mediaPickerImplementation 646 | => MediaPicker.Default; 647 | 648 | public Task PickPhotoAsync(MediaPickerOptions options = null) => 649 | _mediaPickerImplementation.PickPhotoAsync(options); 650 | 651 | public Task CapturePhotoAsync(MediaPickerOptions options = null) => 652 | _mediaPickerImplementation.CapturePhotoAsync(options); 653 | 654 | public Task PickVideoAsync(MediaPickerOptions options = null) => 655 | _mediaPickerImplementation.PickVideoAsync(options); 656 | 657 | public Task CaptureVideoAsync(MediaPickerOptions options = null) => 658 | _mediaPickerImplementation.CaptureVideoAsync(options); 659 | 660 | public bool IsCaptureSupported => _mediaPickerImplementation.IsCaptureSupported; 661 | } 662 | 663 | public class OrientationSensorImplementation : Xamarin.Essentials.Interfaces.IOrientationSensor, Microsoft.Maui.Devices.Sensors.IOrientationSensor, IEssentialsImplementation 664 | { 665 | [Preserve(Conditional = true)] 666 | public OrientationSensorImplementation() 667 | { 668 | } 669 | 670 | private Microsoft.Maui.Devices.Sensors.IOrientationSensor _orientationSensorImplementation 671 | => OrientationSensor.Default; 672 | 673 | public void Start(SensorSpeed sensorSpeed) => 674 | _orientationSensorImplementation.Start(sensorSpeed); 675 | 676 | public void Stop() => 677 | _orientationSensorImplementation.Stop(); 678 | 679 | public bool IsSupported => _orientationSensorImplementation.IsSupported; 680 | public bool IsMonitoring => _orientationSensorImplementation.IsMonitoring; 681 | 682 | public event EventHandler ReadingChanged 683 | { 684 | add => _orientationSensorImplementation.ReadingChanged += value; 685 | remove => _orientationSensorImplementation.ReadingChanged -= value; 686 | } 687 | } 688 | 689 | // no maui interface? 690 | public class PermissionsImplementation : IPermissions, IEssentialsImplementation 691 | { 692 | [Preserve(Conditional = true)] 693 | public PermissionsImplementation() 694 | { 695 | } 696 | 697 | public Task CheckStatusAsync() 698 | where TPermission : Permissions.BasePermission, new() 699 | => Permissions.CheckStatusAsync(); 700 | 701 | public Task RequestAsync() where TPermission : Permissions.BasePermission, new() 702 | => Permissions.RequestAsync(); 703 | 704 | public bool ShouldShowRationale() where TPermission : Permissions.BasePermission, new() 705 | => Permissions.ShouldShowRationale(); 706 | } 707 | 708 | public class PhoneDialerImplementation : Xamarin.Essentials.Interfaces.IPhoneDialer, Microsoft.Maui.ApplicationModel.Communication.IPhoneDialer, IEssentialsImplementation 709 | { 710 | [Preserve(Conditional = true)] 711 | public PhoneDialerImplementation() 712 | { 713 | } 714 | 715 | private Microsoft.Maui.ApplicationModel.Communication.IPhoneDialer _phoneDialerImplementation 716 | => PhoneDialer.Default; 717 | 718 | public void Open(string number) => 719 | _phoneDialerImplementation.Open(number); 720 | 721 | public bool IsSupported => _phoneDialerImplementation.IsSupported; 722 | } 723 | 724 | public class PreferencesImplementation : Xamarin.Essentials.Interfaces.IPreferences, Microsoft.Maui.Storage.IPreferences, IEssentialsImplementation 725 | { 726 | [Preserve(Conditional = true)] 727 | public PreferencesImplementation() 728 | { 729 | } 730 | 731 | private Microsoft.Maui.Storage.IPreferences _preferencesImplementation 732 | => Preferences.Default; 733 | 734 | public bool ContainsKey(string key) => 735 | _preferencesImplementation.ContainsKey(key); 736 | 737 | public void Remove(string key) => 738 | _preferencesImplementation.Remove(key); 739 | 740 | public void Clear() => 741 | _preferencesImplementation.Clear(); 742 | 743 | public string Get(string key, string defaultValue) => 744 | _preferencesImplementation.Get(key, defaultValue); 745 | 746 | public bool Get(string key, bool defaultValue) => 747 | _preferencesImplementation.Get(key, defaultValue); 748 | 749 | public int Get(string key, int defaultValue) => 750 | _preferencesImplementation.Get(key, defaultValue); 751 | 752 | public double Get(string key, double defaultValue) => 753 | _preferencesImplementation.Get(key, defaultValue); 754 | 755 | public float Get(string key, float defaultValue) => 756 | _preferencesImplementation.Get(key, defaultValue); 757 | 758 | public long Get(string key, long defaultValue) => 759 | _preferencesImplementation.Get(key, defaultValue); 760 | 761 | public void Set(string key, string value) => 762 | _preferencesImplementation.Set(key, value); 763 | 764 | public void Set(string key, bool value) => 765 | _preferencesImplementation.Set(key, value); 766 | 767 | public void Set(string key, int value) => 768 | _preferencesImplementation.Set(key, value); 769 | 770 | public void Set(string key, double value) => 771 | _preferencesImplementation.Set(key, value); 772 | 773 | public void Set(string key, float value) => 774 | _preferencesImplementation.Set(key, value); 775 | 776 | public void Set(string key, long value) => 777 | _preferencesImplementation.Set(key, value); 778 | 779 | public bool ContainsKey(string key, string sharedName = null) => 780 | _preferencesImplementation.ContainsKey(key, sharedName); 781 | 782 | public void Remove(string key, string sharedName = null) => 783 | _preferencesImplementation.Remove(key, sharedName); 784 | 785 | public void Clear(string sharedName = null) => 786 | _preferencesImplementation.Clear(sharedName); 787 | 788 | public string Get(string key, string defaultValue, string sharedName) => 789 | _preferencesImplementation.Get(key, defaultValue, sharedName); 790 | 791 | public bool Get(string key, bool defaultValue, string sharedName) => 792 | _preferencesImplementation.Get(key, defaultValue, sharedName); 793 | 794 | public int Get(string key, int defaultValue, string sharedName) => 795 | _preferencesImplementation.Get(key, defaultValue, sharedName); 796 | 797 | public double Get(string key, double defaultValue, string sharedName) => 798 | _preferencesImplementation.Get(key, defaultValue, sharedName); 799 | 800 | public float Get(string key, float defaultValue, string sharedName) => 801 | _preferencesImplementation.Get(key, defaultValue, sharedName); 802 | 803 | public long Get(string key, long defaultValue, string sharedName) => 804 | _preferencesImplementation.Get(key, defaultValue, sharedName); 805 | 806 | public void Set(string key, string value, string sharedName) => 807 | _preferencesImplementation.Set(key, value, sharedName); 808 | 809 | public void Set(string key, bool value, string sharedName) => 810 | _preferencesImplementation.Set(key, value, sharedName); 811 | 812 | public void Set(string key, int value, string sharedName) => 813 | _preferencesImplementation.Set(key, value, sharedName); 814 | 815 | public void Set(string key, double value, string sharedName) => 816 | _preferencesImplementation.Set(key, value, sharedName); 817 | 818 | public void Set(string key, float value, string sharedName) => 819 | _preferencesImplementation.Set(key, value, sharedName); 820 | 821 | public void Set(string key, long value, string sharedName) => 822 | _preferencesImplementation.Set(key, value, sharedName); 823 | 824 | public DateTime Get(string key, DateTime defaultValue) => 825 | _preferencesImplementation.Get(key, defaultValue); 826 | 827 | public void Set(string key, DateTime value) => 828 | _preferencesImplementation.Set(key, value); 829 | 830 | public DateTime Get(string key, DateTime defaultValue, string sharedName) => 831 | _preferencesImplementation.Get(key, defaultValue, sharedName); 832 | 833 | public void Set(string key, DateTime value, string sharedName) => 834 | _preferencesImplementation.Set(key, value, sharedName); 835 | 836 | public void Set(string key, T value, string sharedName = null) => 837 | _preferencesImplementation.Set(key, value, sharedName); 838 | 839 | public T Get(string key, T defaultValue, string sharedName = null) => 840 | _preferencesImplementation.Get(key, defaultValue, sharedName); 841 | } 842 | 843 | public class ScreenshotImplementation : Xamarin.Essentials.Interfaces.IScreenshot, Microsoft.Maui.Media.IScreenshot, IEssentialsImplementation 844 | { 845 | [Preserve(Conditional = true)] 846 | public ScreenshotImplementation() 847 | { 848 | } 849 | 850 | private Microsoft.Maui.Media.IScreenshot _screenshotImplementation 851 | => Screenshot.Default; 852 | 853 | public Task CaptureAsync() => 854 | _screenshotImplementation.CaptureAsync(); 855 | 856 | public bool IsCaptureSupported => _screenshotImplementation.IsCaptureSupported; 857 | } 858 | 859 | public class SecureStorageImplementation : Xamarin.Essentials.Interfaces.ISecureStorage, Microsoft.Maui.Storage.ISecureStorage, IEssentialsImplementation 860 | { 861 | [Preserve(Conditional = true)] 862 | public SecureStorageImplementation() 863 | { 864 | } 865 | 866 | private Microsoft.Maui.Storage.ISecureStorage _secureStorageImplementation 867 | => SecureStorage.Default; 868 | 869 | public Task GetAsync(string key) => 870 | _secureStorageImplementation.GetAsync(key); 871 | 872 | public Task SetAsync(string key, string value) => 873 | _secureStorageImplementation.SetAsync(key, value); 874 | 875 | public bool Remove(string key) => 876 | _secureStorageImplementation.Remove(key); 877 | 878 | public void RemoveAll() => 879 | _secureStorageImplementation.RemoveAll(); 880 | } 881 | 882 | public class ShareImplementation : Xamarin.Essentials.Interfaces.IShare, Microsoft.Maui.ApplicationModel.DataTransfer.IShare, IEssentialsImplementation 883 | { 884 | [Preserve(Conditional = true)] 885 | public ShareImplementation() 886 | { 887 | } 888 | 889 | private Microsoft.Maui.ApplicationModel.DataTransfer.IShare _shareImplementation 890 | => Share.Default; 891 | 892 | public Task RequestAsync(string text) => 893 | _shareImplementation.RequestAsync(text); 894 | 895 | public Task RequestAsync(string text, string title) => 896 | _shareImplementation.RequestAsync(text, title); 897 | 898 | public Task RequestAsync(ShareTextRequest request) => 899 | _shareImplementation.RequestAsync(request); 900 | 901 | public Task RequestAsync(ShareFileRequest request) => 902 | _shareImplementation.RequestAsync(request); 903 | 904 | public Task RequestAsync(ShareMultipleFilesRequest request) => 905 | _shareImplementation.RequestAsync(request); 906 | } 907 | 908 | public class SmsImplementation : Xamarin.Essentials.Interfaces.ISms, Microsoft.Maui.ApplicationModel.Communication.ISms, IEssentialsImplementation 909 | { 910 | [Preserve(Conditional = true)] 911 | public SmsImplementation() 912 | { 913 | } 914 | 915 | private Microsoft.Maui.ApplicationModel.Communication.ISms _smsImplementation 916 | => Sms.Default; 917 | 918 | public Task ComposeAsync() => 919 | _smsImplementation.ComposeAsync(default); 920 | 921 | public Task ComposeAsync(SmsMessage message) => 922 | _smsImplementation.ComposeAsync(message); 923 | 924 | public bool IsComposeSupported => _smsImplementation.IsComposeSupported; 925 | } 926 | 927 | public class TextToSpeechImplementation : Xamarin.Essentials.Interfaces.ITextToSpeech, Microsoft.Maui.Media.ITextToSpeech, IEssentialsImplementation 928 | { 929 | [Preserve(Conditional = true)] 930 | public TextToSpeechImplementation() 931 | { 932 | } 933 | 934 | private Microsoft.Maui.Media.ITextToSpeech _textToSpeechImplementation 935 | => TextToSpeech.Default; 936 | 937 | public Task> GetLocalesAsync() => 938 | _textToSpeechImplementation.GetLocalesAsync(); 939 | 940 | public Task SpeakAsync(string text, CancellationToken cancelToken = default) 941 | => _textToSpeechImplementation.SpeakAsync(text, default, cancelToken); 942 | 943 | public Task SpeakAsync(string text, SpeechOptions options = null, CancellationToken cancelToken = default) => 944 | _textToSpeechImplementation.SpeakAsync(text, options, cancelToken); 945 | } 946 | 947 | public class VersionTrackingImplementation : Xamarin.Essentials.Interfaces.IVersionTracking, Microsoft.Maui.ApplicationModel.IVersionTracking, IEssentialsImplementation 948 | { 949 | [Preserve(Conditional = true)] 950 | public VersionTrackingImplementation() 951 | { 952 | } 953 | 954 | private Microsoft.Maui.ApplicationModel.IVersionTracking _versionTrackingImplementation 955 | => VersionTracking.Default; 956 | 957 | public void Track() => 958 | _versionTrackingImplementation.Track(); 959 | 960 | public bool IsFirstLaunchForVersion(string version) => 961 | _versionTrackingImplementation.IsFirstLaunchForVersion(version); 962 | 963 | public bool IsFirstLaunchForBuild(string build) => 964 | _versionTrackingImplementation.IsFirstLaunchForBuild(build); 965 | 966 | public bool IsFirstLaunchEver => _versionTrackingImplementation.IsFirstLaunchEver; 967 | public bool IsFirstLaunchForCurrentVersion => _versionTrackingImplementation.IsFirstLaunchForCurrentVersion; 968 | public bool IsFirstLaunchForCurrentBuild => _versionTrackingImplementation.IsFirstLaunchForCurrentBuild; 969 | public string CurrentVersion => _versionTrackingImplementation.CurrentVersion; 970 | public string CurrentBuild => _versionTrackingImplementation.CurrentBuild; 971 | public string PreviousVersion => _versionTrackingImplementation.PreviousVersion; 972 | public string PreviousBuild => _versionTrackingImplementation.PreviousBuild; 973 | public string FirstInstalledVersion => _versionTrackingImplementation.FirstInstalledVersion; 974 | public string FirstInstalledBuild => _versionTrackingImplementation.FirstInstalledBuild; 975 | 976 | IEnumerable Xamarin.Essentials.Interfaces.IVersionTracking.VersionHistory => _versionTrackingImplementation.VersionHistory; 977 | IEnumerable Xamarin.Essentials.Interfaces.IVersionTracking.BuildHistory => _versionTrackingImplementation.BuildHistory; 978 | 979 | public IReadOnlyList VersionHistory => _versionTrackingImplementation.VersionHistory; 980 | public IReadOnlyList BuildHistory => _versionTrackingImplementation.BuildHistory; 981 | } 982 | 983 | public class VibrationImplementation : Xamarin.Essentials.Interfaces.IVibration, Microsoft.Maui.Devices.IVibration, IEssentialsImplementation 984 | { 985 | [Preserve(Conditional = true)] 986 | public VibrationImplementation() 987 | { 988 | } 989 | 990 | private Microsoft.Maui.Devices.IVibration _vibrationImplementation 991 | => Vibration.Default; 992 | 993 | public void Vibrate() => 994 | _vibrationImplementation.Vibrate(); 995 | 996 | public void Vibrate(double duration) => 997 | _vibrationImplementation.Vibrate(duration); 998 | 999 | public void Vibrate(TimeSpan duration) => 1000 | _vibrationImplementation.Vibrate(duration); 1001 | 1002 | public void Cancel() => 1003 | _vibrationImplementation.Cancel(); 1004 | 1005 | public bool IsSupported => _vibrationImplementation.IsSupported; 1006 | } 1007 | 1008 | public class WebAuthenticatorImplementation : Xamarin.Essentials.Interfaces.IWebAuthenticator, Microsoft.Maui.Authentication.IWebAuthenticator, IEssentialsImplementation 1009 | { 1010 | [Preserve(Conditional = true)] 1011 | public WebAuthenticatorImplementation() 1012 | { 1013 | } 1014 | 1015 | private Microsoft.Maui.Authentication.IWebAuthenticator _webAuthenticatorImplementation 1016 | => WebAuthenticator.Default; 1017 | 1018 | public Task AuthenticateAsync(Uri url, Uri callbackUrl) => 1019 | _webAuthenticatorImplementation.AuthenticateAsync(url, callbackUrl); 1020 | 1021 | public Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions) => 1022 | _webAuthenticatorImplementation.AuthenticateAsync(webAuthenticatorOptions); 1023 | } 1024 | } 1025 | 1026 | namespace Xamarin.Essentials.Interfaces 1027 | { 1028 | public interface IAccelerometer 1029 | { 1030 | void Start(SensorSpeed sensorSpeed); 1031 | void Stop(); 1032 | bool IsMonitoring { get; } 1033 | event EventHandler ReadingChanged; 1034 | event EventHandler ShakeDetected; 1035 | } 1036 | 1037 | public interface IAppActions 1038 | { 1039 | Task> GetAsync(); 1040 | Task SetAsync(params AppAction[] actions); 1041 | Task SetAsync(IEnumerable actions); 1042 | event EventHandler OnAppAction; 1043 | } 1044 | 1045 | public interface IAppInfo 1046 | { 1047 | void ShowSettingsUI(); 1048 | string PackageName { get; } 1049 | string Name { get; } 1050 | string VersionString { get; } 1051 | Version Version { get; } 1052 | string BuildString { get; } 1053 | AppTheme RequestedTheme { get; } 1054 | } 1055 | 1056 | public interface IBarometer 1057 | { 1058 | void Start(SensorSpeed sensorSpeed); 1059 | void Stop(); 1060 | bool IsMonitoring { get; } 1061 | event EventHandler ReadingChanged; 1062 | } 1063 | 1064 | public interface IBattery 1065 | { 1066 | double ChargeLevel { get; } 1067 | BatteryState State { get; } 1068 | BatteryPowerSource PowerSource { get; } 1069 | EnergySaverStatus EnergySaverStatus { get; } 1070 | event EventHandler BatteryInfoChanged; 1071 | event EventHandler EnergySaverStatusChanged; 1072 | } 1073 | 1074 | public interface IBrowser 1075 | { 1076 | Task OpenAsync(string uri); 1077 | Task OpenAsync(string uri, BrowserLaunchMode launchMode); 1078 | Task OpenAsync(string uri, BrowserLaunchOptions options); 1079 | Task OpenAsync(Uri uri); 1080 | Task OpenAsync(Uri uri, BrowserLaunchMode launchMode); 1081 | Task OpenAsync(Uri uri, BrowserLaunchOptions options); 1082 | } 1083 | 1084 | public interface IClipboard 1085 | { 1086 | Task SetTextAsync(string text); 1087 | Task GetTextAsync(); 1088 | bool HasText { get; } 1089 | event EventHandler ClipboardContentChanged; 1090 | } 1091 | 1092 | public interface ICompass 1093 | { 1094 | void Start(SensorSpeed sensorSpeed); 1095 | void Start(SensorSpeed sensorSpeed, bool applyLowPassFilter); 1096 | void Stop(); 1097 | bool IsMonitoring { get; } 1098 | event EventHandler ReadingChanged; 1099 | } 1100 | 1101 | public interface IConnectivity 1102 | { 1103 | NetworkAccess NetworkAccess { get; } 1104 | IEnumerable ConnectionProfiles { get; } 1105 | event EventHandler ConnectivityChanged; 1106 | } 1107 | 1108 | public interface IContacts 1109 | { 1110 | Task PickContactAsync(); 1111 | Task> GetAllAsync(CancellationToken cancellationToken = default); 1112 | } 1113 | 1114 | public interface IDeviceDisplay 1115 | { 1116 | bool KeepScreenOn { get; set; } 1117 | DisplayInfo MainDisplayInfo { get; } 1118 | event EventHandler MainDisplayInfoChanged; 1119 | } 1120 | 1121 | public interface IDeviceInfo 1122 | { 1123 | string Model { get; } 1124 | string Manufacturer { get; } 1125 | string Name { get; } 1126 | string VersionString { get; } 1127 | Version Version { get; } 1128 | DevicePlatform Platform { get; } 1129 | DeviceIdiom Idiom { get; } 1130 | DeviceType DeviceType { get; } 1131 | } 1132 | 1133 | public interface IEmail 1134 | { 1135 | Task ComposeAsync(); 1136 | Task ComposeAsync(string subject, string body, params string[] to); 1137 | Task ComposeAsync(EmailMessage message); 1138 | } 1139 | 1140 | public interface IFilePicker 1141 | { 1142 | Task PickAsync(PickOptions options = null); 1143 | Task> PickMultipleAsync(PickOptions options = null); 1144 | } 1145 | 1146 | public interface IFileSystem 1147 | { 1148 | Task OpenAppPackageFileAsync(string filename); 1149 | string CacheDirectory { get; } 1150 | string AppDataDirectory { get; } 1151 | } 1152 | 1153 | public interface IFlashlight 1154 | { 1155 | Task TurnOnAsync(); 1156 | Task TurnOffAsync(); 1157 | } 1158 | 1159 | public interface IGeocoding 1160 | { 1161 | Task> GetPlacemarksAsync(Location location); 1162 | Task> GetPlacemarksAsync(double latitude, double longitude); 1163 | Task> GetLocationsAsync(string address); 1164 | } 1165 | 1166 | public interface IGeolocation 1167 | { 1168 | Task GetLastKnownLocationAsync(); 1169 | Task GetLocationAsync(); 1170 | Task GetLocationAsync(GeolocationRequest request); 1171 | Task GetLocationAsync(GeolocationRequest request, CancellationToken cancelToken); 1172 | } 1173 | 1174 | public interface IGyroscope 1175 | { 1176 | void Start(SensorSpeed sensorSpeed); 1177 | void Stop(); 1178 | bool IsMonitoring { get; } 1179 | event EventHandler ReadingChanged; 1180 | } 1181 | 1182 | public interface IHapticFeedback 1183 | { 1184 | void Perform(HapticFeedbackType type = HapticFeedbackType.Click); 1185 | } 1186 | 1187 | public interface ILauncher 1188 | { 1189 | Task CanOpenAsync(string uri); 1190 | Task CanOpenAsync(Uri uri); 1191 | Task OpenAsync(string uri); 1192 | Task OpenAsync(Uri uri); 1193 | Task OpenAsync(OpenFileRequest request); 1194 | Task TryOpenAsync(string uri); 1195 | Task TryOpenAsync(Uri uri); 1196 | } 1197 | 1198 | public interface IMagnetometer 1199 | { 1200 | void Start(SensorSpeed sensorSpeed); 1201 | void Stop(); 1202 | bool IsMonitoring { get; } 1203 | event EventHandler ReadingChanged; 1204 | } 1205 | 1206 | [Obsolete] 1207 | public interface IMainThread 1208 | { 1209 | [Obsolete] 1210 | void BeginInvokeOnMainThread(Action action); 1211 | 1212 | [Obsolete] 1213 | Task InvokeOnMainThreadAsync(Action action); 1214 | 1215 | [Obsolete] 1216 | Task InvokeOnMainThreadAsync(Func func); 1217 | 1218 | [Obsolete] 1219 | Task InvokeOnMainThreadAsync(Func funcTask); 1220 | 1221 | [Obsolete] 1222 | Task InvokeOnMainThreadAsync(Func> funcTask); 1223 | 1224 | [Obsolete] 1225 | Task GetMainThreadSynchronizationContextAsync(); 1226 | 1227 | [Obsolete] bool IsMainThread { get; } 1228 | } 1229 | 1230 | public interface IMap 1231 | { 1232 | Task OpenAsync(Location location); 1233 | Task OpenAsync(Location location, MapLaunchOptions options); 1234 | Task OpenAsync(double latitude, double longitude); 1235 | Task OpenAsync(double latitude, double longitude, MapLaunchOptions options); 1236 | Task OpenAsync(Placemark placemark); 1237 | Task OpenAsync(Placemark placemark, MapLaunchOptions options); 1238 | } 1239 | 1240 | public interface IMediaPicker 1241 | { 1242 | Task PickPhotoAsync(MediaPickerOptions options = null); 1243 | Task CapturePhotoAsync(MediaPickerOptions options = null); 1244 | Task PickVideoAsync(MediaPickerOptions options = null); 1245 | Task CaptureVideoAsync(MediaPickerOptions options = null); 1246 | bool IsCaptureSupported { get; } 1247 | } 1248 | 1249 | public interface IOrientationSensor 1250 | { 1251 | void Start(SensorSpeed sensorSpeed); 1252 | void Stop(); 1253 | bool IsMonitoring { get; } 1254 | event EventHandler ReadingChanged; 1255 | } 1256 | 1257 | public interface IPermissions 1258 | { 1259 | Task CheckStatusAsync() where TPermission : Permissions.BasePermission, new(); 1260 | Task RequestAsync() where TPermission : Permissions.BasePermission, new(); 1261 | bool ShouldShowRationale() where TPermission : Permissions.BasePermission, new(); 1262 | } 1263 | 1264 | public interface IPhoneDialer 1265 | { 1266 | void Open(string number); 1267 | } 1268 | 1269 | public interface IPreferences 1270 | { 1271 | bool ContainsKey(string key); 1272 | void Remove(string key); 1273 | void Clear(); 1274 | string Get(string key, string defaultValue); 1275 | bool Get(string key, bool defaultValue); 1276 | int Get(string key, int defaultValue); 1277 | double Get(string key, double defaultValue); 1278 | float Get(string key, float defaultValue); 1279 | long Get(string key, long defaultValue); 1280 | void Set(string key, string value); 1281 | void Set(string key, bool value); 1282 | void Set(string key, int value); 1283 | void Set(string key, double value); 1284 | void Set(string key, float value); 1285 | void Set(string key, long value); 1286 | bool ContainsKey(string key, string sharedName); 1287 | void Remove(string key, string sharedName); 1288 | void Clear(string sharedName); 1289 | string Get(string key, string defaultValue, string sharedName); 1290 | bool Get(string key, bool defaultValue, string sharedName); 1291 | int Get(string key, int defaultValue, string sharedName); 1292 | double Get(string key, double defaultValue, string sharedName); 1293 | float Get(string key, float defaultValue, string sharedName); 1294 | long Get(string key, long defaultValue, string sharedName); 1295 | void Set(string key, string value, string sharedName); 1296 | void Set(string key, bool value, string sharedName); 1297 | void Set(string key, int value, string sharedName); 1298 | void Set(string key, double value, string sharedName); 1299 | void Set(string key, float value, string sharedName); 1300 | void Set(string key, long value, string sharedName); 1301 | DateTime Get(string key, DateTime defaultValue); 1302 | void Set(string key, DateTime value); 1303 | DateTime Get(string key, DateTime defaultValue, string sharedName); 1304 | void Set(string key, DateTime value, string sharedName); 1305 | } 1306 | 1307 | public interface IScreenshot 1308 | { 1309 | Task CaptureAsync(); 1310 | bool IsCaptureSupported { get; } 1311 | } 1312 | 1313 | public interface ISecureStorage 1314 | { 1315 | Task GetAsync(string key); 1316 | Task SetAsync(string key, string value); 1317 | bool Remove(string key); 1318 | void RemoveAll(); 1319 | } 1320 | 1321 | public interface IShare 1322 | { 1323 | Task RequestAsync(string text); 1324 | Task RequestAsync(string text, string title); 1325 | Task RequestAsync(ShareTextRequest request); 1326 | Task RequestAsync(ShareFileRequest request); 1327 | Task RequestAsync(ShareMultipleFilesRequest request); 1328 | } 1329 | 1330 | public interface ISms 1331 | { 1332 | Task ComposeAsync(); 1333 | Task ComposeAsync(SmsMessage message); 1334 | } 1335 | 1336 | public interface ITextToSpeech 1337 | { 1338 | Task> GetLocalesAsync(); 1339 | Task SpeakAsync(string text, CancellationToken cancelToken = default); 1340 | Task SpeakAsync(string text, SpeechOptions options, CancellationToken cancelToken = default); 1341 | } 1342 | 1343 | public interface IVersionTracking 1344 | { 1345 | void Track(); 1346 | bool IsFirstLaunchForVersion(string version); 1347 | bool IsFirstLaunchForBuild(string build); 1348 | bool IsFirstLaunchEver { get; } 1349 | bool IsFirstLaunchForCurrentVersion { get; } 1350 | bool IsFirstLaunchForCurrentBuild { get; } 1351 | string CurrentVersion { get; } 1352 | string CurrentBuild { get; } 1353 | string PreviousVersion { get; } 1354 | string PreviousBuild { get; } 1355 | string FirstInstalledVersion { get; } 1356 | string FirstInstalledBuild { get; } 1357 | IEnumerable VersionHistory { get; } 1358 | IEnumerable BuildHistory { get; } 1359 | } 1360 | 1361 | public interface IVibration 1362 | { 1363 | void Vibrate(); 1364 | void Vibrate(double duration); 1365 | void Vibrate(TimeSpan duration); 1366 | void Cancel(); 1367 | } 1368 | 1369 | public interface IWebAuthenticator 1370 | { 1371 | Task AuthenticateAsync(Uri url, Uri callbackUrl); 1372 | Task AuthenticateAsync(WebAuthenticatorOptions webAuthenticatorOptions); 1373 | } 1374 | } 1375 | --------------------------------------------------------------------------------