Xamarin.Android如何使“ wav”文件成为应用程序的默认推送通知声音?

时间:2019-01-08 22:22:10

标签: c# push-notification xamarin.android

目标:将自定义wav设置为应用的默认推送通知声音。

我有一个Wave文件,该文件位于Android的“ FilesDir”中。我使用Xamarin.Essentials FileSystem助手在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中,则可能会起作用,但是声音会在运行时自定义录制...

2 个答案:

答案 0 :(得分:1)

查看适用于Android的FileSystem.AppDataDirectory的Xamarin Essentials源代码,

https://github.com/xamarin/Essentials/blob/master/Xamarin.Essentials/FileSystem/FileSystem.android.cs#L14

您要将录制的声音文件保存到内部存储(文件目录)。 Files目录是专用目录,只能由您的应用程序访问。用户或操作系统都无法访问该文件。您必须将文件保存在Public External StoragePrivate External Storage中。这取决于您是否希望MediaStore内容提供商访问录制的声音文件。

答案 1 :(得分:0)

我想出了怎么做,可能会帮助尝试这样做的人。解决方法如下:

如@SharpMoibileCode所述,在使用Xamarin Essentials文件系统助手时,尤其是在使用路径 FileSystem.AppDataDirectory 保存记录时,它将保存在内部存储中。它的路径是这样的:

  

/data/user/0/com.company.appname/files/customsoundfilename.wav

为了在运行时自定义频道的“推送通知”声音,声音文件必须保存到公共外部存储,即 Android.OS.Environment.ExternalStorageDirectory < / strong>,其路径如下:

  

/ storage / emulated / 0 /.../

现在需要写外部存储的权限,才能对外部存储进行写/读。因此,需要将这些添加到清单中:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

但是还不够。像这样访问外部存储之前,必须先征得许可(在此处使用NuGet插件,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);
            }
        }