【问题标题】:Is it possible to get information about all apps installed on iPhone?是否可以获得有关 iPhone 上安装的所有应用程序的信息?
【发布时间】:2010-10-07 02:05:42
【问题描述】:

是否可以获得有关已安装在 iPhone/iPod 上的所有应用程序的信息(应用程序图标、应用程序名称、应用程序位置)?

【问题讨论】:

    标签: iphone


    【解决方案1】:

    有一种方法可以检查应用程序是否已安装,但它确实违反了沙盒规则,Apple *可能会拒绝您的应用程序使用它。不过之前App Store里的其他App已经做过了,大家可以试试

    有时您可能想检查设备上是否安装了特定应用,以防您使用需要安装其他应用的自定义 URL 方案(然后您可以灰显/禁用某些按钮)。不幸的是,Apple 显然没有任何功能可以为您检查这个,所以我做了一个。它不会枚举每个应用程序,而是使用 MobileInstallation 缓存,该缓存始终与 SpringBoard 保持同步,并保存所有已安装应用程序的信息字典。尽管您“不应该”访问缓存,但 App Store 应用程序可以读取它。这是我的代码,它至少与 Simulator 2.2.1 完美配合: 代码:

    // Declaration
    BOOL APCheckIfAppInstalled(NSString *bundleIdentifier); // Bundle identifier (eg. com.apple.mobilesafari) used to track apps
    
    // Implementation
    
    BOOL APCheckIfAppInstalled(NSString *bundleIdentifier)
    {
        static NSString *const cacheFileName = @"com.apple.mobile.installation.plist";
        NSString *relativeCachePath = [[@"Library" stringByAppendingPathComponent: @"Caches"] stringByAppendingPathComponent: cacheFileName];
        NSDictionary *cacheDict = nil;
        NSString *path = nil;
        // Loop through all possible paths the cache could be in
        for (short i = 0; 1; i++)
        {
    
            switch (i) {
        case 0: // Jailbroken apps will find the cache here; their home directory is /var/mobile
            path = [NSHomeDirectory() stringByAppendingPathComponent: relativeCachePath];
            break;
        case 1: // App Store apps and Simulator will find the cache here; home (/var/mobile/) is 2 directories above sandbox folder
            path = [[NSHomeDirectory() stringByAppendingPathComponent: @"../.."] stringByAppendingPathComponent: relativeCachePath];
            break;
        case 2: // If the app is anywhere else, default to hardcoded /var/mobile/
            path = [@"/var/mobile" stringByAppendingPathComponent: relativeCachePath];
            break;
        default: // Cache not found (loop not broken)
            return NO;
            break; }
    
            BOOL isDir = NO;
            if ([[NSFileManager defaultManager] fileExistsAtPath: path isDirectory: &isDir] && !isDir) // Ensure that file exists
                cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
    
            if (cacheDict) // If cache is loaded, then break the loop. If the loop is not "broken," it will return NO later (default: case)
                break;
        }
    
        NSDictionary *system = [cacheDict objectForKey: @"System"]; // First check all system (jailbroken) apps
        if ([system objectForKey: bundleIdentifier]) return YES;
        NSDictionary *user = [cacheDict objectForKey: @"User"]; // Then all the user (App Store /var/mobile/Applications) apps
        if ([user objectForKey: bundleIdentifier]) return YES;
    
        // If nothing returned YES already, we'll return NO now
        return NO;
    }
    

    这是一个示例,假设您的应用名为“yourselfmadeapp”并且是应用商店中的一个应用。 代码:

    NSArray *bundles2Check = [NSArray arrayWithObjects: @"com.apple.mobilesafari", @"com.yourcompany.yourselfmadeapp", @"com.blahblah.nonexistent", nil];
    for (NSString *identifier in bundles2Check)
        if (APCheckIfAppInstalled(identifier))
            NSLog(@"App installed: %@", identifier);
        else
            NSLog(@"App not installed: %@", identifier);
    

    日志输出: 代码:

    2009-01-30 12:19:20.250 SomeApp[266:20b] 已安装应用程序: com.apple.mobilesafari 2009-01-30 12:19:20.254 SomeApp[266:20b] 应用程序 安装: com.yourcompany.yourselfmadeapp 2009-01-30 12:19:20.260 SomeApp[266:20b] 未安装应用程序: com.blahblah.不存在

    在使用它之前尝试一下,我认为 Apple 更改了 MobileInstallation.plist 所在的位置,如果您确实更改了它,请在实际设备而不是模拟器上尝试。祝你好运!

    http://www.iphonedevsdk.com/forum/iphone-sdk-development/37103-finding-out-what-apps-installed.html

    PK

    【讨论】:

    • 这篇文章已有 2 年多的历史了,你认为它不会在 iOS 6 上立即运行吗?另外,解释什么是不工作的,仅仅说它不能正常工作是不足以帮助你的。
    • Pavan,你知道应用商店里有什么应用使用这个吗?谢谢!
    • 我想不到;但是,如果任何应用程序有兴趣知道用户的 iDevice 上是否安装了特定应用程序,那么最好的方法是使用 iPhone URL schemes 并且您可以通过执行类似的操作来测试应用程序是否已安装:if ([ourApplication canOpenURL:@"fb://"]) { NSLog(@"facebook installed");}; 等。这会让你知道是否安装了 facebook。
    • 对我来说,iOS7 越狱后所有路径都返回 NO 为什么?我该如何解决这个问题?我需要那种紧迫感
    • ion iOS8 com.apple.mobile.installation.plist 被删除了,替换成什么?
    【解决方案2】:

    当然,您可以在设备越狱时执行此操作,以便您可以伸出沙箱。 您可以通过分析位于每个路径“/var/mobile/Applications/”的每个.app 中的Info.plist 来获取您想要的信息,例如“/var/mobile/Applications// *.app/Info.plist" 这是我的代码。

    - (void)scan
    {
    
        NSString *pathOfApplications = @"/var/mobile/Applications";
    
        NSLog(@"scan begin");
    
        // all applications
        NSArray *arrayOfApplications = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathOfApplications error:nil];
        for (NSString *applicationDir in arrayOfApplications) {
            // path of an application
            NSString *pathOfApplication = [pathOfApplications stringByAppendingPathComponent:applicationDir];
            NSArray *arrayOfSubApplication = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pathOfApplication error:nil];
            // seek for *.app
            for (NSString *applicationSubDir in arrayOfSubApplication) {
                if ([applicationSubDir hasSuffix:@".app"]) {// *.app
                    NSString *path = [pathOfApplication stringByAppendingPathComponent:applicationSubDir];
    
                    path = [path stringByAppendingPathComponent:@"Info.plist"];
    
                    // so you get the Info.plist in the dict
                    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
                    // code to analyzing the dict.
                }
            }
        }
    
        NSLog(@"scan end");
    }
    

    这是 Info.plist 的示例内容。因此,获取您关心的任何键的值。

    {
    BuildMachineOSBuild = 11G63;
    CFBundleDevelopmentRegion = "zh_CN";
    CFBundleDisplayName = "\U4e50\U89c6\U5f71\U89c6HD";
    CFBundleExecutable = LetvIpadClient;
    CFBundleIconFile = "icon.png";
    CFBundleIconFiles =     (
        "icon.png",
        "icon@2x.png"
    );
    CFBundleIdentifier = "com.letv.ipad.hdclient";
    CFBundleInfoDictionaryVersion = "6.0";
    CFBundleName = LetvIpadClient;
    CFBundlePackageType = APPL;
    CFBundleResourceSpecification = "ResourceRules.plist";
    CFBundleShortVersionString = "3.1";
    CFBundleSignature = "????";
    CFBundleSupportedPlatforms =     (
        iPhoneOS
    );
    CFBundleURLTypes =     (
                {
            CFBundleURLName = "m.letv.com";
            CFBundleURLSchemes =             (
                letvIPad
            );
        }
    );
    CFBundleVersion = "3.1";
    DTCompiler = "com.apple.compilers.llvmgcc42";
    DTPlatformBuild = 10A403;
    DTPlatformName = iphoneos;
    DTPlatformVersion = "6.0";
    DTSDKBuild = 10A403;
    DTSDKName = "iphoneos6.0";
    DTXcode = 0450;
    DTXcodeBuild = 4G182;
    LSRequiresIPhoneOS = 0;
    MinimumOSVersion = "4.3";
    UIDeviceFamily =     (
        2
    );
    "UILaunchImageFile~ipad" =     (
        "Default.png",
        "Default@2x.png"
    );
    UIPrerenderedIcon = 1;
    UIStatusBarHidden = 1;
    UISupportedInterfaceOrientations =     (
        UIInterfaceOrientationPortrait,
        UIInterfaceOrientationPortraitUpsideDown,
        UIInterfaceOrientationLandscapeLeft,
        UIInterfaceOrientationLandscapeRight
    );
    "UISupportedInterfaceOrientations~ipad" =     (
        UIInterfaceOrientationLandscapeRight,
        UIInterfaceOrientationLandscapeLeft
    );
    }
    

    【讨论】:

      【解决方案3】:

      在 iPhone 中获取已安装应用程序的另一种方法是调用:

      NSString *rootAppPath = @"/Applications";
      NSArray *listApp = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:rootAppPath error:nil];
      

      您可以在每个应用程序中访问然后阅读他们的字典 Info.plist 以了解有关这些应用程序的更多信息。

      更新:显然,此方法不再起作用(对于 iOS8),因为我们的应用程序没有权限查看 /Applications 的内容

      【讨论】:

      • 没有私有 API,因此必须在 App Store 中接受。
      • 这会返回 a 应用程序列表,而不是正确的应用程序列表。在 Sim 上,它返回主机上的应用程序,在真实硬件上,它看起来像一个默认应用程序列表。
      • 这会返回默认应用列表,而不是通过应用商店安装的应用。
      【解决方案4】:

      试试这个,它甚至可以在非越狱设备上工作

      #include <objc/runtime.h>
      Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
      SEL selector=NSSelectorFromString(@"defaultWorkspace");
      NSObject* workspace = [LSApplicationWorkspace_class performSelector:selector];
      
      SEL selectorALL = NSSelectorFromString(@"allApplications");
      NSLog(@"apps: %@", [workspace performSelector:selectorALL]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-12
        • 2017-10-13
        • 2019-05-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多