Xamarin.Android 如何使“wav”文件成为应用程序的默认推送通知声音?
Posted
技术标签:
【中文标题】Xamarin.Android 如何使“wav”文件成为应用程序的默认推送通知声音?【英文标题】:Xamarin.Android How to make a 'wav' file the default push notification sound for the app? 【发布时间】:2019-01-08 22:22:10 【问题描述】:目标:将自定义 wav 设置为应用的默认推送通知声音。
我有一个 Wave 文件,它位于 android 上的“FilesDir”中。我使用 Xamarin.Essentials FileSystem helper 在 FileSystem.AppDataDirectory 中创建文件,它实际上是一个录音。
在 Debug 中检查 wav 文件的确切位置是:
/data/user/o/com.company.appname/files/fileName.Wav
我需要将此文件设置为我的应用程序的默认推送通知声音。 目前我设置了一个通知通道,但使用的通知声音(并且按预期工作)驻留在 res/raw 中。
我怎样才能做到这一点?
似乎我无法将其设为当前位置的默认推送通知声音。我必须将它复制到 Ringtone 文件夹或 res/raw 文件夹,但是我该如何在应用程序运行时动态地执行此操作(将文件复制到可以用作通知声音的相应位置)?是否可以在 APK 内进行文件传输?
这是我在创建推送通知通道时尝试过的,但没有成功:
//Create two notif channels, the urgent channel
// should use a custom wav as notification sound
private void createNotificationChannels()
try
// the urgent channel
var urgentChannelName = GetString(Resource.String.noti_chan_urgent);
var urgentChannelDescription = GetString(Resource.String.noti_chan_urgent_description);
// the informational channel
var infoChannelName = GetString(Resource.String.noti_chan_info);
var infoChannelDescrption = GetString(Resource.String.noti_chan_info_description);
// set the vibration patterns for the channels
long[] urgentVibrationPattern = 100, 30, 100, 30, 100, 200, 200, 30, 200, 30, 200, 200, 100, 30, 100, 30, 100, 100, 30, 100, 30, 100, 200, 200, 30, 200, 30, 200, 200, 100, 30, 100, 30, 100 ;
long[] infoVibrationPattern = 100, 200, 300, 400, 500, 400, 300, 200, 400 ;
// Creating common Audio Attributes for both channels
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
// get path of custom sound recording to use as push notification
var recordingFileDestinationPath = System.IO.Path.Combine(FileSystem.AppDataDirectory, AppConstants.CUSTOM_ALERT_FILENAME);
//**This is where I am trying to create the URI for the custom wav file for notification, which resides in FilesDir**
Android.Net.Uri urgentAlarmUri = Android.Net.Uri.Parse(recordingFileDestinationPath);
Android.Net.Uri infoAlarmUri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
var chan1 = new NotificationChannel(PRIMARY_CHANNEL_ID, urgentChannelName, NotificationImportance.High)
Description = urgentChannelDescription
;
var chan2 = new NotificationChannel(SECONDARY_CHANNEL_ID, infoChannelName, NotificationImportance.Default)
Description = infoChannelDescrption
;
// set the urgent channel properties
chan1.EnableLights(true);
chan1.LightColor = Color.Red;
chan1.SetSound(urgentAlarmUri, alarmAttributes);
chan1.EnableVibration(true);
chan1.SetVibrationPattern(urgentVibrationPattern);
chan1.SetBypassDnd(true);
chan1.LockscreenVisibility = NotificationVisibility.Public;
// set the info channel properties
chan2.EnableLights(true);
chan2.LightColor = Color.Red;
chan2.SetSound(infoAlarmUri, alarmAttributes);
chan2.EnableVibration(true);
chan2.SetVibrationPattern(infoVibrationPattern);
chan2.SetBypassDnd(false);
chan2.LockscreenVisibility = NotificationVisibility.Public;
var manager = (NotificationManager)GetSystemService(NotificationService);
// create chan1 which is the urgent notifications channel
manager.CreateNotificationChannel(chan1);
manager.CreateNotificationChannel(chan2);
catch (Exception ex)
Console.WriteLine(ex.Message);
使用上述代码的紧急频道没有声音。 如果我从 res/raw 加载声音,它工作正常。如果我事先将录音放在 res/raw 中,它可能会起作用,但声音是在运行时自定义录制的......
【问题讨论】:
【参考方案1】:查看适用于 Android 的 FileSystem.AppDataDirectory
的 Xamarin Essentials 源代码,
https://github.com/xamarin/Essentials/blob/master/Xamarin.Essentials/FileSystem/FileSystem.android.cs#L14
您正在将录制的声音文件保存到内部存储(文件目录)。 Files 目录是一个私有目录,只能由您的应用程序访问。用户或操作系统都无法访问此文件。您必须将文件保存在Public External Storage 或Private External Storage 中。这取决于您是否希望 MediaStore 内容提供商可以访问您录制的声音文件。
【讨论】:
你说得对,谢谢你的提示。我有一个可行的解决方案并将其发布在下面。【参考方案2】:我想出了如何做到这一点,并且可能会帮助尝试这样做的人。这是解决方案:
正如@SharpMoibileCode 所述,在使用 Xamarin Essentials 文件系统帮助程序时,特别是在使用路径 FileSystem.AppDataDirectory 保存录制文件时,它会将其保存在 Internal Storage 中。这有一个这样的路径:
/data/user/0/com.company.appname/files/customsoundfilename.wav
为了在运行时自定义频道的推送通知声音,声音文件必须保存到公共外部存储,即Android.OS.Environment.ExternalStorageDirectory 有这样的路径:
/storage/emulated/0/.../
现在需要写入外部存储的权限才能写入/读取外部存储。因此需要将这些添加到清单中:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
但这还不够。必须在像这样访问外部存储之前询问权限(在此处使用 NuGet 插件 Current Activity for Android 项目来获取当前活动):
var currentActivity = CrossCurrentActivity.Current.Activity;
int requestCode=1;
ActivityCompat.RequestPermissions(currentActivity, new string[]
Manifest.Permission.ReadExternalStorage,
Manifest.Permission.WriteExternalStorage
, requestCode);
如果授予权限,则继续并将文件复制到外部存储:
var recordingFileExternalPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, AppConstants.CUSTOM_ALERT_FILENAME);
if (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.WriteExternalStorage) == (int)Permission.Granted)
try
if (File.Exists(recordingFileExternalPath))
File.Delete(recordingFileExternalPath);
File.Copy(filePath, recordingFileExternalPath);
catch (Exception ex)
Console.WriteLine(ex.Message);
else
UserDialogs.Instance.Alert("Permission to write to External Storage not approved, cannot save settings.", "Permission Denied", "Ok");
现在终于将上面复制的声音设置为频道的通知:
try
// the urgent channel
var urgentChannelName = GetString(Resource.String.noti_chan_urgent);
var urgentChannelDescription = GetString(Resource.String.noti_chan_urgent_description);
// set the vibration patterns for the channels
long[] urgentVibrationPattern = 100, 30, 100, 30, 100, 200, 200, 30, 200, 30, 200, 200, 100, 30, 100, 30, 100, 100, 30, 100, 30, 100, 200, 200, 30, 200, 30, 200, 200, 100, 30, 100, 30, 100 ;
// Creating an Audio Attribute
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Speech)
.SetUsage(AudioUsageKind.Notification).Build();
// Create the uri for the alarm file
var recordingFileDestinationPath = System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, AppConstants.CUSTOM_ALERT_FILENAME);
Android.Net.Uri urgentAlarmUri = Android.Net.Uri.Parse(recordingFileDestinationPath);
var chan1 = new NotificationChannel(PRIMARY_CHANNEL_ID, urgentChannelName, NotificationImportance.High)
Description = urgentChannelDescription
;
// set the urgent channel properties
chan1.EnableLights(true);
chan1.LightColor = Color.Red;
chan1.SetSound(urgentAlarmUri, alarmAttributes);
chan1.EnableVibration(true);
chan1.SetVibrationPattern(urgentVibrationPattern);
chan1.SetBypassDnd(true);
chan1.LockscreenVisibility = NotificationVisibility.Public;
var manager = (NotificationManager)GetSystemService(NotificationService);
// create chan1 which is the urgent notifications channel
manager.CreateNotificationChannel(chan1);
catch (Exception ex)
Console.WriteLine(ex.Message);
【讨论】:
以上是关于Xamarin.Android 如何使“wav”文件成为应用程序的默认推送通知声音?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法将 NAudio.Lame 与 Xamarin (Android/iOS) 应用程序一起使用?
如何使为 API 22 设计的 Android 应用程序与 API21 兼容
我可以在不使用gradle的情况下使用Xamarin.Android中的Android数据绑定库吗?不是MVVM for dotnet