Xamarin.Android无法在Android 10(Q)中将录制的自定义声音用于推送通知

时间:2019-10-08 05:00:41

标签: android xamarin push-notification

这曾经用来录制声音,以便用于推送通知频道的自定义声音。现在不再了。 请更改什么,为什么这将不再起作用,当收到通知时没有声音?

为了将录制的声音用于推送通知,我曾经将其复制到外部存储中,这样可以在运行时从中访问它:

外部路径的路径是这样的:

  

/storage/emulated/0/customNotificationSoundRecording.wav

这是完整的代码,首先记录声音:

private async Task RecordAudio()
        {
            buttonSave.IsEnabled = false;
            try
            {
                if (!recorder.IsRecording)
                {                
                    buttonRecord.IsEnabled = false;
                    buttonPlay.IsEnabled = false;               

                    // only if ios
                    if (Device.RuntimePlatform == Device.iOS)
                        DependencyService.Get<IAudioService>().PrepareRecording();


                    Increment = 1 / (double)AppConstants.MAX_RECORD_TIME;
                    Set_Timer();

                    var recordTask = await recorder.StartRecording();

                    buttonRecord.Text = "Stop";
                    buttonRecord.IsEnabled = true;

                    // get the recorded file
                    var recordedAudioFile = await recordTask;
                    // isRecording = false;                  

                    if (recordedAudioFile != null)
                    {
                        // first save the file from cache to AppData
                        var recordingFileDestinationPath = Path.Combine(FileSystem.AppDataDirectory, AppConstants.CUSTOM_ALERT_FILENAME);                     

                        //if (File.Exists(recordingFileDestinationPath))
                        if (CustomAlertSoundExists(recordingFileDestinationPath))
                        {
                            File.Delete(recordingFileDestinationPath);
                        }

                        File.Copy(recordedAudioFile, recordingFileDestinationPath);                     

                        Preferences.Set(AppConstants.CUSTOM_RECORDING_EXISTS_KEY, true);

                        if (Device.RuntimePlatform == Device.iOS)
                        {
                            DependencyService.Get<IGroupUserPrefs>().SetBoolValueForKey("isCustomAlert", true);
                        }

                        buttonSave.IsEnabled = true;
                    }

                    if (secondsElapsed >= AppConstants.MAX_RECORD_TIME)
                    {
                        Preferences.Set(AppConstants.RECORDING_LENGTH_SECONDS_KEY, secondsElapsed);
                        secondsElapsed = 0;
                        Reset_Timer();
                    }

                    buttonRecord.Text = "Record";
                    buttonPlay.IsEnabled = true;

                }
                else // stop button clicked
                {                                  

                    buttonRecord.IsEnabled = false;

                    await recorder.StopRecording();
                    buttonSave.IsEnabled = true;

                    // isRecording = false;

                    Reset_Timer();

                    // save last recording length in seconds
                    Preferences.Set(AppConstants.RECORDING_LENGTH_SECONDS_KEY, secondsElapsed);

                    //reset seconds elapsed 
                    secondsElapsed = 0;

                    buttonRecord.IsEnabled = true;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

然后将录音复制到外部存储,以前是该录音可用于发布通知声音的唯一位置:

public async void CopyRecordingToExternalStorage(string filePath)
        {
            var recordingFileExternalPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, AppConstants.CUSTOM_ALERT_FILENAME);

             // made some other attempts with different paths.
            // var recordingFileExternalPath = Path.Combine(FileSystem.AppDataDirectory, AppConstants.CUSTOM_ALERT_FILENAME);
            //var recordingFileExternalPath = Path.Combine(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryAlarms).AbsolutePath, AppConstants.CUSTOM_ALERT_FILENAME);

            var storageStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Plugin.Permissions.Abstractions.Permission.Storage);

            if (storageStatus != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
            {
                var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Plugin.Permissions.Abstractions.Permission.Storage });
                storageStatus = results[Plugin.Permissions.Abstractions.Permission.Storage];
            }

            if (storageStatus == Plugin.Permissions.Abstractions.PermissionStatus.Granted)
            {
                try
                {
                    if (File.Exists(recordingFileExternalPath))  // if file exists already in external storage
                    {
                        File.Delete(recordingFileExternalPath); // erase the file
                    }

                    File.Copy(filePath, recordingFileExternalPath); // and overwrite with new one
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            else
            {
                UserDialogs.Instance.Alert("Permission to write to External Storage denied, cannot save settings.", "Permission Denied", "Ok");
            }             
        }

然后我将创建一个具有以下声音的通道:

private void createCustomNotificationChannel()
        {
            try
            {
                // the custom channel
                var urgentChannelName = GetString(Resource.String.noti_chan_custom);
                var customChannelDescription = GetString(Resource.String.noti_chan_custom_description);

                long[] customVibrationPattern = { 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.Sonification)
                    .SetUsage(AudioUsageKind.Notification).Build();

                var alarmSourcePath = System.IO.Path.Combine(Android.OS.Environment.ExternalStorageDirectory.Path, AppConstants.CUSTOM_ALERT_FILENAME);

                 // also tried here with other paths
                // var alarmSourcePath = Path.Combine(FileSystem.AppDataDirectory, AppConstants.CUSTOM_ALERT_FILENAME);
                // var alarmSourcePath = System.IO.Path.Combine(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryAlarms).AbsolutePath, AppConstants.CUSTOM_ALERT_FILENAME);

                var urgentAlarmUri = Android.Net.Uri.Parse(alarmSourcePath);

                // checking here if file exists after voice recording and
                //  the bool is true
                bool soundFileExists = File.Exists(alarmSourcePath);

                var chan3 = new NotificationChannel(TERTIARY_CHANNEL_ID, urgentChannelName, NotificationImportance.High)
                {
                    Description = customChannelDescription
                };

                // set the urgent channel properties
                chan3.EnableLights(true);
                chan3.LightColor = Android.Graphics.Color.Red;
                chan3.SetSound(urgentAlarmUri, alarmAttributes);
                chan3.EnableVibration(true);
                chan3.SetVibrationPattern(customVibrationPattern);
                chan3.SetBypassDnd(true);
                chan3.LockscreenVisibility = NotificationVisibility.Public;

                var manager = (NotificationManager)GetSystemService(NotificationService);

                // create chan1  which is the urgent notifications channel
                manager.CreateNotificationChannel(chan3);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

1 个答案:

答案 0 :(得分:1)

为使用户能够更好地控制文件并限制文件混乱,默认情况下,面向Android 10(API级别29)及更高版本的应用将获得对外部存储设备(或范围存储)的作用域访问。此类应用只能看到其特定于应用的目录(使用Context.getExternalFilesDir()访问)和特定类型的媒体。除非您的应用程序需要访问不在应用程序特定目录或MediaStore中的文件,否则最好使用作用域存储。您可以参考Manage scoped external storage access

如果您不想更改,则希望坚持以前所做的事情。

对于Android Q,您可以尝试将android:requestLegacyExternalStorage="true"添加到清单中的<application>元素中。