You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Maui中MediaRouteButton实现问题求助

.NET Maui 8中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:58:14