这曾经用来录制声音,以便用于推送通知频道的自定义声音。现在不再了。 请更改什么,为什么这将不再起作用,当收到通知时没有声音?
为了将录制的声音用于推送通知,我曾经将其复制到外部存储中,这样可以在运行时从中访问它:
外部路径的路径是这样的:
/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);
}
}
答案 0 :(得分:1)
为使用户能够更好地控制文件并限制文件混乱,默认情况下,面向Android 10(API级别29)及更高版本的应用将获得对外部存储设备(或范围存储)的作用域访问。此类应用只能看到其特定于应用的目录(使用Context.getExternalFilesDir()
访问)和特定类型的媒体。除非您的应用程序需要访问不在应用程序特定目录或MediaStore
中的文件,否则最好使用作用域存储。您可以参考Manage scoped external storage access。
如果您不想更改,则希望坚持以前所做的事情。
对于Android Q,您可以尝试将android:requestLegacyExternalStorage="true"
添加到清单中的<application>
元素中。