C# 播放类似于电话铃声的通知音
我正在用Xamarin.Forms构建一个原型,它向安装在其他设备上的同一应用程序发送推送通知。我正在使用OneSignal库。 一切都很完美。推送通知由一个设备发送,其他设备正确接收。应用程序是在前台还是在后台。 当推送通知到达其他设备时,我会在HandleNotificationReceived中捕获它,并呼叫播放铃声的服务。 当推送通知到达其他设备,并且应用程序位于前台时,一切都会正常工作。但是,当它到达其他设备,并且应用程序处于后台时,只有推送通知到达,但铃声不会播放。 当我试图在后台运行一些东西时,我读到了一些限制,我相信我的问题与此有关。 有人能帮我吗? 这是我的密码: 应用程序C# 播放类似于电话铃声的通知音,c#,xamarin.forms,push-notification,xamarin.android,xamarin.ios,C#,Xamarin.forms,Push Notification,Xamarin.android,Xamarin.ios,我正在用Xamarin.Forms构建一个原型,它向安装在其他设备上的同一应用程序发送推送通知。我正在使用OneSignal库。 一切都很完美。推送通知由一个设备发送,其他设备正确接收。应用程序是在前台还是在后台。 当推送通知到达其他设备时,我会在HandleNotificationReceived中捕获它,并呼叫播放铃声的服务。 当推送通知到达其他设备,并且应用程序位于前台时,一切都会正常工作。但是,当它到达其他设备,并且应用程序处于后台时,只有推送通知到达,但铃声不会播放。 当我试图在后台运
namespace SaferProject
{
public partial class App : Application
{
public App()
{
InitializeComponent();
var page = new NavigationPage(new Views.MainMenu());
MainPage = page;
IPlaySoundService playSoundService;
playSoundService = DependencyService.Get<IPlaySoundService>();
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE, LOG_LEVEL.NONE);
OneSignal.Current.StartInit("417d7b75-ed42-4ca5-aed3-42612d260235")
.Settings(new Dictionary<string, bool>() {
{ IOSSettings.kOSSettingsKeyAutoPrompt, false },
{ IOSSettings.kOSSettingsKeyInAppLaunchURL, false } })
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.HandleNotificationOpened((result) =>
{
if (playSoundService.GetServiceStatus())
{
playSoundService.StopSystemSound();
}
Debug.WriteLine("HandleNotificationOpened: {0}", result.notification.payload.body);
})
//################ Here I call the PlaySystemSound service###############
//################ Here I call the PlaySystemSound service###############
//################ Here I call the PlaySystemSound service###############
.HandleNotificationReceived((notification) =>
{
playSoundService.PlaySystemSound();
DeviceDisplay.KeepScreenOn = true;
Debug.WriteLine("HandleNotificationReceived: {0}", notification.payload.body);
})
//########################################################################
//########################################################################
//########################################################################
.HandleInAppMessageClicked((action) =>
{
// Example IAM click handling for IAM elements
Debug.WriteLine("HandledInAppMessageClicked: {0}", action.clickName);
})
.EndInit();
// The promptForPushNotificationsWithUserResponse function will show the iOS push notification prompt. We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 7)
OneSignal.Current.RegisterForPushNotifications();
}
protected override void OnStart()
{
IPlaySoundService playSoundService;
playSoundService = DependencyService.Get<IPlaySoundService>();
if (playSoundService.GetServiceStatus())
{
playSoundService.StopSystemSound();
}
//Handle when your app sleeps
Task.Run(async () => { await SaferProjectService.GetInstance().GetOut(UserManager.GetLogUser()); });
}
protected override void OnSleep()
{
//Handle when your app sleeps
Task.Run(async()=> { await SaferProjectService.GetInstance().GetOut(UserManager.GetLogUser()); });
}
protected override void OnResume()
{
//Handle when your app resumes
Task.Run(async () => { await SaferProjectService.GetInstance().GetIn(UserManager.GetLogUser()); });
}
}
}
安卓服务
namespace SaferProject.Services
{
public interface IPlaySoundService
{
Task PlaySystemSound();
Task StopSystemSound();
void SetServiceStatus(bool isPlaying);
bool GetServiceStatus();
}
}
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace SaferProject.Droid.Services
{
[Activity(Label = "PlaySoundService", NoHistory = true, Theme = "@style/MyTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class PlaySoundService : IPlaySoundService
{
private static PlaySoundService _instance;
readonly Ringtone _rt;
bool IsPlaying;
public static PlaySoundService GetInstance()
{
if (_instance == null)
{
_instance = new PlaySoundService();
}
return _instance;
}
public PlaySoundService()
{
AudioManager am = (AudioManager)Application.Context.GetSystemService(Context.AudioService);
if (!am.RingerMode.Equals(2))
{
am.RingerMode = RingerMode.Normal;
//am.SetVibrateSetting(VibrateType.Ringer, VibrateSetting.On);
}
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Ringtone);
_rt = RingtoneManager.GetRingtone(MainActivity.instance.ApplicationContext, uri);
}
public Task PlaySystemSound()
{
_rt.Play();
Vibration.Vibrate(500);
SetServiceStatus(true);
return Task.CompletedTask;
}
public Task StopSystemSound()
{
Vibration.Cancel();
_rt.Stop();
SetServiceStatus(false);
return Task.CompletedTask;
}
public void SetServiceStatus(bool isPlaying)
{
IsPlaying = isPlaying;
}
public bool GetServiceStatus()
{
return IsPlaying;
}
}
}
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace SaferProject.iOS.Services
{
public class PlaySoundService : IPlaySoundService
{
private static PlaySoundService _instance;
readonly SystemSound Sound;
bool IsPlaying;
public static PlaySoundService GetInstance()
{
if (_instance == null)
{
_instance = new PlaySoundService();
}
return _instance;
}
public PlaySoundService()
{
AVAudioSession audioSession = AVAudioSession.SharedInstance();
NSError error;
audioSession.OverrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, out error);
Sound = new SystemSound(1151); //1304 (Alarm)
}
public Task PlaySystemSound()
{
Sound.PlaySystemSound();
Vibration.Vibrate(500);
SetServiceStatus(true);
return Task.CompletedTask;
}
public Task StopSystemSound()
{
Sound.Close();
Vibration.Cancel();
SetServiceStatus(false);
return Task.CompletedTask;
}
public void SetServiceStatus(bool isPlaying)
{
IsPlaying = isPlaying;
}
public bool GetServiceStatus()
{
return IsPlaying;
}
}
}
namespace SaferProject.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
//return base.FinishedLaunching(app, options);
base.FinishedLaunching(app, options);
//################ Início OneSignal #################
// Remove this method to stop OneSignal Debugging
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE, LOG_LEVEL.NONE);
OneSignal.Current.StartInit("417d7b75-ed42-4ca5-aed3-42612d260235")
.Settings(new Dictionary<string, bool>() {
{ IOSSettings.kOSSettingsKeyAutoPrompt, false },
{ IOSSettings.kOSSettingsKeyInAppLaunchURL, false } })
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.EndInit();
// The promptForPushNotificationsWithUserResponse function will show the iOS push notification prompt. We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 7)
OneSignal.Current.RegisterForPushNotifications();
return true;
//################# Fim OneSignal ###################
}
}
}
主要活动
namespace SaferProject.Droid
{
[Activity(Label = "SaferProject.Droid", Theme = "@style/MainTheme", MainLauncher = false,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait, LaunchMode = LaunchMode.SingleTop)] //This is what controls orientation
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static MainActivity instance { set; get; }
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
instance = this;
// Radio Button configuration
Xamarin.Forms.Forms.SetFlags(new string[] { "RadioButton_Experimental" });
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
//CreateNotificationFromIntent(Intent); //Local Notification - CRIADO NA MADRUGADA
//################ Início OneSignal #################
// Remove this method to stop OneSignal Debugging
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE, LOG_LEVEL.NONE);
OneSignal.Current.StartInit("417d7b75-ed42-4ca5-aed3-42612d260235")
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.EndInit();
//################# Fim OneSignal ###################
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
ANDROID清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="6" android:versionName="1.2.0" package="br.com.safertechnology.saferproject" android:installLocation="auto">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
<permission android:name="$br.com.safertechnology.saferproject.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application android:label="Safer" android:icon="@mipmap/ic_launcher" android:fullBackupContent="@xml/auto_backup_rules">
<receiver android:name="com.onesignal.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="$br.com.safertechnology.saferproject" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="$com.aolserra.sirene.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
</manifest>
APPDELEGATE
namespace SaferProject.Services
{
public interface IPlaySoundService
{
Task PlaySystemSound();
Task StopSystemSound();
void SetServiceStatus(bool isPlaying);
bool GetServiceStatus();
}
}
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace SaferProject.Droid.Services
{
[Activity(Label = "PlaySoundService", NoHistory = true, Theme = "@style/MyTheme", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class PlaySoundService : IPlaySoundService
{
private static PlaySoundService _instance;
readonly Ringtone _rt;
bool IsPlaying;
public static PlaySoundService GetInstance()
{
if (_instance == null)
{
_instance = new PlaySoundService();
}
return _instance;
}
public PlaySoundService()
{
AudioManager am = (AudioManager)Application.Context.GetSystemService(Context.AudioService);
if (!am.RingerMode.Equals(2))
{
am.RingerMode = RingerMode.Normal;
//am.SetVibrateSetting(VibrateType.Ringer, VibrateSetting.On);
}
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Ringtone);
_rt = RingtoneManager.GetRingtone(MainActivity.instance.ApplicationContext, uri);
}
public Task PlaySystemSound()
{
_rt.Play();
Vibration.Vibrate(500);
SetServiceStatus(true);
return Task.CompletedTask;
}
public Task StopSystemSound()
{
Vibration.Cancel();
_rt.Stop();
SetServiceStatus(false);
return Task.CompletedTask;
}
public void SetServiceStatus(bool isPlaying)
{
IsPlaying = isPlaying;
}
public bool GetServiceStatus()
{
return IsPlaying;
}
}
}
[assembly: Xamarin.Forms.Dependency(typeof(PlaySoundService))]
namespace SaferProject.iOS.Services
{
public class PlaySoundService : IPlaySoundService
{
private static PlaySoundService _instance;
readonly SystemSound Sound;
bool IsPlaying;
public static PlaySoundService GetInstance()
{
if (_instance == null)
{
_instance = new PlaySoundService();
}
return _instance;
}
public PlaySoundService()
{
AVAudioSession audioSession = AVAudioSession.SharedInstance();
NSError error;
audioSession.OverrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, out error);
Sound = new SystemSound(1151); //1304 (Alarm)
}
public Task PlaySystemSound()
{
Sound.PlaySystemSound();
Vibration.Vibrate(500);
SetServiceStatus(true);
return Task.CompletedTask;
}
public Task StopSystemSound()
{
Sound.Close();
Vibration.Cancel();
SetServiceStatus(false);
return Task.CompletedTask;
}
public void SetServiceStatus(bool isPlaying)
{
IsPlaying = isPlaying;
}
public bool GetServiceStatus()
{
return IsPlaying;
}
}
}
namespace SaferProject.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
//return base.FinishedLaunching(app, options);
base.FinishedLaunching(app, options);
//################ Início OneSignal #################
// Remove this method to stop OneSignal Debugging
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE, LOG_LEVEL.NONE);
OneSignal.Current.StartInit("417d7b75-ed42-4ca5-aed3-42612d260235")
.Settings(new Dictionary<string, bool>() {
{ IOSSettings.kOSSettingsKeyAutoPrompt, false },
{ IOSSettings.kOSSettingsKeyInAppLaunchURL, false } })
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.EndInit();
// The promptForPushNotificationsWithUserResponse function will show the iOS push notification prompt. We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 7)
OneSignal.Current.RegisterForPushNotifications();
return true;
//################# Fim OneSignal ###################
}
}
}
namespace SaferProject.iOS
{
//应用程序的UIApplicationLegate。此类负责启动
//应用程序的用户界面,以及对
//来自iOS的应用程序事件。
[注册(“AppDelegate”)]
公共部分类AppDelegate:global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
//当应用程序已加载并准备运行时,将调用此方法
//方法,您应该实例化窗口,将UI加载到其中,然后创建窗口
//看得见。
//
//您有17秒的时间从该方法返回,否则iOS将终止您的应用程序。
//
公共覆盖bool FinishedLaunching(UIApplication应用程序、NSDictionary选项)
{
全局::Xamarin.Forms.Forms.Init();
加载应用程序(新应用程序());
//返回基地。完成发射(应用程序,选项);
基础。完成发射(应用程序,选项);
//################Início OneSignal#################
//删除此方法以停止OneSignal调试
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE,LOG_LEVEL.NONE);
OneSignal.Current.StartInit(“417d7b75-ed42-4ca5-aed3-42612d260235”)
.Settings(新字典(){
{IOSSettings.kossettingskeyayautoprompt,false},
{IOSSettings.kOSSettingsKeyInAppLaunchURL,false})
.InFocusDisplaying(osinfocusdisplayeption.Notification)
.EndInit();
//promptForPushNotificationsWithUserResponse函数将显示iOS推送通知提示。建议删除以下代码,改为使用应用内消息提示通知权限(请参阅步骤7)
OneSignal.Current.RegisterForPushNotifications();
返回true;
//#################Fim OneSignal###################
}
}
}
INFO.PLIST
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="6" android:versionName="1.2.0" package="br.com.safertechnology.saferproject" android:installLocation="auto">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
<permission android:name="$br.com.safertechnology.saferproject.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application android:label="Safer" android:icon="@mipmap/ic_launcher" android:fullBackupContent="@xml/auto_backup_rules">
<receiver android:name="com.onesignal.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="$br.com.safertechnology.saferproject" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="$com.aolserra.sirene.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
</manifest>
我们可以设置
声音
在OneSignal中发送消息时,您是否检查了文档:?谢谢ColeX MSFT,但我可以设置声音文件。但我不能让它像智能手机铃声一样响。我说得对吗?我在文档中没有找到任何类似的内容。您可以从internet下载智能手机呼叫铃
声音文件,并将其添加到xcode项目根目录中,然后发送带有声音的通知:。抱歉,ColeX-MSFT。。。但是我想我不能用英语表达我的想法。我需要通知声音继续循环播放,直到用户点击通知或打开应用程序。在我使用OneSignal创建的原型中,消息以默认通知铃声接收。这个只播放一次声音。我能解释得更清楚些吗?我还在学英语。这是不可能的,通知只能播放一次声音。