C# 播放类似于电话铃声的通知音

C# 播放类似于电话铃声的通知音,c#,xamarin.forms,push-notification,xamarin.android,xamarin.ios,C#,Xamarin.forms,Push Notification,Xamarin.android,Xamarin.ios,我正在用Xamarin.Forms构建一个原型,它向安装在其他设备上的同一应用程序发送推送通知。我正在使用OneSignal库。 一切都很完美。推送通知由一个设备发送,其他设备正确接收。应用程序是在前台还是在后台。 当推送通知到达其他设备时,我会在HandleNotificationReceived中捕获它,并呼叫播放铃声的服务。 当推送通知到达其他设备,并且应用程序位于前台时,一切都会正常工作。但是,当它到达其他设备,并且应用程序处于后台时,只有推送通知到达,但铃声不会播放。 当我试图在后台运

我正在用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创建的原型中,消息以默认通知铃声接收。这个只播放一次声音。我能解释得更清楚些吗?我还在学英语。这是不可能的,通知只能播放一次声音。