.NET MAUI 中创建录音机和播放器应用 (转)
前言
在本博客中,你将了解如何在 .NET MAUI 中开发录音机和播放器。音频播放器将录制和播放音频文件。
此应用程序可以在Android和iOS上部署和使用。
预览
以下是该录音机和播放录音的应用程序屏幕截图。
先决条件
IDE: VisualStudio 2022
支持的平台:Android 和 IOS
支持的操作系统:Android(7.0 及以上)和 iOS(v12 及以上)
步骤1:在两个平台中添加所需的权限。
要录制音频并将其保存在设备中,应用程序必须访问设备的音频输入和存储。为此,需要授予以下权限:
- RECORD_AUDIO
- READ_EXTERNAL_STORAGE
- WRITE_EXTERNAL_STORAGE
注意:在iOS中,您无法添加存储权限。在选中和请求时,它将始终返回"已授予"。
在 Android 中,将以下代码添加到 AndroidManifest.xml 文件中。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
在 iOS 中,将以下代码添加到 Info.plist 文件中。
<key>NSMicrophoneUsageDescription</key>
<string>The audio recorder app wants to use your microphone to record audio.</string>
步骤2:创建用于录制和播放音频的服务。
NET MAUI 没有能够直接使用的录制和播放音频功能。因此,必须在本机平台中创建用于录制和播放音频文件的服务。
在创建服务类之前,请创建用于调用本机方法的接口。
请参考以下代码。
public interface IAudioPlayer
{
void PlayAudio(string filePath);
void Pause();
void Stop();
string GetCurrentPlayTime();
bool CheckFinishedPlayingAudio();
}
public interface IRecordAudio
{
void StartRecord();
string StopRecord();
void PauseRecord();
void ResetRecord();
}
然后,创建服务以在两个平台上录制和播放音频。
安卓录音机服务
参考以下方法和属性来创建适用于 Android 的录音机服务:
- 创建 MediaRecorder 类的实例,该实例将用于录制音频.
- SetAudioSource(): 指定用于捕获音频输入的硬件设备.
- SetOutputFile(): 指定输出音频文件的名称.
- Prepare(): 初始化录音机.
- Start(): 开始录制音频.
- Reset(): 丢弃录制的音频并重置录音机.
- Pause(): 将录制暂停在当前运行位置.
- Resume(): 从暂停位置恢复录制.
- Stop(): 停止录音.
请参考以下代码。
public class RecordAudio : IRecordAudio
{
#region Fields
private MediaRecorder mediaRecorder;
private string storagePath;
private bool isRecordStarted = false;
#endregion
#region Methods
public void StartRecord()
{
if (mediaRecorder == null)
{
SetAudioFilePath();
mediaRecorder = new MediaRecorder();
mediaRecorder.Reset();
mediaRecorder.SetAudioSource(AudioSource.Mic);
mediaRecorder.SetOutputFormat(OutputFormat.AacAdts);
mediaRecorder.SetAudioEncoder(AudioEncoder.Aac);
mediaRecorder.SetOutputFile(storagePath);
mediaRecorder.Prepare();
mediaRecorder.Start();
}
else
{
mediaRecorder.Resume();
}
isRecordStarted = true;
}
public void PauseRecord()
{
if (mediaRecorder == null)
{
return;
}
mediaRecorder.Pause();
isRecordStarted = false;
}
public void ResetRecord()
{
if (mediaRecorder != null)
{
mediaRecorder.Resume();
mediaRecorder.Reset();
}
mediaRecorder = null;
isRecordStarted = false;
}
public string StopRecord()
{
if (mediaRecorder == null)
{
return string.Empty;
}
mediaRecorder.Resume();
mediaRecorder.Stop();
mediaRecorder = null;
isRecordStarted = false;
return storagePath;
}
private void SetAudioFilePath()
{
string fileName = "/Record_" + DateTime.UtcNow.ToString("ddMMM_hhmmss") + ".mp3";
var path = Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
storagePath = path + fileName;
Directory.CreateDirectory(path);
}
#endregion
}
适用于 iOS 的录音机服务
现在,使用AVAudioRecorder为iOS平台创建录音机服务:
- 在尝试录制之前初始化音频会话。
- 指定录制文件格式和保存录制内容的位置。记录格式被指定为 NSDictionary 中的条目,其中包含两个包含格式键和值的 NSObject 数组。
- 准备好开始录制音频时调用 Record 方法。
- 完成录制后,在录制器上调用 Stop() 方法。
请参考以下代码。
public class RecordAudio : IRecordAudio
{
AVAudioRecorder recorder;
NSUrl url;
NSError error;
NSDictionary settings;
string audioFilePath;
public RecordAudio()
{
InitializeAudioSession();
}
private bool InitializeAudioSession()
{
var audioSession = AVAudioSession.SharedInstance();
var err = audioSession.SetCategory(AVAudioSessionCategory.PlayAndRecord);
if (err != null)
{
Console.WriteLine("audioSession: {0}", err);
return false;
}
err = audioSession.SetActive(true);
if (err != null)
{
Console.WriteLine("audioSession: {0}", err);
return false;
}
return false;
}
public void PauseRecord()
{
recorder.Pause();
}
public void ResetRecord()
{
recorder.Dispose();
recorder = null;
}
public void StartRecord()
{
if (recorder == null)
{
string fileName = "/Record_" + DateTime.UtcNow.ToString("ddMMM_hhmmss") + ".wav";
var docuFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
audioFilePath = docuFolder + fileName;
url = NSUrl.FromFilename(audioFilePath);
NSObject[] values = new NSObject[]
{
NSNumber.FromFloat(44100.0f),
NSNumber.FromInt32((int)AudioToolbox.AudioFormatType.LinearPCM),
NSNumber.FromInt32(2),
NSNumber.FromInt32(16),
NSNumber.FromBoolean(false),
NSNumber.FromBoolean(false)
};
NSObject[] key = new NSObject[]
{
AVAudioSettings.AVSampleRateKey,
AVAudioSettings.AVFormatIDKey,
AVAudioSettings.AVNumberOfChannelsKey,
AVAudioSettings.AVLinearPCMBitDepthKey,
AVAudioSettings.AVLinearPCMIsBigEndianKey,
AVAudioSettings.AVLinearPCMIsFloatKey
};
settings = NSDictionary.FromObjectsAndKeys(values, key);
recorder = AVAudioRecorder.Create(url, new AudioSettings(settings), out error);
recorder.PrepareToRecord();
recorder.Record();
}
else
{
recorder.Record();
}
}
public string StopRecord()
{
if (recorder == null)
{
return string.Empty;
}
recorder.Stop();
recorder = null;
return audioFilePath;
}
}
现在,来实现一个音频播放器服务,用于在两个平台上播放录制的音频。
适用于安卓的音频播放器服务
请按照以下步骤创建适用于 Android 的音频播放服务:
- 创建 MediaPlayer 类的实例以播放音频文件。
- 通过 SetDataSource 方法将音频文件的文件路径提供给媒体播放器实例。
- 设置数据源后,通过调用 Prepare 方法准备媒体播放器。
- 准备好媒体播放器后,使用 Start 方法开始播放音频。
请参考以下代码。
public class AudioPlayer : IAudioPlayer
{
#region Fields
private MediaPlayer _mediaPlayer;
private int currentPositionLength = 0;
private bool isPrepared;
private bool isCompleted;
#endregion
#region Methods
public void PlayAudio(string filePath)
{
if (_mediaPlayer != null && !_mediaPlayer.IsPlaying)
{
_mediaPlayer.SeekTo(currentPositionLength);
currentPositionLength = 0;
_mediaPlayer.Start();
}
else if (_mediaPlayer == null || !_mediaPlayer.IsPlaying)
{
try
{
isCompleted = false;
_mediaPlayer = new MediaPlayer();
_mediaPlayer.SetDataSource(filePath);
_mediaPlayer.SetAudioStreamType(Stream.Music);
_mediaPlayer.PrepareAsync();
_mediaPlayer.Prepared += (sender, args) =>
{
isPrepared = true;
_mediaPlayer.Start();
};
_mediaPlayer.Completion += (sender, args) =>
{
isCompleted = true;
};
}
catch (Exception e)
{
_mediaPlayer = null;
}
}
}
public void Pause()
{
if (_mediaPlayer != null && _mediaPlayer.IsPlaying)
{
_mediaPlayer.Pause();
currentPositionLength = _mediaPlayer.CurrentPosition;
}
}
public void Stop()
{
if (_mediaPlayer != null)
{
if (isPrepared)
{
_mediaPlayer.Stop();
_mediaPlayer.Release();
isPrepared = false;
}
isCompleted = false;
_mediaPlayer = null;
}
}
public string GetCurrentPlayTime()
{
if (_mediaPlayer != null)
{
var positionTimeSeconds =
double.Parse(_mediaPlayer.CurrentPosition.ToString());
positionTimeSeconds = positionTimeSeconds / 1000;
TimeSpan currentTime = TimeSpan.FromSeconds(positionTimeSeconds);
string currentPlayTime = string.Format("{0:mm\\:ss}", currentTime);
return currentPlayTime;
}
return null;
}
public bool CheckFinishedPlayingAudio()
{
return isCompleted;
}
#endregion
}
适用于 iOS 的音频播放器服务
使用 AVPlayer 类在 iOS 中创建音频播放服务:
- 将音频文件配置为通过 AVPlayerItem 内置类播放。
- 调用 Play 方法以开始播放音频。
请参考以下代码。
public class AudioPlayer : IAudioPlayer
{
AVPlayer _player;
NSObject notificationHandle;
NSUrl url;
private bool isFinishedPlaying;
private bool isPlaying;
public bool IsPlaying
{
get { return isPlaying; }
set
{
if (_player.Rate == 1 && _player.Error == null)
isPlaying = true;
else
isPlaying = false;
}
}
public AudioPlayer()
{
RegisterNotification();
}
~AudioPlayer()
{
UnregisterNotification();
}
public void PlayAudio(string filePath)
{
isFinishedPlaying = false;
if (_player == null)
{
url = NSUrl.FromString(filePath);
AVPlayerItem avPlayerItem = new AVPlayerItem(URL);
_player = new AVPlayer(avPlayerItem);
_player.AutomaticallyWaitsToMinimizeStalling = false;
_player.Volume = 1;
_player.Play();
IsPlaying = true;
isFinishedPlaying = false;
}
else if (_player != null && !IsPlaying)
{
_player.Play();
IsPlaying = true;
isFinishedPlaying = false;
}
}
public void Pause()
{
if (_player != null && IsPlaying)
{
_player.Pause();
IsPlaying = false;
}
}
public void Stop()
{
if (_player != null)
{
_player.Dispose();
IsPlaying = false;
_player = null;
}
}
public string GetCurrentPlayTime()
{
if (_player != null)
{
var positionTimeSeconds = _player.CurrentTime.Seconds;
TimeSpan currentTime = TimeSpan.FromSeconds(positionTimeSeconds);
string currentPlayTime = string.Format("{0:mm\\:ss}", currentTime);
return currentPlayTime;
}
return null;
}
public bool CheckFinishedPlayingAudio()
{
return isFinishedPlaying;
}
private void RegisterNotification()
{
notificationHandle = NSNotificationCenter.DefaultCenter.AddObserver(AVPlayerItem.DidPlayToEndTimeNotification, HandleNotification);
}
private void UnregisterNotification()
{
NSNotificationCenter.DefaultCenter.RemoveObserver(notificationHandle);
}
private void HandleNotification(NSNotification notification)
{
isFinishedPlaying = true;
Stop();
}
}
步骤3:创建模型。
创建一个模型类以在列表中显示录制的音频文件。请参考以下代码。
public class Audio : INotifyPropertyChanged
{
#region Private
private bool isPlayVisible;
private bool isPauseVisible;
private string currentAudioPostion;
#endregion
#region Constructor
public Audio()
{
IsPlayVisible = true;
}
#endregion
#region Properties
public string AudioName { get; set; }
public string AudioURL { get; set; }
public string Caption { get; set; }
public bool IsPlayVisible
{
get { return isPlayVisible; }
set
{
isPlayVisible = value;
OnPropertyChanged();
IsPauseVisble = !value;
}
}
public bool IsPauseVisble
{
get { return isPauseVisible; }
set { isPauseVisible = value; OnPropertyChanged(); }
}
public string CurrentAudioPosition
{
get { return currentAudioPostion; }
set
{
if (string.IsNullOrEmpty(currentAudioPostion))
{
currentAudioPostion = string.Format("{0:mm\\:ss}", new TimeSpan());
}
else
{
currentAudioPostion = value;
}
OnPropertyChanged();
}
}
#endregion
}
在代码中,属性可以显示播放音频时间。
步骤4:创建 UI。
这里将创建一个简单的UI,用于显示录制的音频文件和录制音频。为此,这里使用 Syncfusion 的 ListView for .NET MAUI。安装 .NET MAUI 列表视图 NuGet 包,然后将其包含在应用程序中。
以下 XAML 代码将在 Syncfusion 的 .NET MAUI 列表视图控件中显示录制的音频。
<syncfusion:SfListView
x:Name="AudioList"
Grid.Row="0"
Grid.ColumnSpan="2"
Margin="0,8"
IsVisible="true"
ItemsSource="{Binding Audios}"
SelectionMode="None">
<syncfusion:SfListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid
x:Name="PlayAudioGrid"
Margin="0,4,0,12"
BackgroundColor="Transparent"
HeightRequest="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Button
Grid.Column="0"
Padding="0"
BackgroundColor="Transparent"
Command="{Binding Path=BindingContext.PlayAudioCommand, Source={x:Reference mainPage}}"
CommandParameter="{Binding .}"
FontFamily="AudioIconFonts"
FontSize="22"
IsVisible="{Binding IsPlayVisible}"
Text=""
TextColor="Black" />
<Button
Grid.Column="0"
Padding="0"
BackgroundColor="Transparent"
BorderColor="LightGray"
Command="{Binding Path=BindingContext.PauseAudioCommand, Source={x:Reference mainPage}}"
CommandParameter="{Binding .}"
FontFamily="AudioIconFonts"
FontSize="22"
IsVisible="{Binding IsPauseVisble}"
Text=""
TextColor="Black" />
<Label
Grid.Column="1"
FontSize="14"
Text="{Binding AudioName}"
TextColor="Black"
VerticalTextAlignment="Center" />
<Label
Grid.Column="2"
Margin="0,0,12,0"
FontSize="14"
IsVisible="{Binding IsPauseVisble}"
Text="{Binding CurrentAudioPosition}"
TextColor="Black"
VerticalTextAlignment="Center" />
<Button
Grid.Column="3"
BackgroundColor="Transparent"
Command="{Binding Path=BindingContext.DeleteCommand, Source={x:Reference mainPage}}"
CommandParameter="{Binding}"
FontFamily="AudioIconFonts"
FontSize="20"
Text=""
TextColor="Red" />
</Grid>
</ViewCell>
</DataTemplate>
</syncfusion:SfListView.ItemTemplate>
</syncfusion:SfListView>
以下 XAML 代码用于设计用于录制音频的 UI。
<!-- Timer Label -->
<StackLayout
Grid.Row="2"
Grid.ColumnSpan="2"
Margin="0,0,0,32"
VerticalOptions="End">
<Label
FontSize="14"
HorizontalTextAlignment="Center"
IsVisible="{Binding IsRecordingAudio}"
Text="Recording…"
TextColor="#7D898F" />
<Label
FontSize="60"
HorizontalTextAlignment="Center"
IsVisible="{Binding IsRecordingAudio}"
Text="{Binding TimerLabel}"
TextColor="Black" />
</StackLayout>
<!-- Button Setup -->
<Grid
Grid.Row="3"
Grid.ColumnSpan="2"
ColumnSpacing="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Retry -->
<Grid Grid.Column="0" RowDefinitions="auto,auto">
<Button
Grid.Row="0"
BackgroundColor="LightGray"
BorderColor="#5F49FF"
BorderWidth="1"
Command="{Binding ResetCommand}"
CornerRadius="25"
FontFamily="AudioIconFonts"
FontSize="22"
HeightRequest="50"
IsEnabled="{Binding IsRecordingAudio}"
Text=""
TextColor="#5F49FF"
WidthRequest="50">
<Button.Triggers>
<DataTrigger
Binding="{Binding IsRecordingAudio}"
TargetType="Button"
Value="False">
<Setter Property="TextColor" Value="Gray" />
<Setter Property="BorderColor" Value="Gray" />
</DataTrigger>
</Button.Triggers>
</Button>
<Label
Grid.Row="1"
HorizontalOptions="Center"
Text="Retry" />
</Grid>
<!-- Play -->
<Grid
Grid.Column="1"
HorizontalOptions="CenterAndExpand"
RowDefinitions="auto,auto">
<!-- Record Button -->
<Button
Grid.Row="0"
BackgroundColor="Red"
BorderColor="Red"
BorderWidth="1"
Command="{Binding RecordCommand}"
CornerRadius="25"
FontFamily="AudioIconFonts"
FontSize="22"
HeightRequest="50"
IsVisible="{Binding IsRecordButtonVisible}"
Text=""
TextColor="White"
WidthRequest="50" />
<Label
Grid.Row="1"
HorizontalOptions="Center"
IsVisible="{Binding IsRecordButtonVisible}"
Text="Record" />
<!-- Pause Button -->
<Button
Grid.Row="0"
BackgroundColor="Green"
BorderColor="Green"
BorderWidth="1"
Command="{Binding PauseCommand}"
CornerRadius="25"
FontFamily="AudioIconFonts"
FontSize="22"
HeightRequest="50"
IsVisible="{Binding IsPauseButtonVisible}"
Text=""
TextColor="White"
WidthRequest="50" />
<Label
Grid.Row="1"
HorizontalOptions="Center"
IsVisible="{Binding IsPauseButtonVisible}"
Text="Pause" />
<!-- Resume Button -->
<Button
Grid.Row="0"
BackgroundColor="Red"
BorderColor="Red"
BorderWidth="1"
Command="{Binding RecordCommand}"
CornerRadius="25"
FontFamily="AudioIconFonts"
FontSize="22"
HeightRequest="50"
IsVisible="{Binding IsResumeButtonVisible}"
Text=""
TextColor="White"
WidthRequest="50" />
<Label
Grid.Row="1"
HorizontalOptions="Center"
IsVisible="{Binding IsResumeButtonVisible}"
Text="Resume" />
</Grid>
<!-- Stop -->
<Grid Grid.Column="2" RowDefinitions="auto,auto">
<Button
Grid.Row="0"
BackgroundColor="LightGray"
BorderColor="#5F49FF"
BorderWidth="1"
Command="{Binding StopCommand}"
CornerRadius="25"
FontFamily="AudioIconFonts"
FontSize="22"
HeightRequest="50"
IsEnabled="{Binding IsRecordingAudio}"
Text=""
TextColor="#5F49FF"
WidthRequest="50">
<Button.Triggers>
<DataTrigger
Binding="{Binding IsRecordingAudio}"
TargetType="Button"
Value="False">
<Setter Property="TextColor" Value="Gray" />
<Setter Property="BorderColor" Value="Gray" />
</DataTrigger>
</Button.Triggers>
</Button>
<Label
Grid.Row="1"
HorizontalOptions="Center"
Text="Stop" />
</Grid>
</Grid>
步骤 5:注册依赖项注入以访问构造函数中的对象。
依赖关系注入是对象(客户端)接收依赖于它的其他对象(服务)的一种方式。若要了解有关在 .NET MAUI 中使用依赖项注入的详细信息.
请参阅以下代码以注册依赖项注入服务。首先,必须添加必要的服务。然后,可以直接访问所需类构造函数中的对象。因此才可以在视图模型中访问 AudioPlayerService 和 RecordAudioService 对象。
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
fonts.AddFont("AudioIconFonts.ttf", "AudioIconFonts");
});
#if ANDROID || IOS
builder.Services.AddTransient<IAudioPlayerService, AudioPlayerService>();
builder.Services.AddTransient<IRecordAudioService, RecordAudioService>();
#endif
builder.Services.AddTransient<MainPage>();
builder.Services.AddTransient<AppShell>();
builder.ConfigureSyncfusionListView();
return builder.Build();
}
步骤6:创建视图模型。
这里遵循 MVVM(模型-视图-视图模型)结构来开发该应用程序。
因此,需要创建一个用于录制和播放音频的视图模型(MainPageViewModel.cs)文件。
在 ViewModel 中,生成一个音频集合来绑定录制音频的数据。
ViewModel 类中的属性
recordTime,playTimer:播放或录制音频时UI中使用的计时器属性。
IsRecordingAudio: 控制重置和停止选项的可见性。
IsPauseButtonVisible:控制 UI 中“暂停”按钮的可见性。
IsRecordButtonVisible:控制“录制”按钮的可见性。
IsResumeButtonVisible:控制“恢复”按钮的可见性。
audios:要在列表视图中显示的所有录制音频文件的集合。
recordAudioService,audioPlayerService:这些接口属性调用特定于本机平台的代码。
下面的代码示例演示录音机。
使用以下代码启动录制器。必须调用依赖服务方法 recordAudio.StartRecord() 来启动记录器。
只有授予权限,才能启动记录器。
private async void StartRecording()
{
if (!IsRecordingAudio)
{
var permissionStatus = await RequestandCheckPermission();
if (permissionStatus == PermissionStatus.Granted)
{
IsRecordingAudio = true;
IsPauseButtonVisible = true;
recordAudio.StartRecord();
IsRecordButtonVisible = false;
isRecord = true;
timerValue = new TimeSpan(0, 0, -1);
recordTimer.Start();
}
else
{
IsRecordingAudio = false;
IsPauseButtonVisible = false;
}
}
else
{
ResumeRecording();
}
}
使用 recordAudio.PauseRecord() 平台特定的方法暂停录制器。
private void PauseRecording()
{
isRecord = false;
IsPauseButtonVisible = false;
IsResumeButtonVisible = true;
recordAudio.PauseRecord();
}
以下方法用于从暂停位置继续录制。
private void ResumeRecording()
{
recordAudio.StartRecord();
IsResumeButtonVisible = false;
IsPauseButtonVisible = true;
isRecord = true;
}
使用以下代码重置记录器并从初始位置启动它。使用特定于平台的代码 recordAudio.ResetRecord() 重置录制器。
private void ResetRecording()
{
recordAudio.ResetRecord();
timerValue = new TimeSpan();
TimerLabel = string.Format("{0:mm\\:ss}", timerValue);
IsRecordingAudio = false;
IsPauseButtonVisible = false;
IsResumeButtonVisible = false;
StartRecording();
}
若要停止录制器,请使用特定于平台的代码 recordAudio.StopRecord()。
private async void StopRecording()
{
IsPauseButtonVisible = false;
IsResumeButtonVisible = false;
IsRecordingAudio = false;
IsRecordButtonVisible = true;
timerValue = new TimeSpan();
recordTimer.Stop();
RecentAudioFilePath = recordAudio.StopRecord();
await App.Current.MainPage.DisplayAlert("Alert", "Audio has been recorded", "Ok");
TimerLabel = string.Format("{0:mm\\:ss}", timerValue);
SendRecording();
}
private void SendRecording()
{
Audio recordedFile = new Audio() { AudioURL = RecentAudioFilePath };
if (recordedFile != null)
{
recordedFile.AudioName = Path.GetFileName(RecentAudioFilePath);
Audios.Insert(0, recordedFile);
}
}
以下代码用于获取录制权限
public async Task<PermissionStatus> RequestandCheckPermission()
{
PermissionStatus status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
if (status != PermissionStatus.Granted)
await Permissions.RequestAsync<Permissions.StorageWrite>();
status = await Permissions.CheckStatusAsync<Permissions.Microphone>();
if (status != PermissionStatus.Granted)
await Permissions.RequestAsync<Permissions.Microphone>();
PermissionStatus storagePermission = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
PermissionStatus microPhonePermission = await Permissions.CheckStatusAsync<Permissions.Microphone>();
if (storagePermission == PermissionStatus.Granted && microPhonePermission == PermissionStatus.Granted)
{
return PermissionStatus.Granted;
}
return PermissionStatus.Denied;
}
下面的代码示例演示音频播放器。
调用特定于平台的方法 audioPlayer.PlayAudio(audioFilePath) 来播放音频。
private void StartPlayingAudio(object obj)
{
if (audioFile != null && audioFile != (Audio)obj)
{
AudioFile.IsPlayVisible = true;
StopAudio();
}
if (obj is Audio)
{
audioFile = (Audio)obj;
audioFile.IsPlayVisible = false;
string audioFilePath = AudioFile.AudioURL;
audioPlayer.PlayAudio(audioFilePath);
SetCurrentAudioPosition();
}
}
使用以下方法通过特定于平台的方法 audioPlayer.Pause() 暂停音频。
private void PauseAudio(object obj)
{
if (obj is Audio)
{
var audiophile = (Audio)obj;
audioFile.IsPlayVisible = true;
audioPlayer.Pause();
}
}
使用方法audioPlayer.Stop() 停止以下代码中的音频。
public void StopAudio()
{
if (AudioFile != null)
{
audioPlayer.Stop();
playTimer.Stop();
}
}
使用以下代码获取音频的当前位置并将其显示在 UI 中。
private void SetCurrentAudioPosition()
{
playTimer.Interval = new TimeSpan(0, 0, 0, 0, 250);
playTimer.Tick += (s, e) =>
{
if (AudioFile != null)
{
AudioFile.CurrentAudioPosition = audioPlayer.GetCurrentPlayTime();
bool isAudioCompleted = audioPlayer.CheckFinishedPlayingAudio();
if (isAudioCompleted)
{
AudioFile.IsPlayVisible = true;
playTimer.Stop();
}
}
};
playTimer.Start();
}
参考
1.Android:
Android Audio
2.iOS:
AVAudioPlayer Class
AVAudioRecorder Class
资源
有关更多详细信息,请参阅 GitHub 项目 .NET MAUI Audio Recorder and Player