Prioritizes app refresh order

Tries to refresh apps that are about to expire first, and then always refreshes AltStore itself last, since refreshing AltStore means that the app will quit.
This commit is contained in:
Riley Testut
2019-06-21 11:20:03 -07:00
parent c096fd02b4
commit 39c84e623a
21 changed files with 1016 additions and 621 deletions

View File

@@ -34,6 +34,7 @@
<entity name="InstalledApp" representedClassName="InstalledApp" syncable="YES">
<attribute name="bundleIdentifier" attributeType="String" syncable="YES"/>
<attribute name="expirationDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="refreshedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
<attribute name="version" attributeType="String" syncable="YES"/>
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="App" inverseName="installedApp" inverseEntity="App" syncable="YES"/>
<uniquenessConstraints>
@@ -57,7 +58,7 @@
<elements>
<element name="Account" positionX="-36" positionY="90" width="128" height="135"/>
<element name="App" positionX="-63" positionY="-18" width="128" height="210"/>
<element name="InstalledApp" positionX="-63" positionY="0" width="128" height="105"/>
<element name="InstalledApp" positionX="-63" positionY="0" width="128" height="120"/>
<element name="Team" positionX="-45" positionY="81" width="128" height="120"/>
</elements>
</model>

View File

@@ -8,6 +8,7 @@
import CoreData
import AltSign
import Roxas
public class DatabaseManager
@@ -120,14 +121,23 @@ private extension DatabaseManager
altStoreApp.version = version
}
if let installedApp = altStoreApp.installedApp
let installedApp: InstalledApp
if let app = altStoreApp.installedApp
{
installedApp.version = version
installedApp = app
}
else
{
let installedApp = InstalledApp(app: altStoreApp, bundleIdentifier: altStoreApp.identifier, expirationDate: Date(), context: context)
installedApp.version = version
installedApp = InstalledApp(app: altStoreApp, bundleIdentifier: altStoreApp.identifier, context: context)
}
installedApp.version = version
if let provisioningProfileURL = Bundle.main.url(forResource: "embedded", withExtension: "mobileprovision"), let provisioningProfile = ALTProvisioningProfile(url: provisioningProfileURL)
{
installedApp.refreshedDate = provisioningProfile.creationDate
installedApp.expirationDate = provisioningProfile.expirationDate
}
do

View File

@@ -16,6 +16,7 @@ class InstalledApp: NSManagedObject, Fetchable
@NSManaged var bundleIdentifier: String
@NSManaged var version: String
@NSManaged var refreshedDate: Date
@NSManaged var expirationDate: Date
/* Relationships */
@@ -26,7 +27,7 @@ class InstalledApp: NSManagedObject, Fetchable
super.init(entity: entity, insertInto: context)
}
init(app: App, bundleIdentifier: String, expirationDate: Date, context: NSManagedObjectContext)
init(app: App, bundleIdentifier: String, context: NSManagedObjectContext)
{
super.init(entity: InstalledApp.entity(), insertInto: context)
@@ -35,7 +36,9 @@ class InstalledApp: NSManagedObject, Fetchable
self.version = app.version
self.bundleIdentifier = bundleIdentifier
self.expirationDate = expirationDate
self.refreshedDate = Date()
self.expirationDate = self.refreshedDate.addingTimeInterval(60 * 60 * 24 * 7) // Rough estimate until we get real values from provisioning profile.
}
}
@@ -45,6 +48,52 @@ extension InstalledApp
{
return NSFetchRequest<InstalledApp>(entityName: "InstalledApp")
}
class func fetchAltStore(in context: NSManagedObjectContext) -> InstalledApp?
{
let predicate = NSPredicate(format: "%K == %@", #keyPath(InstalledApp.app.identifier), App.altstoreAppID)
let altStore = InstalledApp.first(satisfying: predicate, in: context)
return altStore
}
class func fetchAppsForRefreshingAll(in context: NSManagedObjectContext) -> [InstalledApp]
{
let predicate = NSPredicate(format: "%K != %@", #keyPath(InstalledApp.app.identifier), App.altstoreAppID)
var installedApps = InstalledApp.all(satisfying: predicate,
sortedBy: [NSSortDescriptor(keyPath: \InstalledApp.expirationDate, ascending: true)],
in: context)
if let altStoreApp = InstalledApp.fetchAltStore(in: context)
{
// Refresh AltStore last since it causes app to quit.
installedApps.append(altStoreApp)
}
return installedApps
}
class func fetchAppsForBackgroundRefresh(in context: NSManagedObjectContext) -> [InstalledApp]
{
let date = Date().addingTimeInterval(-120)
let predicate = NSPredicate(format: "(%K < %@) AND (%K != %@)",
#keyPath(InstalledApp.refreshedDate), date as NSDate,
#keyPath(InstalledApp.app.identifier), App.altstoreAppID)
var installedApps = InstalledApp.all(satisfying: predicate,
sortedBy: [NSSortDescriptor(keyPath: \InstalledApp.expirationDate, ascending: true)],
in: context)
if let altStoreApp = InstalledApp.fetchAltStore(in: context), altStoreApp.refreshedDate < date
{
// Refresh AltStore last since it causes app to quit.
installedApps.append(altStoreApp)
}
return installedApps
}
}
extension InstalledApp
@@ -67,10 +116,10 @@ extension InstalledApp
return appsDirectoryURL
}
class func ipaURL(for app: App) -> URL
class func fileURL(for app: App) -> URL
{
let ipaURL = self.directoryURL(for: app).appendingPathComponent("App.ipa")
return ipaURL
let appURL = self.directoryURL(for: app).appendingPathComponent("App.app")
return appURL
}
class func refreshedIPAURL(for app: App) -> URL
@@ -79,7 +128,6 @@ extension InstalledApp
return ipaURL
}
class func directoryURL(for app: App) -> URL
{
let directoryURL = InstalledApp.appsDirectoryURL.appendingPathComponent(app.identifier)
@@ -94,8 +142,8 @@ extension InstalledApp
return InstalledApp.directoryURL(for: self.app)
}
var ipaURL: URL {
return InstalledApp.ipaURL(for: self.app)
var fileURL: URL {
return InstalledApp.fileURL(for: self.app)
}
var refreshedIPAURL: URL {