mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-20 04:03:26 +01:00
Uses UTIs to determine whether apps are installed or not
AltStore now inserts an app-specific UTI when resigning apps, and it periodically checks whether that app has been deleted by checking whether UTTypeCopyDeclaration returns nil for the same app-specific UTI.
This commit is contained in:
@@ -18,6 +18,7 @@ public extension Bundle
|
|||||||
public static let appGroups = "ALTAppGroups"
|
public static let appGroups = "ALTAppGroups"
|
||||||
|
|
||||||
public static let urlTypes = "CFBundleURLTypes"
|
public static let urlTypes = "CFBundleURLTypes"
|
||||||
|
public static let exportedUTIs = "UTExportedTypeDeclarations"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import UserNotifications
|
import UserNotifications
|
||||||
|
import MobileCoreServices
|
||||||
|
|
||||||
import AltSign
|
import AltSign
|
||||||
import AltKit
|
import AltKit
|
||||||
@@ -55,16 +56,19 @@ extension AppManager
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
let installedApps = try context.fetch(fetchRequest)
|
let installedApps = try context.fetch(fetchRequest)
|
||||||
for app in installedApps where app.storeApp != nil
|
for app in installedApps
|
||||||
{
|
{
|
||||||
|
let uti = UTTypeCopyDeclaration(app.installedAppUTI as CFString)?.takeRetainedValue() as NSDictionary?
|
||||||
|
|
||||||
if app.bundleIdentifier == StoreApp.altstoreAppID
|
if app.bundleIdentifier == StoreApp.altstoreAppID
|
||||||
{
|
{
|
||||||
self.scheduleExpirationWarningLocalNotification(for: app)
|
self.scheduleExpirationWarningLocalNotification(for: app)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if !UIApplication.shared.canOpenURL(app.openAppURL)
|
if uti == nil
|
||||||
{
|
{
|
||||||
|
// This UTI is not declared by any apps, which means this app has been deleted by the user.
|
||||||
context.delete(app)
|
context.delete(app)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,12 @@ extension InstalledApp
|
|||||||
return directoryURL
|
return directoryURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class func installedAppUTI(forBundleIdentifier bundleIdentifier: String) -> String
|
||||||
|
{
|
||||||
|
let installedAppUTI = "io.altstore.Installed." + bundleIdentifier
|
||||||
|
return installedAppUTI
|
||||||
|
}
|
||||||
|
|
||||||
var directoryURL: URL {
|
var directoryURL: URL {
|
||||||
return InstalledApp.directoryURL(for: self)
|
return InstalledApp.directoryURL(for: self)
|
||||||
}
|
}
|
||||||
@@ -198,4 +204,8 @@ extension InstalledApp
|
|||||||
var refreshedIPAURL: URL {
|
var refreshedIPAURL: URL {
|
||||||
return InstalledApp.refreshedIPAURL(for: self)
|
return InstalledApp.refreshedIPAURL(for: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var installedAppUTI: String {
|
||||||
|
return InstalledApp.installedAppUTI(forBundleIdentifier: self.resignedBundleIdentifier)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -372,6 +372,17 @@ private extension ResignAppOperation
|
|||||||
infoDictionary[Bundle.Info.appGroups] = appGroups
|
infoDictionary[Bundle.Info.appGroups] = appGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add app-specific exported UTI so we can check later if this app (extension) is installed or not.
|
||||||
|
let installedAppUTI = ["UTTypeConformsTo": [],
|
||||||
|
"UTTypeDescription": "AltStore Installed App",
|
||||||
|
"UTTypeIconFiles": [],
|
||||||
|
"UTTypeIdentifier": InstalledApp.installedAppUTI(forBundleIdentifier: profile.bundleIdentifier),
|
||||||
|
"UTTypeTagSpecification": [:]] as [String : Any]
|
||||||
|
|
||||||
|
var exportedUTIs = infoDictionary[Bundle.Info.exportedUTIs] as? [[String: Any]] ?? []
|
||||||
|
exportedUTIs.append(installedAppUTI)
|
||||||
|
infoDictionary[Bundle.Info.exportedUTIs] = exportedUTIs
|
||||||
|
|
||||||
try (infoDictionary as NSDictionary).write(to: bundle.infoPlistURL)
|
try (infoDictionary as NSDictionary).write(to: bundle.infoPlistURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user