Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,49 @@ open class MainApplication : Application(), ReactApplication {

override fun onCreate() {
super.onCreate()

Bugsnag.start(this)


migrateLegacyExperimentalDatabases()

// Initialize MMKV encryption - reads existing key or generates new one
// Must run before React Native starts to avoid race conditions
MMKVKeyManager.initialize(this)

// Load the native entry point for the New Architecture
loadReactNative(this)

ApplicationLifecycleDispatcher.onApplicationCreate(this)
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig)
}

// Renames <=4.72.0 `-experimental.db.db` files.
private fun migrateLegacyExperimentalDatabases() {
val dir = java.io.File(applicationInfo.dataDir)
val legacySuffix = "-experimental.db.db"
val files = dir.listFiles() ?: return
for (legacy in files) {
if (!legacy.isFile || !legacy.name.endsWith(legacySuffix)) {
continue
}
val baseName = legacy.name.removeSuffix(legacySuffix)
val target = java.io.File(dir, "$baseName.db.db")
if (target.exists() && target.length() > 0) {
continue
}
for (suffix in listOf("-wal", "-shm", "-journal", "")) {
val from = java.io.File(dir, legacy.name + suffix)
val to = java.io.File(dir, target.name + suffix)
to.delete()
if (from.exists() && !from.renameTo(to)) {
// Starting with a fresh DB at `target` would strand the legacy data, since later launches skip a non-empty target.
throw IllegalStateException("Failed to migrate ${from.name} to ${to.name}")
}
}
}
}
}
36 changes: 35 additions & 1 deletion ios/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ public class AppDelegate: ExpoAppDelegate {
// This reads existing encryption key or generates a new one for fresh installs
// Must run before Firebase, Bugsnag, and React Native start
MMKVKeyManager.initialize()

FirebaseApp.configure()
Bugsnag.start()
migrateLegacyExperimentalDatabases()
ReplyNotification.configure()
if !VoipRegion.isChina() {
VoipService.voipRegistration()
Expand Down Expand Up @@ -69,6 +70,39 @@ public class AppDelegate: ExpoAppDelegate {
return result
}

// Renames <=4.72.0 `-experimental.db` files; a 0-byte target is one NotificationService created.
private func migrateLegacyExperimentalDatabases() {
let fileManager = FileManager.default
guard let suite = Bundle.main.object(forInfoDictionaryKey: "AppGroupIdentifier") as? String,
let containerURL = fileManager.containerURL(forSecurityApplicationGroupIdentifier: suite),
let files = try? fileManager.contentsOfDirectory(at: containerURL, includingPropertiesForKeys: nil)
else {
return
}
let legacySuffix = "-experimental.db"
for legacy in files {
let name = legacy.lastPathComponent
guard name.hasSuffix(legacySuffix) else { continue }
let target = containerURL.appendingPathComponent(String(name.dropLast(legacySuffix.count)) + ".db")
if let targetSize = (try? fileManager.attributesOfItem(atPath: target.path))?[.size] as? Int, targetSize > 0 {
continue
}
for suffix in ["-wal", "-shm", "-journal", ""] {
let from = URL(fileURLWithPath: legacy.path + suffix)
let to = URL(fileURLWithPath: target.path + suffix)
try? fileManager.removeItem(at: to)
guard fileManager.fileExists(atPath: from.path) else { continue }
do {
try fileManager.moveItem(at: from, to: to)
} catch {
// Starting with a fresh DB at `target` would strand the legacy data, since later launches skip a non-empty target.
Bugsnag.notifyError(error)
fatalError("Failed to migrate \(from.lastPathComponent) to \(to.lastPathComponent): \(error)")
}
}
}
}

// Linking API
public override func application(
_ app: UIApplication,
Expand Down
Loading