2010-10-07 33 views

回答

1

有一種方法來檢查應用程序是否安裝,但是,它確實違反了Sandbox規則,Apple *可能會拒絕您的應用程序使用它。但之前已由App Store中的其他應用完成,因此請隨時嘗試使用

有時您可能需要檢查設備上是否安裝了特定應用,以防您使用自定義URL方案這需要安裝其他應用程序(您可以只是灰色/禁用某些按鈕)。不幸的是,蘋果顯然沒有任何功能來檢查這個,所以我掀起了一個。它並未列舉每一個應用程序,而是使用MobileInstallation緩存,該緩存始終與SpringBoard保持同步,並保存安裝的所有應用程序的Info字典。雖然您不是「應該」訪問緩存,但它可以被App Store應用讀取。這裏是我的代碼至少可與模擬器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]沒有安裝應用程序: 融爲一體。 blahblah.nonexistent

在使用它之前試用一下,我認爲Apple更改了MobileInstallation.plist所在的位置,如果您更改了它,請在實際設備而非模擬器上嘗試。祝你好運!在iPhone

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

PK

+0

我已經在iOS 6測試這一點,它不能正常工作運行。 – 2013-02-08 18:04:20

+0

這篇文章已經超過2年了,你不認爲它會與iOS 6一起工作嗎? 此外,解釋什麼是不工作,只是說它不能正常工作是不足以幫助你。 – Pavan 2013-02-08 18:59:25

+0

Pavan,你知道應用商店中使用它的任何應用嗎?謝謝! – 2014-04-08 17:43:49

1

另一種方式讓安裝的應用程序是隻要致電:

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

您可以訪問然後在每個應用程序讀取字典的Info.plist到更多地瞭解這些應用程序。

UPDATE:顯然,這種方法不工作了(對iOS8上)引起我們的應用程序沒有權限查看的內容/應用

+0

這會在App Store中被接受嗎? – OlivaresF 2013-02-21 23:35:05

+0

沒有私人API,因此它必須在App Store中被接受。 – 2013-03-13 15:10:07

+0

這將返回* a *列表的應用程序,而不是正確的。在Sim上,它在真實硬件上返回主機上的應用程序,它看起來像是默認應用程序的列表。 – 2013-05-14 17:25:05

1

當然,你可以做到這一點時,該設備是越獄,所以你可以接觸沙盒。 您可以通過分析位於每個路徑「/ 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", 
    "[email protected]" 
); 
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", 
    "[email protected]" 
); 
UIPrerenderedIcon = 1; 
UIStatusBarHidden = 1; 
UISupportedInterfaceOrientations =  (
    UIInterfaceOrientationPortrait, 
    UIInterfaceOrientationPortraitUpsideDown, 
    UIInterfaceOrientationLandscapeLeft, 
    UIInterfaceOrientationLandscapeRight 
); 
"UISupportedInterfaceOrientations~ipad" =  (
    UIInterfaceOrientationLandscapeRight, 
    UIInterfaceOrientationLandscapeLeft 
); 
} 
0

試試這個,它甚至會用非越獄的設備

#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]); 
相關問題