我正在 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;
}
}
}
APPDELEGATE
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 ###################
}
}
}
INFO.PLIST