百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
S

shiny

> 编程语言
开源

用于后台运行和设备硬件服务的 .NET Framework (iOS、MacCatalyst、Android 和 Windows)

1.6K stars0 点赞0 次浏览
访问官网GitHub

工具介绍

用于后台运行和设备硬件服务的 .NET Framework (iOS、MacCatalyst、Android 和 Windows)

Shiny Client for .NET

Shiny is a cross-platform framework designed to make working with device services and background processes easy, testable, and consistent while bringing things like dependency injection & logging in a structured way to your code!

Features

  • Handles all of the cruft like Permissions, main thread traversal, persistent storage and app restarts
  • Brings your infrastructure to the background
  • Provides logging to ensure you know when your services fail in the background
  • Gives a clean & testable API surface for your code
  • Native AOT & trim-friendly across all modules
  • Cross-platform: iOS, Android, tvOS, Mac Catalyst, macOS, Windows, Linux, and Blazor WebAssembly (where the platform allows)

Modules

  • Background Jobs - periodic background work backed by BGTaskScheduler (iOS/tvOS), WorkManager (Android), COM-activated background tasks (Windows), and an in-process managed runner for Linux/macOS/Blazor WASM
  • HTTP Transfers - resumable background uploads/downloads on NSURLSession (iOS/tvOS), an HttpClient-driven managed loop with Range-based resume (Android, Windows, Linux, macOS, .NET base), and Service Worker Background Sync (Blazor WASM). Pause/resume support - pause stops a transfer without cancelling it (downloads continue from where they left off, uploads restart). First-class Azure Blob Storage and AWS S3 (SigV4) request builders included. AddTransferProgress() puts progress in front of the user - an iOS Live Activity, or the Android foreground-service notification promoted to an Android 16 live update - from one manager, with no code in your transfer delegate
  • Data Sync - bidirectional JSON record sync over HTTP with the same platform tiers as HTTP Transfers: outbox + inbox on NSURLSession (iOS/tvOS/Mac Catalyst), Foreground Service + HttpClient (Android), HttpClient + connectivity loop (Windows/Linux/macOS), and LocalStorage-backed HttpClient (Blazor WASM). Includes batched outbox, tombstones, conflict resolution, retry with exponential backoff, and AOT-safe serialization through Shiny.Json
  • Network Discovery - three local-network discovery protocols in one package, each with browse, resolve, and publish
    • mDNS/DNS-SD (Bonjour/Zeroconf) - backed by NSNetService on iOS/tvOS/Mac Catalyst/macOS (so no com.apple.developer.networking.multicast entitlement is needed), NsdManager on Android (no multicast lock), and a dependency-free managed responder on UDP 5353 for Windows, Linux, macOS console, and server .NET. await foreach (var r in mdns.Browse("_http._tcp", ct)) for live discovery, BrowseOnce(...) for a one-shot scan, and Publish(...) to advertise your own service with TXT metadata
    • SSDP/UPnP - find routers, media servers, Sonos, Roku, and smart TVs. ssdp.SearchAll() for a one-shot sweep, Browse(...) for a live list keyed on UDN with ssdp:alive/byebye tracking and BOOTID-aware expiry, GetDescription(...) to fetch and parse the device description (friendly name, model, icons, service list), and Publish(...) to advertise your own root device. Discovery and description only - no SOAP action invocation, no GENA eventing
    • WS-Discovery - find ONVIF cameras, WSD printers/scanners, and Windows machines. Probe/Resolve/Hello/Bye on both the 2005 (ONVIF/Windows) and 2009 (OASIS) profiles, with correct QName-prefix resolution for Types, RFC 3986 segment-prefix scope matching, and ProbeOnvifCameras(...) as a shortcut
    • Platform requirements differ by protocol. mDNS needs no entitlement anywhere. SSDP and WS-Discovery have no OS-level API on any platform, so they use raw multicast: iOS requires the Apple-approved com.apple.developer.networking.multicast entitlement, Android needs CHANGE_WIFI_MULTICAST_STATE (the multicast lock is acquired for you) plus ACCESS_LOCAL_NETWORK from Android 17. Sandboxed hosts still need their usual network permission - com.apple.security.network.client/.server on Mac Catalyst & macOS, privateNetworkClientServer for packaged Windows apps. A missing one throws DiscoveryPermissionException naming exactly what to add, rather than silently finding nothing
  • Wi-Fi - scan for access points, join and leave networks, manage the networks the device has saved, watch the current network's SSID/signal/IP/DNS, and host a hotspot
    • Platform reach is genuinely uneven, and the API says so rather than pretending otherwise. Every manager publishes a WifiCapabilities flags property; anything unavailable throws WifiNotSupportedException naming the specific limit (an Apple entitlement, an Android API level that revoked the call, a platform with no such concept). Check the flag to branch, catch the exception as a backstop
    • IWifiManager - Scan(ct) returns one WifiNetwork per BSSID with SSID, security scheme, dBm + 0-100 signal, frequency, band and channel. Connect(new WifiConnectionRequest(ssid) { Passphrase = ... }) joins and waits for DHCP rather than returning on association, and with Remember left on also persists the network for later (a WifiNetworkSuggestion on Android 11+, an ordinary profile elsewhere). await GetCurrentNetwork(ct) reports the joined network - SSID, BSSID, security, signal, plus every IP, DNS resolver, gateway and mask - and Changed fires with the new WifiNetworkInfo? (null when Wi-Fi drops), de-duplicated so the chatty native watchers behind it do not leak through, delivering the current network once on subscribe. Reading the SSID is asynchronous because both phone platforms stopped answering synchronously: iOS 14 replaced CNCopyCurrentNetworkInfo with NEHotspotNetwork.fetchCurrent, and Android 12 redacts the SSID and BSSID out of every pull-style read no matter what permissions are held, handing them out only through a NetworkCallback registered with FLAG_INCLUDE_LOCATION_INFO
    • Known networks - GetKnownNetworks() lists what the device has saved as KnownWifiNetwork (opaque platform Id, SSID, security, hidden), Forget(id) deletes one, and Connect(id) rejoins one without handing the passphrase over again. The scope differs and the API says which: iOS/Mac Catalyst and Android only ever disclose your own app's entries (NEHotspotConfigurationManager.getConfiguredSSIDs, network suggestions), while Windows, macOS and Linux hand back every profile on the machine. Connect(id) works on Windows, macOS, Linux and Android below API 29 - iOS and modern Android treat a saved network as a standing hint the OS acts on, with no call to force it. The Id is the platform's own handle: a NetworkManager connection UUID on Linux, a numeric network id on legacy Android, the SSID everywhere else
    • IWifiHotspot - Start(...) returns an IHotspotSession carrying the SSID and passphrase actually in use; dispose it to bring the access point down. GetClients() lists joined devices with MAC and address on Windows and Linux. Android raises a local-only hotspot (clients reach the device, not the internet) and picks the SSID/passphrase itself, Windows shares the machine's internet connection, Linux runs NetworkManager AP mode with DHCP + NAT, and iOS/macOS have no hotspot API at all
    • Backends - WifiManager + ConnectivityManager on Android (specifier-based joins from API 29, legacy WifiConfiguration below), NEHotspotConfiguration + CaptiveNetwork on iOS/Mac Catalyst, CoreWLAN on macOS, WiFiAdapter + NetworkOperatorTetheringManager + Radio on Windows, and NetworkManager over D-Bus on Linux (separate Shiny.Net.Wifi.Linux package). Saved profiles are outside WinRT entirely, so Windows reaches wlanapi.dll directly for those three calls. The plain .NET target still reports IP/DNS off the wireless interface and raises Changed; the Wi-Fi-specific calls throw
    • Permissions - Android needs ACCESS_WIFI_STATE, CHANGE_WIFI_STATE, ACCESS_FINE_LOCATION and NEARBY_WIFI_DEVICES (API 33+); iOS needs the Hotspot Configuration and Access WiFi Information capabilities plus NSLocationWhenInUseUsageDescription; macOS needs the location usage description; Windows needs wiFiControl and radios; Linux gates the mutating calls behind polkit. A scan that comes back empty because location was refused throws WifiPermissionException instead of looking like an empty neighbourhood
  • Screen Recording - record the screen to an MP4 with optional microphone and system audio
    • What "the screen" means is not the same everywhere, and the API says so rather than pretending otherwise. Android, macOS, Windows and Linux record the system screen, so other apps end up in the file. iOS and Mac Catalyst record your own app's UI only - that is all ReplayKit offers without a Broadcast Upload Extension, which a NuGet package cannot deliver. Every recorder publishes a ScreenRecorderCapabilities flags property; anything unavailable throws ScreenRecorderNotSupportedException naming the specific limit. The flags are read off the instance because they differ within a platform: macOS 15 gains microphone capture and loses pause (SCRecordingOutput writes the file itself and cannot be detached mid-recording) where macOS 12.3-14 has it the other way round
    • IScreenRecorder - await recorder.Start(new ScreenRecordingRequest { IncludeMicrophone = true, MaxWidth = 1280 }) returns an IScreenRecording that does not come back until frames are genuinely being written - so a consent dialog, a compositor picker or an Android foreground-service promotion all complete first. Pause()/Resume() close the gap in the timeline rather than leaving a frozen stretch, Stop() returns a ScreenRecordingResult with the path, duration, size and the MimeType actually produced (browsers disagree - Safari and Chrome give MP4, Firefox gives WebM), and disposing without stopping cancels and deletes the partial file. A request asking for something outside Capabilities throws before any native call, because a recording that silently came out without the microphone is worse than one that refused to start
    • GetTargets() lists displays, windows and applications on macOS and Windows, so an app can offer its own picker. Linux and the browser hand selection to the compositor and throw here - their picker appears during Start instead
    • The OS ending it on its own is a first-class outcome. IScreenRecording.Faulted fires with a reason - the user hit Android's cast notification or the browser's "Stop sharing" bar, iOS took the screen for an incoming call, a monitor was unplugged, the encoder failed - and carries whatever was salvaged, so a recording cut short still yields a playable file rather than a silent truncation. MaxDuration stops cleanly and reports the same way
    • Backends - MediaProjection + MediaCodec/MediaMuxer on Android (MediaRecorder takes a single audio source and playback capture is not one of them, so app audio forces the whole pipeline down to MediaCodec), ReplayKit startCapture into an AVAssetWriter on iOS/tvOS/Mac Catalyst (startRecording only surrenders its file through a share sheet, which is no use to a library), ScreenCaptureKit on macOS - SCRecordingOutput on 15+ and the same AVAssetWriter below it - Windows.Graphics.Capture into a MediaStreamSource transcoded by Media Foundation on Windows, and the xdg-desktop-portal ScreenCast API driving gst-launch-1.0 or ffmpeg on Linux (separate Shiny.ScreenRecorder.Linux package). Blazor WebAssembly uses getDisplayMedia + MediaRecorder (separate Shiny.ScreenRecorder.Blazor package) and is the only platform where pause is native and the result has no file path - there is no filesystem, so OpenRead() is the portable accessor
    • Permissions - Android needs FOREGROUND_SERVICE, FOREGROUND_SERVICE_MEDIA_PROJECTION and RECORD_AUDIO for audio, plus a per-recording consent dialog that cannot be pre-granted; iOS needs `NSMicrophoneUsageDescript

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

C#androidblebluetoothlegeofences

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言