使用 Xamarin 使用本地数据库之外的信息在 Android 中显示通知信息
Using information off local database to display notification information in Android using Xamarin
您好,我有一条重复通知。
我希望通知上显示的信息在每次调用时都是本地数据库中的一个新元素。
例如,我的数据库中有一个 table,其中包含 3 个元素,每个索引包含一个唯一的标题和消息字符串。每次调用通知都会调用数据库的新索引,带来新的元素。
SQL数据:
Table: Table Name
Element 1: String 1, String One
Element 2: String 2, String Two
Element 3: String 3, String Three
Android 通知发出:
First notification: Title: 1, Message: One
Second notification: Title: 2, Message: Two
Third notification: Title: 3, Message: Three
如何在每次调用 android 通知时触发 Xamarin cross-platform 方法来遍历我的数据库以获取下一个元素?我如何跟踪下一个通知将在后台显示?
这是我的 android 通知代码:
//used: https://blog.nishanil.com/2014/12/16/scheduled-notifications-in-android-using-alarm-manager/
// new notifications service
public class AndroidReminderService : IReminderService
{
public void Remind(DateTime dateTime, string title, string message)
{
// create alarm intent
Intent alarmIntent = new Intent(Application.Context, typeof(AlarmReceiver));
alarmIntent.PutExtra("message", message);
alarmIntent.PutExtra("title", title);
// specify the broadcast receiver
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
// set the time when app is woken up
// todo: this is where time is adjusted
alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + 5* 1000, 1000, pendingIntent);
}
}
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
const string channelId = "default";
public override void OnReceive(Context context, Intent intent)
{
var message = intent.GetStringExtra("message");
var title = intent.GetStringExtra("title");
var notIntent = new Intent(context, typeof(MainActivity));
var contentIntent = PendingIntent.GetActivity(context, 0, notIntent, PendingIntentFlags.CancelCurrent);
var manager = NotificationManagerCompat.From(context);
var style = new NotificationCompat.BigTextStyle();
style.BigText(message);
// sets notifcation logo
int resourceId;
resourceId = Resource.Drawable.xamarin_logo;
var wearableExtender = new NotificationCompat.WearableExtender().SetBackground(BitmapFactory.DecodeResource(context.Resources, resourceId));
// Generate a notification
// todo look at notification compat properties
var builder = new NotificationCompat.Builder(context, channelId)
.SetContentIntent(contentIntent)
.SetSmallIcon(Resource.Drawable.notification_template_icon_bg)
.SetContentTitle(title)
.SetContentText(message)
.SetStyle(style)
.SetWhen(Java.Lang.JavaSystem.CurrentTimeMillis())
.SetAutoCancel(true)
.Extend(wearableExtender);
var notification = builder.Build();
manager.Notify(0, notification);
}
}
技巧似乎是序列化信息。
我的 OnReceive 执行 SQL 逻辑,然后调用一个函数将其全部序列化,然后我调用下一个提醒
[assembly: Xamarin.Forms.Dependency(typeof(DebugNoti))]
namespace LawsForImpact.Droid
{
class DebugNoti : IDebugNotiServ
{
int _notificationIconId { get; set; }
internal string _randomNumber;
public void LocalNotification(string title, string body, int id, DateTime notifyTime)
{
var intent = CreateIntent(id);
var localNotification = new LocalNotification();
localNotification.Title = title;
localNotification.Body = body;
localNotification.Id = id;
localNotification.NotifyTime = notifyTime;
if (_notificationIconId != 0)
{
localNotification.IconId = _notificationIconId;
}
else
{
localNotification.IconId = Resource.Drawable.notification_template_icon_bg;
}
var serializedNotification = SerializeNotification(localNotification);
intent.PutExtra(DebugScheduledAlarmHandler.LocalNotificationKey, serializedNotification);
Random generator = new Random();
_randomNumber = generator.Next(100000, 999999).ToString("D6");
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
var alarmManager = GetAlarmManager();
// todo change variable of alarm manager
//totalMilliSeconds, repeateForMinute
alarmManager.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, 3000, pendingIntent);
}
public void Cancel(int id)
{
var intent = CreateIntent(id);
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
var alarmManager = GetAlarmManager();
alarmManager.Cancel(pendingIntent);
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.CancelAll();
notificationManager.Cancel(id);
}
public static Intent GetLauncherActivity()
{
var packageName = Application.Context.PackageName;
return Application.Context.PackageManager.GetLaunchIntentForPackage(packageName);
}
private Intent CreateIntent(int id)
{
return new Intent(Application.Context, typeof(DebugScheduledAlarmHandler))
.SetAction("LocalNotifierIntent" + id);
}
private AlarmManager GetAlarmManager()
{
var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
return alarmManager;
}
private string SerializeNotification(LocalNotification notification)
{
var xmlSerializer = new XmlSerializer(notification.GetType());
using (var stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, notification);
return stringWriter.ToString();
}
}
}
[BroadcastReceiver(Enabled = true, Label = "Debug Noti")]
public class DebugScheduledAlarmHandler : BroadcastReceiver
{
public const string LocalNotificationKey = "LocalNotification";
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
const int pendingIntentId = 0;
public const string TitleKey = "title";
public const string MessageKey = "message";
bool channelInitialized = false;
NotificationManager manager;
NotificationCompat.BigTextStyle textStyle = new NotificationCompat.BigTextStyle();
Dictionary<string,int> nQueue = Global.notifQueue;
private SQLiteConnection _sqLiteConnection ;
public override async void OnReceive(Context context, Intent intent)
{
_sqLiteConnection = await Xamarin.Forms.DependencyService.Get<ISQLite>().GetConnection();
var listDataPower = _sqLiteConnection.Table<Power>().ToList();
if (!channelInitialized)
{
CreateNotificationChannel();
}
intent.SetFlags(ActivityFlags.SingleTop);
intent.PutExtra("OpenPage", "SomePage");
var extra = intent.GetStringExtra(LocalNotificationKey);
var notification = DeserializeNotification(extra);
int notiID = notification.Id;
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentIntent(pendingIntent)
.SetContentTitle(listDataPower[notiID].Title)
.SetContentText(listDataPower[notiID].Description)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.notify_panel_notification_icon_bg))
.SetSmallIcon(Resource.Drawable.notify_panel_notification_icon_bg)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
.SetStyle(textStyle);
var resultIntent = DebugNoti.GetLauncherActivity();
resultIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
var stackBuilder = Android.Support.V4.App.TaskStackBuilder.Create(Application.Context);
stackBuilder.AddNextIntent(resultIntent);
Random random = new Random();
int randomNumber = random.Next(9999 - 1000) + 1000;
var resultPendingIntent =
stackBuilder.GetPendingIntent(randomNumber, (int)PendingIntentFlags.Immutable);
builder.SetContentIntent(resultPendingIntent);
// Sending notification
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(randomNumber, builder.Build());
notiID++;
Xamarin.Forms.DependencyService.Get<IDebugNotiServ>().LocalNotification(listDataPower[notiID].Title, listDataPower[notiID].Description, notiID, DateTime.Now);
}
private LocalNotification DeserializeNotification(string notificationString)
{
var xmlSerializer = new XmlSerializer(typeof(LocalNotification));
using (var stringReader = new StringReader(notificationString))
{
var notification = (LocalNotification)xmlSerializer.Deserialize(stringReader);
return notification;
}
}
void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.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;
}
}
}
您好,我有一条重复通知。
我希望通知上显示的信息在每次调用时都是本地数据库中的一个新元素。
例如,我的数据库中有一个 table,其中包含 3 个元素,每个索引包含一个唯一的标题和消息字符串。每次调用通知都会调用数据库的新索引,带来新的元素。
SQL数据:
Table: Table Name
Element 1: String 1, String One
Element 2: String 2, String Two
Element 3: String 3, String Three
Android 通知发出:
First notification: Title: 1, Message: One
Second notification: Title: 2, Message: Two
Third notification: Title: 3, Message: Three
如何在每次调用 android 通知时触发 Xamarin cross-platform 方法来遍历我的数据库以获取下一个元素?我如何跟踪下一个通知将在后台显示?
这是我的 android 通知代码:
//used: https://blog.nishanil.com/2014/12/16/scheduled-notifications-in-android-using-alarm-manager/
// new notifications service
public class AndroidReminderService : IReminderService
{
public void Remind(DateTime dateTime, string title, string message)
{
// create alarm intent
Intent alarmIntent = new Intent(Application.Context, typeof(AlarmReceiver));
alarmIntent.PutExtra("message", message);
alarmIntent.PutExtra("title", title);
// specify the broadcast receiver
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, alarmIntent, PendingIntentFlags.UpdateCurrent);
AlarmManager alarmManager = (AlarmManager)Application.Context.GetSystemService(Context.AlarmService);
// set the time when app is woken up
// todo: this is where time is adjusted
alarmManager.SetInexactRepeating(AlarmType.ElapsedRealtimeWakeup, SystemClock.ElapsedRealtime() + 5* 1000, 1000, pendingIntent);
}
}
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
const string channelId = "default";
public override void OnReceive(Context context, Intent intent)
{
var message = intent.GetStringExtra("message");
var title = intent.GetStringExtra("title");
var notIntent = new Intent(context, typeof(MainActivity));
var contentIntent = PendingIntent.GetActivity(context, 0, notIntent, PendingIntentFlags.CancelCurrent);
var manager = NotificationManagerCompat.From(context);
var style = new NotificationCompat.BigTextStyle();
style.BigText(message);
// sets notifcation logo
int resourceId;
resourceId = Resource.Drawable.xamarin_logo;
var wearableExtender = new NotificationCompat.WearableExtender().SetBackground(BitmapFactory.DecodeResource(context.Resources, resourceId));
// Generate a notification
// todo look at notification compat properties
var builder = new NotificationCompat.Builder(context, channelId)
.SetContentIntent(contentIntent)
.SetSmallIcon(Resource.Drawable.notification_template_icon_bg)
.SetContentTitle(title)
.SetContentText(message)
.SetStyle(style)
.SetWhen(Java.Lang.JavaSystem.CurrentTimeMillis())
.SetAutoCancel(true)
.Extend(wearableExtender);
var notification = builder.Build();
manager.Notify(0, notification);
}
}
技巧似乎是序列化信息。
我的 OnReceive 执行 SQL 逻辑,然后调用一个函数将其全部序列化,然后我调用下一个提醒
[assembly: Xamarin.Forms.Dependency(typeof(DebugNoti))]
namespace LawsForImpact.Droid
{
class DebugNoti : IDebugNotiServ
{
int _notificationIconId { get; set; }
internal string _randomNumber;
public void LocalNotification(string title, string body, int id, DateTime notifyTime)
{
var intent = CreateIntent(id);
var localNotification = new LocalNotification();
localNotification.Title = title;
localNotification.Body = body;
localNotification.Id = id;
localNotification.NotifyTime = notifyTime;
if (_notificationIconId != 0)
{
localNotification.IconId = _notificationIconId;
}
else
{
localNotification.IconId = Resource.Drawable.notification_template_icon_bg;
}
var serializedNotification = SerializeNotification(localNotification);
intent.PutExtra(DebugScheduledAlarmHandler.LocalNotificationKey, serializedNotification);
Random generator = new Random();
_randomNumber = generator.Next(100000, 999999).ToString("D6");
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
var alarmManager = GetAlarmManager();
// todo change variable of alarm manager
//totalMilliSeconds, repeateForMinute
alarmManager.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, 3000, pendingIntent);
}
public void Cancel(int id)
{
var intent = CreateIntent(id);
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
var alarmManager = GetAlarmManager();
alarmManager.Cancel(pendingIntent);
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.CancelAll();
notificationManager.Cancel(id);
}
public static Intent GetLauncherActivity()
{
var packageName = Application.Context.PackageName;
return Application.Context.PackageManager.GetLaunchIntentForPackage(packageName);
}
private Intent CreateIntent(int id)
{
return new Intent(Application.Context, typeof(DebugScheduledAlarmHandler))
.SetAction("LocalNotifierIntent" + id);
}
private AlarmManager GetAlarmManager()
{
var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
return alarmManager;
}
private string SerializeNotification(LocalNotification notification)
{
var xmlSerializer = new XmlSerializer(notification.GetType());
using (var stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, notification);
return stringWriter.ToString();
}
}
}
[BroadcastReceiver(Enabled = true, Label = "Debug Noti")]
public class DebugScheduledAlarmHandler : BroadcastReceiver
{
public const string LocalNotificationKey = "LocalNotification";
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
const int pendingIntentId = 0;
public const string TitleKey = "title";
public const string MessageKey = "message";
bool channelInitialized = false;
NotificationManager manager;
NotificationCompat.BigTextStyle textStyle = new NotificationCompat.BigTextStyle();
Dictionary<string,int> nQueue = Global.notifQueue;
private SQLiteConnection _sqLiteConnection ;
public override async void OnReceive(Context context, Intent intent)
{
_sqLiteConnection = await Xamarin.Forms.DependencyService.Get<ISQLite>().GetConnection();
var listDataPower = _sqLiteConnection.Table<Power>().ToList();
if (!channelInitialized)
{
CreateNotificationChannel();
}
intent.SetFlags(ActivityFlags.SingleTop);
intent.PutExtra("OpenPage", "SomePage");
var extra = intent.GetStringExtra(LocalNotificationKey);
var notification = DeserializeNotification(extra);
int notiID = notification.Id;
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentIntent(pendingIntent)
.SetContentTitle(listDataPower[notiID].Title)
.SetContentText(listDataPower[notiID].Description)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.notify_panel_notification_icon_bg))
.SetSmallIcon(Resource.Drawable.notify_panel_notification_icon_bg)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
.SetStyle(textStyle);
var resultIntent = DebugNoti.GetLauncherActivity();
resultIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
var stackBuilder = Android.Support.V4.App.TaskStackBuilder.Create(Application.Context);
stackBuilder.AddNextIntent(resultIntent);
Random random = new Random();
int randomNumber = random.Next(9999 - 1000) + 1000;
var resultPendingIntent =
stackBuilder.GetPendingIntent(randomNumber, (int)PendingIntentFlags.Immutable);
builder.SetContentIntent(resultPendingIntent);
// Sending notification
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.Notify(randomNumber, builder.Build());
notiID++;
Xamarin.Forms.DependencyService.Get<IDebugNotiServ>().LocalNotification(listDataPower[notiID].Title, listDataPower[notiID].Description, notiID, DateTime.Now);
}
private LocalNotification DeserializeNotification(string notificationString)
{
var xmlSerializer = new XmlSerializer(typeof(LocalNotification));
using (var stringReader = new StringReader(notificationString))
{
var notification = (LocalNotification)xmlSerializer.Deserialize(stringReader);
return notification;
}
}
void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.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;
}
}
}