我正在學習 Xamarin,并希望為應用程式實作一種方法,以大約每 20 分鐘左右在后臺發出一個 HttpClient 請求,并根據從請求回應中獲得的資料向用戶發送推送通知。我相當有信心這是可能的,但是通過在 Internet 上搜索,我還沒有看到在 Xamarin.Forms 中執行此操作的方法。
uj5u.com熱心網友回復:
這需要針對特定??平臺進行。使用 android 調度請求會更簡單一些,因為這可以通過運行周期性任務和廣播接收器的后臺服務來實作。您可以在此處閱讀有關它的更多資訊https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/和https://docs.microsoft.com/en-us/xamarin/android/應用程式基礎/廣播接收器。
在共享專案中:
public class BackgroundJobManager
{
private int _currentId;
private readonly List<BackgroundJob> _backgroundJobs = new List<BackgroundJob>();
public IReadOnlyList<BackgroundJob> BackgroundJobs => _backgroundJobs;
private int NextId() => Interlocked.Increment(ref _currentId);
public int AddJob(Action action, TimeSpan delay, TimeSpan interval, string description)
{
var nextJobId = NextId();
MessagingCenter.Subscribe<IAlarmReceiver>(this, nextJobId.ToString(), (sender) => action());
_backgroundJobs.Add(new BackgroundJob() { DueTime = delay, Interval = interval, ID = nextJobId });
return nextJobId;
}
public void RemoveJob(int jobId)
{
MessagingCenter.Unsubscribe<IAlarmReceiver>(this, jobId.ToString());
_backgroundJobs.RemoveWhere(job => job.ID == jobId);
}
}
INotificationManager
public interface INotificationManager
{
event EventHandler<NotificationEventArgs> NotificationReceived;
void Initialize();
void SendNotification(string title, string message);
void ReceiveNotification(string title, string message);
}
通知事件引數
public class NotificationEventArgs : System.EventArgs
{
public string Title { get; set; }
public string Message { get; set; }
}
報警接收器
public interface IAlarmReceiver
{
}
在您提出請求的班級中:
private void SetUpBackgroundRequest()
{
Action startBackGroundJob = async () => await MakeYourRequestHere();
_backgroundJobManager.AddJob(startBackGroundJob, TimeSpan.FromSeconds(10), TimeSpan.FromMinutes(20), "Making request");
}
Android 在您的 MainActivity.cs 添加以下內容:
private Intent _serviceIntent;
protected override void OnPause()
{
base.OnPause();
_serviceIntent = new Intent(this, typeof(PeriodicService));
StartService(_serviceIntent);
}
protected override void OnResume()
{
base.OnResume();
if (_serviceIntent != null)
StopService(_serviceIntent);
}
定期服務
[Service]
class PeriodicService : Service
{
private static AlarmHandler alarm = new AlarmHandler();
private readonly BackgroundJobManager _backgroundJobManager = new YourSharedProject.BackgroundJobManager();
public override StartCommandResult OnStartCommand(Intent intent,
StartCommandFlags flags, int startId)
{
foreach(var job in _backgroundJobManager.BackgroundJobs)
{
alarm.SetAlarm(job.DueTime, job.Interval, job.ID);
}
return StartCommandResult.Sticky;
}
public override bool StopService(Intent name)
{
foreach (var job in _backgroundJobManager.BackgroundJobs)
{
alarm.UnsetAlarm(job.ID);
}
return base.StopService(name);
}
public override void OnDestroy()
{
base.OnDestroy();
}
public override IBinder OnBind(Intent intent)
{
return null;
}
}
AndroidNotificationManager
public class AndroidNotificationManager : YourSharedProject.NotificationManager
{
private const string ChannelId = "default";
private const string ChannelName = "Default";
private const string ChannelDescription = "The default channel for notifications.";
public const string TitleKey = "title";
public const string MessageKey = "message";;
private bool channelInitialized = false;
private int messageId = 0;
private int pendingIntentId = 0;
private NotificationManager manager;
public static AndroidNotificationManager Instance { get; private set; }
public AndroidNotificationManager() => Initialize();
public override void Initialize()
{
if (Instance == null)
{
CreateNotificationChannel();
Instance = this;
}
}
public override void SendNotification(string title, string message)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
Show(title, message);
}
public void Show(string title, string message)
{
Interlocked.Increment(ref messageId);
Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId , intent, PendingIntentFlags.UpdateCurrent);
NotificationCompat.BigTextStyle textStyle = new NotificationCompat.BigTextStyle();
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, ChannelId)
.SetContentIntent(pendingIntent)
.SetContentTitle(title)
.SetContentText(message)
.SetStyle(textStyle)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.launchIcon))
.SetSmallIcon(Resource.Drawable.launchIcon)
.SetDefaults((int)NotificationDefaults.All)
.SetAutoCancel(true);
Notification notification = builder.Build();
manager.Notify(messageId, notification);
}
private void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(Context.NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelNameJava = new Java.Lang.String(ChannelName);
var channel = new NotificationChannel(ChannelId, channelNameJava, NotificationImportance.Default)
{
Description = ChannelDescription
};
manager.CreateNotificationChannel(channel);
}
channelInitialized = true;
}
}
報警接收器
[BroadcastReceiver]
class AlarmReciver : BroadcastReceiver, IAlarmReceiver
{
public override void OnReceive(Context context, Intent intent)
{
var id = intent.GetStringExtra("jobId");
MessagingCenter.Send<IAlarmReceiver>(this, id);
}
}
[BroadcastReceiver(Enabled = true, Label = "Local Notifications Broadcast Receiver")]
class AlarmHandler : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
if (intent?.Extras != null)
{
string title = intent.GetStringExtra(View.AndroidNotificationManager.TitleKey);
string message = intent.GetStringExtra(View.AndroidNotificationManager.MessageKey);
View.AndroidNotificationManager manager = View.AndroidNotificationManager.Instance ?? new View.AndroidNotificationManager();
manager.Show(title, message, assignmentId);
}
}
public void SetAlarm(TimeSpan dueTime, TimeSpan interval, int jobId)
{
var alarmIntent = new Intent(Application.Context, typeof(AlarmReciver));
alarmIntent.PutExtra("jobId", jobId.ToString());
var pending = PendingIntent.GetBroadcast(Application.Context,
jobId, alarmIntent, PendingIntentFlags.UpdateCurrent);
var alarmManager = Application.Context.GetSystemService(Context.AlarmService)
.JavaCast<AlarmManager>();
alarmManager.SetRepeating(AlarmType.RtcWakeup, (long)dueTime.TotalMilliseconds,
(long)interval.TotalMilliseconds, pending);
}
public void UnsetAlarm(int jobId)
{
var alarmIntent = new Intent(Application.Context, typeof(AlarmReciver));
var pending = PendingIntent.GetBroadcast(Application.Context,
jobId, alarmIntent, PendingIntentFlags.UpdateCurrent);
var alarmManager = Application.Context.GetSystemService(Context.AlarmService)
.JavaCast<AlarmManager>();
alarmManager.Cancel(pending);
}
}
對于 iOS,它有點復雜。IOS 提供后臺獲取來重繪 非關鍵內容。不可能選擇一個時間間隔,因為 UIApplication.BackgroundFetchIntervalMinimum 是基于很多東西,例如應用程式使用情況、電池壽命等。您仍然希望使用 UIApplication.BackgroundFetchIntervalMinimum盡可能頻繁地獲取內容。另一種方法是使用遠程通知,使用 Apple 推送通知服務 (APN)。此處的資訊和示例https://docs.microsoft.com/en-us/xamarin/ios/app-fundamentals/backgrounding/ios-backgrounding-techniques/updating-an-application-in-the-background。
這兩個平臺的另一個選擇是 Azure,如此處所述https://docs.microsoft.com/en-us/azure/developer/mobile-apps/notification-hubs-backend-service-xamarin-forms
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/481175.html
上一篇:在另一個頁面中顯示條目值
