Xamarin Android前台FCM推送点击致SQLite数据丢失求助
问题诊断与解决方案
你的问题分为两个核心关联点:前台FCM通知跳转错误和SQLite数据丢失/无法读取,二者大概率是因为多进程启动冲突引发的连锁问题,以下分步骤逐一解决:
一、修复FCM前台通知跳转至SISActivity的问题
后台状态下系统会自动处理click_action参数,但前台接收FCM通知时,必须手动构建通知并指定跳转的PendingIntent,不能完全依赖默认参数逻辑。具体操作:
- 在你的
FirebaseMessagingService子类中,重写OnMessageReceived方法,针对前台状态自定义通知跳转:
public override void OnMessageReceived(RemoteMessage message) { base.OnMessageReceived(message); // 先判断应用是否处于前台(可以通过Activity生命周期回调实现状态跟踪) if (AppState.IsForeground) { var intent = new Intent(this, typeof(SISActivity)); // 添加标志确保复用现有进程的Activity,避免启动新进程 intent.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop | ActivityFlags.NewTask); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable); // 构建自定义通知 var notificationBuilder = new NotificationCompat.Builder(this, "你的通知渠道ID") .SetContentTitle(message.GetNotification().Title) .SetContentText(message.GetNotification().Body) .SetSmallIcon(Resource.Drawable.ic_notification) .SetContentIntent(pendingIntent) .SetAutoCancel(true); var notificationManager = NotificationManager.FromContext(this); notificationManager.Notify(0, notificationBuilder.Build()); } else { // 后台状态可沿用系统默认处理逻辑 base.OnMessageReceived(message); } }
- 修正
SISActivity的IntentFilter配置,避免Action冲突:
// 建议加上包名前缀,防止与其他应用的Action重名 [IntentFilter(new[] { "com.yourpackage.SISActivity" }, Categories = new[] { Intent.CategoryDefault })] public class SISActivity : AppCompatActivity { // 你的页面逻辑代码 }
注意:FCM通知里的
click_action参数值要和上面的Action完全一致,比如com.yourpackage.SISActivity,不能只用简单的SISActivity。
二、解决SQLite数据丢失/无法读取的问题
数据丢失的核心原因是前台点击通知启动了新的应用进程,新进程中重复初始化数据库时引发了数据冲突或重置。解决方法:
- 确保SQLite连接单例化:你的
GetConnection方法每次都创建新连接,多连接同时操作会导致数据锁或丢失,改为单例模式:
private static SQLiteAsyncConnection _instance; private static readonly object _lockObj = new object(); public static SQLiteAsyncConnection GetConnection() { lock (_lockObj) { if (_instance == null) { try { var sqlDbFileName = "edTheSIS.db3"; var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal); var path = System.IO.Path.Combine(documentsPath, sqlDbFileName); _instance = new SQLiteAsyncConnection(path); } catch (Exception ex) { Toast.MakeText(Application.Context, "Something went wrong", ToastLength.Short).Show(); var objLog = new LogService(); objLog.MobileLog(ex, SISConst.UserName); } } return _instance; } }
- 避免表创建时的数据重置:
CreateTableAsync如果遇到实体结构变更,可能会重建表导致数据丢失,明确指定只创建不存在的表:
// 添加CreateFlags.None确保仅当表不存在时才创建 await _conn.CreateTableAsync<LoggedInUser>(CreateFlags.None);
三、SQLite数据库恢复方法
如果数据已经丢失,可以尝试以下恢复途径:
- 从设备文件系统提取备份:通过Android Studio的Device File Explorer,导航到
/data/data/你的应用包名/files/edTheSIS.db3,如果开启了Android自动备份,可查看/data/data/你的应用包名/backup目录下的备份文件,替换当前数据库。 - 应用内部备份恢复:如果你的应用有内部备份功能,直接从备份文件导入数据库。
- 手动修复损坏的数据库:将当前数据库导出到电脑,用SQLite可视化工具(如SQLiteStudio)打开,检查是否有残留数据,修复后再导回设备。
内容的提问来源于stack exchange,提问作者Arvind Chourasiya
相关产品推荐
相关产品推荐

