.NET/MAUI中如何通过代码创建使用TextureView的ExoPlayer
在.NET MAUI中创建基于TextureView的ExoPlayer(纯C#实现)
问题说明
需要在.NET MAUI的Android平台上,用纯C#代码实现渲染到TextureView的ExoPlayer(StyledPlayerView),无需依赖XML文件。之前尝试通过XML片段创建IAttributeSet时遇到两个错误:
- XML解析报错:
System.Xml.XmlException: 'android' is an undeclared prefix - 类型转换异常:
Java.Lang.ClassCastException: 'android.util.XmlPullAttributes cannot be cast to android.content.res.XmlBlock$Parser
解决方案1:直接设置SurfaceType(推荐)
无需构造AttributeSet,创建StyledPlayerView后直接调用SetSurfaceType方法指定使用TextureView,代码更简洁:
using Android.Content; using Com.Google.Android.Exoplayer2; using Com.Google.Android.Exoplayer2.UI; using Com.Google.Android.Exoplayer2.Source.Progressive; using Com.Google.Android.Exoplayer2.Upstream; // 获取当前Context(示例:在MAUI自定义ViewHandler中可通过Context属性获取) Context context = Android.App.Application.Context; // 1. 创建StyledPlayerView实例 StyledPlayerView playerView = new StyledPlayerView(context); // 2. 设置SurfaceType为TextureView playerView.SetSurfaceType(PlayerView.SurfaceTypeTextureView); // 3. 初始化ExoPlayer并关联到PlayerView SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).Build(); playerView.Player = player; // 4. 设置播放源(示例:播放网络视频) Uri videoUri = Uri.Parse("https://example.com/your-video.mp4"); DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory(); ProgressiveMediaSource mediaSource = new ProgressiveMediaSource.Factory(dataSourceFactory) .CreateMediaSource(MediaItem.FromUri(videoUri)); player.Prepare(mediaSource); // 5. 将PlayerView添加到布局(示例:在MAUI自定义Handler中赋值给PlatformView) // this.PlatformView = playerView;
解决方案2:纯代码创建IAttributeSet(构造函数传参方式)
若必须通过构造函数的IAttributeSet参数指定SurfaceType,可通过Android原生Xml解析方式创建正确的AttributeSet,避免之前的错误:
using Android.Content; using Android.Content.Res; using Android.Runtime; using Com.Google.Android.Exoplayer2.UI; using Org.Xmlpull.V1; using System.IO; Context context = Android.App.Application.Context; // 构造包含命名空间和surface_type属性的XML字符串 string xml = @"<?xml version=""1.0"" encoding=""utf-8""?> <com.google.android.exoplayer2.ui.StyledPlayerView xmlns:app=""http://schemas.android.com/apk/res-auto"" app:surface_type=""texture_view"" />"; // 使用Android原生XmlPullParser解析XML XmlPullParser parser = Xml.NewPullParser(); parser.SetInput(new StringReader(xml), "utf-8"); parser.NextTag(); // 移动到根节点 // 创建AttributeSet(使用Android的XmlBlock.Parser,避免类型转换异常) using (XmlBlock xmlBlock = new XmlBlock(context.AssetManager, xml, "utf-8")) { using (XmlBlock.Parser xmlParser = xmlBlock.NewParser()) { xmlParser.NextTag(); IAttributeSet attrs = Xml.AsAttributeSet(xmlParser); // 通过构造函数创建StyledPlayerView StyledPlayerView playerView = new StyledPlayerView(context, attrs); // 后续初始化Player等操作同方案1 } }
代码说明
- 方案1利用
PlayerView提供的SetSurfaceType方法直接切换渲染表面,无需处理XML和AttributeSet,是最简便的实现方式。 - 方案2解决了之前的错误:
- XML字符串中声明了ExoPlayer的命名空间
xmlns:app="http://schemas.android.com/apk/res-auto",避免前缀未声明的错误。 - 使用Android原生的
XmlBlock.Parser创建AttributeSet,而非XmlPullAttributes,解决了类型转换异常问题。
- XML字符串中声明了ExoPlayer的命名空间
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

