关于获取IOS应用列表

转自:http://blog.cnrainbird.com/index.php/2012/04/19/guan_yu_huo_qu_ios_ying_yong_lie_biao/

当两天没事儿,突然想起这么一个命题:获取IOS应用安装列表。
研究来研究去最后也没有得出个所以然来。这不今天上网,发现这篇儿文章。晾这说有三种方法。也就顺便总结一下,边转载边补充。
ok,说是三种方法,靠谱的两种:
1.openURL
我们知道可以给应用设置URL Scheme,这样别的应用就可以通过这个地址打开咱们的应用。其实还有一个api叫canOpenURL.这样如果咱们知道要检查的IOS应用列表的URL Scheme的话,就可以用canOpenURL检查一下。
2.获取运行程序列表

// .h

@interface UIDevice (ProcessesAdditions)
- (NSArray *)runningProcesses;
@end

// .m
#import <sys/sysctl.h>

@implementation UIDevice (ProcessesAdditions)

- (NSArray *)runningProcesses {

        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
        size_t miblen = 4;
        
        size_t size;
        int st = sysctl(mib, miblen, NULL, &size, NULL, 0);
        
        struct kinfo_proc * process = NULL;
        struct kinfo_proc * newprocess = NULL;
        
    do {
                
        size += size / 10;
        newprocess = realloc(process, size);
                
        if (!newprocess){
                        
            if (process){
                free(process);
            }
                        
            return nil;
        }
                
        process = newprocess;
        st = sysctl(mib, miblen, process, &size, NULL, 0);
                
    } while (st == -1 && errno == ENOMEM);
        
        if (st == 0){
                
                if (size % sizeof(struct kinfo_proc) == 0){
                        int nprocess = size / sizeof(struct kinfo_proc);
                
                        if (nprocess){
                        
                                NSMutableArray * array = [[NSMutableArray alloc] init];
        
                                for (int i = nprocess - 1; i >= 0; i--){
                
                                        NSString * processID = [[NSString alloc] initWithFormat:@"%d", process[i].kp_proc.p_pid];
                                        NSString * processName = [[NSString alloc] initWithFormat:@"%s", process[i].kp_proc.p_comm];
                
                                        NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName, nil] 
                                                                                                                                                forKeys:[NSArray arrayWithObjects:@"ProcessID", @"ProcessName", nil]];
                                        [processID release];
                                        [processName release];
                                        [array addObject:dict];
                                        [dict release];
                                }
        
                                free(process);
                                return [array autorelease];
                        }
                }
        }
        
        return nil;
}

@end

// Example usage.
NSArray * processes = [[UIDevice currentDevice] runningProcesses];
for (NSDictionary * dict in processes){
        NSLog(@"%@ - %@", [dict objectForKey:@"ProcessID"], [dict objectForKey:@"ProcessName"]);
}

这种方法是获取运行中的应用列表。如果应用没被运行过或不在后台,就得不到喽。

比起上面两个方法要靠谱一点儿的就是私有API了。

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;
  NSLog(@"relativeCachePath:%@",relativeCachePath);
  // 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;
    NSLog(@"path:%@",path);
    // Ensure that file exists
    if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir] && !isDir){
      cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
    } 
    
    // If cache is loaded, then break the loop. If the loop is not "broken," it will return NO later (default: case)
    if (cacheDict){
      NSLog(@"cacheDict:%@",cacheDict);
      break;
    } 
    
  }
  
  NSLog(@"gggg");
  // First check all system (jailbroken) apps
  NSDictionary *system = [cacheDict objectForKey: @"System"]; 
  NSLog(@"system:%@",system);
  if ([system objectForKey: bundleIdentifier]){
    return YES;
  }
  
  // Then all the user (App Store /var/mobile/Applications) apps
  NSDictionary *user = [cacheDict objectForKey: @"User"]; 
  NSLog(@"user:%@",user);
  if ([user objectForKey: bundleIdentifier]){
    return YES;
  }
  
  // If nothing returned YES already, we'll return NO now
  return NO;
}

不过这种方法需要机器已经越狱,还需要你的应用不在沙盒里,由于后一条笔者还不大会搞,所以没试成功:)


你可能感兴趣的:(ios,Objective-C,应用,应用列表)