关于获取IOS应用列表

Sommaire de cet article :
  1. import <sys/sysctl.h>

当两天没事儿,突然想起这么一个命题:获取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;
}

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

转载请注明: 转自Rainbird的个人博客
   本文链接: 关于获取IOS应用列表

About rainbird

IOS攻城狮
This entry was posted in iOS, 原创 and tagged , , . Bookmark the permalink.

发表评论