【Android Xamarin-使用SQLite时打开计划的通知会停止重复并崩溃】别裁伪体亲风雅,转益多师是汝师。这篇文章主要讲述Android Xamarin-使用SQLite时打开计划的通知会停止重复并崩溃相关的知识,希望能为你提供帮助。
我已经使用SQLite创建了一个具有6个数据库表的Xamarin android应用程序。我实现了重复通知功能,每次调用通知时,该功能都会显示与SQLite表不同的元素。这是通过使应用程序在后台运行并遍历SQL数据以找到要在通知中显示的元素来完成的。如果点击通知,则会打开应用程序,并且通知中显示的信息会显示在应用程序的页面上。
所以我可以做的就是打开我的应用程序并将其设置为显示重复通知。每次触发通知时,通知都会根据通过SQL数据的后台函数显示不同的信息。我退出我的应用程序并清除我最近的应用程序以使其在后台运行。通知和更改信息效果很好。但是,一旦我重新打开该应用程序,通知就会停止触发,稍后当我关闭我的应用程序时,我会收到通知,通知该应用程序已停止响应。
我相信问题来自Android警报服务和SQLite数据连接。即使再次打开应用程序后,如何保持通知不断重复?如果我在最初设置要显示的通知后再也没有打开应用程序,则通知将继续显示而不会出现错误。
这是我的课程,用于设置警报管理器并创建通知
[assembly: Dependency(typeof(LawsForImpact.Droid.AndroidNotificationManager))]
namespace LawsForImpact.Droid
{
[BroadcastReceiver]
public class AndroidNotificationManager : BroadcastReceiver, INotificationManager
{
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
const int pendingIntentId = 0;
public const string LocalNotificationKey = "LocalNotification";
public const string TableKey = "table";
public const string IndexKey = "index";
bool channelInitialized = false;
int messageId = -1;
NotificationManager manager;
public event EventHandler NotificationReceived;
string currentTitle;
int currentIndex;
SavedInformation savedInfo;
public void Initialize()
{
CreateNotificationChannel();
}public int ScheduleNotification(string title, string message)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}messageId++;
// 1 MainActivity intent allows MainActivity to change once notification tapped
Intent intentMain = new Intent(AndroidApp.Context, typeof(MainActivity));
intentMain.PutExtra(TableKey, currentTitle);
intentMain.PutExtra(IndexKey, currentIndex);
PendingIntent pendingIntentMain = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intentMain, PendingIntentFlags.UpdateCurrent);
NotificationCompat.BigTextStyle textStyle = new NotificationCompat.BigTextStyle();
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentIntent(pendingIntentMain)
.SetContentTitle(title)
.SetContentText(message)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.ic_mtrl_chip_checked_circle))
.SetSmallIcon(Resource.Drawable.ic_mtrl_chip_checked_black)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate)
.SetStyle(textStyle);
Random random = new Random();
int randomNumber = random.Next(9999 - 1000) + 1000;
Notification notification = builder.Build();
manager.Notify(randomNumber, notification);
return messageId;
}public void SavedInfo(SerializableDictionary<
string, int>
pickedQueue, int queueIndex, bool randomTog, int repeatInterval)
{
savedInfo = new SavedInformation();
currentTitle = pickedQueue.ElementAt(queueIndex).Key;
savedInfo.QueueOfSaved = pickedQueue;
savedInfo.QueueIndex = queueIndex;
savedInfo.RandomToggle = randomTog;
savedInfo.RepeatInterval = repeatInterval;
LoadData();
RepeatAlarmSet();
}public override void OnReceive(Context context, Intent intent)
{var extra = intent.GetStringExtra(LocalNotificationKey);
var notification = DeserializeNotification(extra);
SerializableDictionary<
string, int>
queue = notification.QueueOfSaved;
var queueIndex = notification.QueueIndex;
var randTog = notification.RandomToggle;
var repInterval = notification.RepeatInterval;
SavedInfo(queue, queueIndex, randTog, repInterval);
}public void RepeatAlarmSet()
{
Intent intent = new Intent(Application.Context, typeof(AndroidNotificationManager));
var serializedNotification = SerializeNotification(savedInfo);
intent.PutExtra(LocalNotificationKey, serializedNotification);
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent);
var alarmManager = GetAlarmManager();
alarmManager.SetExactAndAllowWhileIdle(AlarmType.RtcWakeup, 1000, pendingIntent);
}public void Cancel()
{var intent = new Intent(Application.Context, typeof(AndroidNotificationManager));
var pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.UpdateCurrent);
var alarmManager = GetAlarmManager();
pendingIntent.Cancel();
alarmManager.Cancel(pendingIntent);
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.CancelAll();
}private async void LoadData()
{
SQLiteConnection _sqLiteConnection;
_sqLiteConnection = await Xamarin.Forms.DependencyService.Get<
ISQLite>
().GetConnection();
IEnumerable<
IDataTable>
tableToEnumerable = new List<
IDataTable>
();
List<
IDataTable>
listData;
switch (currentTitle)
{
case "Table1":
tableToEnumerable = _sqLiteConnection.Table<
Table1>
().ToList();
break;
case "Table2":
tableToEnumerable = _sqLiteConnection.Table<
Table2>
().ToList();
break;
case "Table3":
tableToEnumerable = _sqLiteConnection.Table<
Table3>
().ToList();
break;
case "Table4":
tableToEnumerable = _sqLiteConnection.Table<
Table4>
().ToList();
break;
case "Table5":
tableToEnumerable = _sqLiteConnection.Table<
Table5>
().ToList();
break;
case "Table6":
tableToEnumerable = _sqLiteConnection.Table<
Table6>
().ToList();
break;
}
listData = https://www.songbingjia.com/android/tableToEnumerable.ToList();
int index = listData.Count() - savedInfo.QueueOfSaved[currentTitle];
index = index - 1;
currentIndex = index;
// if random enabled
if (savedInfo.RandomToggle)
{
Random random = new Random();
index = random.Next(0, listData.Count());
}//sets all the current notification information
string title = listData[index].Title;
string message = listData[index].Description;
//logic for next notification// subtract the queue int of current notification subject to keep track of next index
savedInfo.QueueOfSaved[currentTitle] = savedInfo.QueueOfSaved[currentTitle] - 1;
// check for index overflow
if (savedInfo.QueueOfSaved[currentTitle] <
0)
{
savedInfo.QueueOfSaved[currentTitle] = listData.Count() - 1;
}// index of next table
savedInfo.QueueIndex = savedInfo.QueueIndex + 1;
// if next table index overflows that means its time to restart the table index and move up the notification index
if (savedInfo.QueueIndex >
= savedInfo.QueueOfSaved.Count)
{
savedInfo.QueueIndex = 0;
}ScheduleNotification(title, message);
}public void ReceiveNotification(string table, int index)
{
var args = new NotificationEventArgs()
{
Table = table,
Index = index,
};
NotificationReceived?.Invoke(null, args);
var notificationManager = NotificationManagerCompat.From(Application.Context);
notificationManager.CancelAll();
}public static Intent GetLauncherActivity()
{var packageName = Application.Context.PackageName;
return Application.Context.PackageManager.GetLaunchIntentForPackage(packageName);
}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;
}private string SerializeNotification(SavedInformation notification)
{var xmlSerializer = new XmlSerializer(notification.GetType());
using (var stringWriter = new StringWriter())
{
xmlSerializer.Serialize(stringWriter, notification);
return stringWriter.ToString();
}
}private SavedInformation DeserializeNotification(string notificationString)
{var xmlSerializer = new XmlSerializer(typeof(SavedInformation));
using (var stringReader = new StringReader(notificationString))
{
var notification = (SavedInformation)xmlSerializer.Deserialize(stringReader);
return notification;
}
}private AlarmManager GetAlarmManager()
{
var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
return alarmManager;
}
}
我相信MainActivity以某种方式参与其中,因为它负责重新启动应用程序的过程。
[Activity(
LaunchMode = LaunchMode.SingleTop,
Label = "LawsForImpact",
Icon = "@mipmap/icon",
Theme = "@style/MainTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
CreateNotificationFromIntent(Intent);
}protected override void OnNewIntent(Intent intent)
{
CreateNotificationFromIntent(intent);
}void CreateNotificationFromIntent(Intent intent)
{
if (intent?.Extras != null)
{
string tableKey = intent.Extras.GetString(AndroidNotificationManager.TableKey);
int indexKey = intent.Extras.GetInt(AndroidNotificationManager.IndexKey);
DependencyService.Get<
INotificationManager>
().ReceiveNotification(tableKey, indexKey);
}
}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);
}
}
答案我在后台进程中加载??SQL数据时遇到的问题。依赖服务引起了该问题。我通过使用Android设备监控器工具并在以下工具的帮助下找到了答案:Xamarin Service and Forms Init
推荐阅读
- 我希望我的Android应用程序将数据同步到MYSQL以用于我的在线ERP
- 禁用插件并使用./gradlew(app:dependencies检查依赖关系树)
- Android 8或更高版本使用Firebase Performance SDK在Android Oreo上崩溃的应用程序
- AppComponent中的ERROR不能用作条目组件
- 构建gradle时出错 - com.google.android.gms(各种其他库正在请求play-services-basement)
- android(fcm在库模块中)
- Azure Bot服务示例AuthenticationBot登录卡无法正常工作(application / vnd.microsoft.card.oauth)
- 在Azure Application Insights中记录机器人数据
- 我是否需要使用azure waf和web app指向站点vpn