首页 > 解决方案 > 像电话铃声一样播放通知声音

问题描述

我正在 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;
        }
    }
}

主要活动

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);
        }
    }
}

安卓清单

<?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>

IOS服务

[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 ###################
        }
    }
}

信息列表

信息列表

标签: c#xamarin.formspush-notificationxamarin.androidxamarin.ios

解决方案


推荐阅读