.NET Maui中MediaRouteButton实现问题求助
问题描述
我正在实现.NET Maui 8中的MediaRouteButton,已查阅Google SDK文档,但缺乏Maui落地的明确指引。目前已完成自定义处理器与设备发现服务的开发,能够检测并列出符合MediaSelector筛选条件的设备,但点击MediaRouteButton时,按钮默认的设备选择对话框并未弹出。我考虑自行开发该对话框,但希望先确认是否遗漏了关键配置或步骤。
自定义处理器代码
using AndroidX.MediaRouter.App; // 原使用Android.APP的MediaRouteButton,已替换 using MauiApp3.CustomControls; using Microsoft.Maui.Handlers; using static Android.Views.View; using AndroidViews = Android.Views; using AU = Android.Util; namespace MauiApp3.Platforms.Android.Handlers { public partial class CustomMediaRouteButtonHandler : ViewHandler<CustomMediaRouteButton, MediaRouteButton> { public static IPropertyMapper<CustomMediaRouteButton, CustomMediaRouteButtonHandler> Mapper = new PropertyMapper<CustomMediaRouteButton, CustomMediaRouteButtonHandler> { // 按需添加映射 }; public CustomMediaRouteButtonHandler() : base(Mapper) { } protected override void ConnectHandler(MediaRouteButton platformView) { base.ConnectHandler(platformView); // 执行需要PlatformView存在的初始化操作 SetEnabled(VirtualView.IsEnabled); } protected override MediaRouteButton CreatePlatformView() { var mediaRouteButton = new MediaRouteButton(Context); mediaRouteButton.SetOnClickListener(new CustomClickListener()); return mediaRouteButton; } private class CustomClickListener : Java.Lang.Object, AndroidViews.View.IOnClickListener { public void OnClick(AndroidViews.View? v) { //((MediaRouteButton)v).PerformClick(); // 记录点击事件 AU.Log.Debug("CustomMediaRouteButton", "Button clicked."); // 可选:在此执行额外操作 // 如果对话框未自动弹出,可尝试手动调用 // 但若按钮默认会弹出对话框,则不要调用ShowDialog(),避免冲突 } } private void OnMediaRouteButtonTouched(object sender, AndroidViews.View.TouchEventArgs e) { // 处理触摸事件 // e.Event可访问MotionEvent var oo = ""; } private void OnMediaRouteButtonClicked(object sender, EventArgs e) { if (VirtualView != null) { VirtualView.OnClicked(); } } protected override void DisconnectHandler(MediaRouteButton platformView) { platformView.Touch -= OnMediaRouteButtonTouched; platformView.Click -= OnMediaRouteButtonClicked; base.DisconnectHandler(platformView); } public static void MapIsEnabled(CustomMediaRouteButtonHandler handler, CustomMediaRouteButton customMediaRouteButton) { handler.SetEnabled(customMediaRouteButton.IsEnabled); } private void SetEnabled(bool isEnabled) { //isEnabled = true; if (PlatformView != null) { PlatformView.Enabled = isEnabled; // 调整按钮视觉状态,比如透明度,区分启用/禁用状态 PlatformView.Alpha = isEnabled ? 1.0f : 0.5f; } } public void UpdateIsEnabled(bool isEnabled) { if (PlatformView != null) { PlatformView.Enabled = isEnabled; // 更新按钮视觉状态的额外逻辑 PlatformView.Alpha = isEnabled ? 1.0f : 0.5f; } } } }
设备发现服务代码
using Android.Content; using AndroidX.MediaRouter.Media; using AU = Android.Util; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Android.Gms.Cast; namespace MauiApp3.Platforms.Android.Services { public class DeviceDiscoveryService : IDeviceDiscoveryService { private readonly MediaRouter _mediaRouter; private readonly MediaRouteSelector _mediaRouteSelector; private readonly MediaRouterCallback _mediaRouterCallback; private readonly List<string> _deviceNames = new List<string>(); public event EventHandler DevicesChanged; public DeviceDiscoveryService() { // 使用MainActivity的静态上下文 var context = MainActivity.AppContext; _mediaRouteSelector = new MediaRouteSelector.Builder() .AddControlCategory(CastMediaControlIntent.CategoryForCast("My Reciver ID Here")) // 替换为实际的Cast接收器应用ID .Build(); _mediaRouterCallback = new MediaRouterCallback(this); _mediaRouter = MediaRouter.GetInstance(context); _mediaRouter.AddCallback(_mediaRouteSelector, _mediaRouterCallback, MediaRouter.CallbackFlagRequestDiscovery); } // 实现设备发现逻辑 public Task<IEnumerable<string>> GetAvailableDevicesAsync() { return Task.FromResult(_deviceNames.AsEnumerable()); } public async Task ConnectToDeviceAsync(string deviceName) { // 连接到设备 } private class MediaRouterCallback : MediaRouter.Callback { private readonly DeviceDiscoveryService _service; public MediaRouterCallback(DeviceDiscoveryService service) { _service = service; } public override void OnRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) { base.OnRouteAdded(router, route); _service._deviceNames.Add(route.Name); AU.Log.Debug("MainActivity", $"Route added: {route.Name}"); // 通知订阅者设备列表已变更 _service.DevicesChanged?.Invoke(_service, EventArgs.Empty); } public override void OnRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) { base.OnRouteRemoved(router, route); _service._deviceNames.Remove(route.Name); } } } }
主活动代码
using Android.App; using Android.Content; using Android.Content.PM; using Android.Gms.Cast; using Android.Gms.Cast.Framework; using Android.Gms.Tasks; using Android.OS; using Android.Util; using AndroidX.MediaRouter.Media; using Java.Util.Concurrent; using MauiApp3.Platforms.Android.Services; using System.Threading.Tasks; namespace MauiApp3 { [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { //private MediaRouter _mediaRouter; //private MediaRouteSelector _mediaRouteSelector; //private MyMediaRouterCallback _mediaRouterCallback; public static Context AppContext { get; private set; } protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); AppContext = ApplicationContext; InitializeCastContextAsync(ApplicationContext); DependencyService.Register<IDeviceDiscoveryService, DeviceDiscoveryService>(); } private void InitializeCastContextAsync(Context context) { // 定义执行器 IExecutor executor = AsyncTask.ThreadPoolExecutor; // 调用异步方法获取CastContext实例 Android.Gms.Tasks.Task castContextTask = CastContext.GetSharedInstance(context, executor); // 添加完成监听器处理结果 castContextTask.AddOnCompleteListener(new OnCompleteListener(task => { if (task.IsSuccessful) { // CastContext初始化完成 var castContext = (CastContext)task.Result; Log.Debug("MainActivity", "CastContext initialized successfully."); } else { // 处理初始化失败 Exception exception = task.Exception; Log.Error("MainActivity", "Error initializing CastContext: " + exception); } })); } // 处理任务完成的辅助类 public class OnCompleteListener : Java.Lang.Object, IOnCompleteListener { private readonly Action<Android.Gms.Tasks.Task> _onComplete; public OnCompleteListener(Action<Android.Gms.Tasks.Task> onComplete) { _onComplete = onComplete; } public void OnComplete(Android.Gms.Tasks.Task task) { _onComplete?.Invoke(task); } } } }
Cast选项提供类代码
using Android.Content; using Android.Gms.Cast.Framework; using Android.Runtime; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MauiApp3.Platforms.Android { [Register("MauiApp3/CastOptionsProvider")] public class CastOptionsProvider : Java.Lang.Object, IOptionsProvider { public CastOptions GetCastOptions(Context appContext) { var options = new CastOptions.Builder() .SetReceiverApplicationId("My Reciever ID here") .Build(); return options; } public IList<SessionProvider> GetAdditionalSessionProviders(Context appContext) { return null; } } }
内容的提问来源于stack exchange,提问作者Joe Ricklefs
相关产品推荐
相关产品推荐

