获取iphone objective-c上已安装应用程序的列表

时间:2011-12-27 13:51:23

标签: iphone objective-c ios uidevice

我有一个应用程序需要获取设备上已安装(其他可能是第三方)应用程序的列表。怎么做到呢?或者它可以完成吗?

6 个答案:

答案 0 :(得分:17)

您可以通过Apple私有框架“MobileInstallationInstall”扫描您的所有应用。

方法如下:

NSDictionary *options = [NSDictionary dictionaryWithKeyAndValues:@"ApplicationType",@"Any",nil]
NSDictionary *apps = MobileInstallationLookup(options);

它只能在JB设备中使用。

答案 1 :(得分:6)

-(NSArray *) installedApps
{
    BOOL isDir enter code here= NO;
    NSDictionary *cacheDienter code herect;
    NSDictionary *user;
    static NSString *const cacheFileName = @"com.apple.mobile.installation.plist";
    NSString *relativeCachePath = [[@"Library" stringByAppendingPathComponent: @"Caches"] stringByAppendingPathComponent: cacheFileName];
    NSString *path = [[NSHomeDirectory() stringByAppendingPathComponent: @"../.."] stringByAppendingPathComponent: relativeCachePath];
    if ([[NSFileManager defaultManager] fileExistsAtPath: path isDirectory: &isDir] && !isDir) // Ensure that file exists
    {
        cacheDict    = [NSDictionary dictionaryWithContentsOfFile: path];
        user = [cacheDict objectForKey: @"System"]; // Then all the user (App Store /var/mobile/Applications) apps
    }



    //NSLog(@"Installed Applications = %@",[user allKeys]); 
    //return [user allKeys];
    return nil;
}

这将使用私有API

为您提供已安装应用程序的名称数组

答案 2 :(得分:5)

苹果没有从iOS设备(iPod Touch / iPhone / iPad)获取此类列表的公共API

答案 3 :(得分:3)

我怀疑是否有可用的东西(如果某些iphone被越狱并且用户可以访问文件系统,那么它将是可能的,但我不知道这一点。),  但您可以使用以下link,在此帮助下,您可以检查所有应用程序的存在,并根据您的一些需求进行自定义。

答案 4 :(得分:2)

此WONT提供已安装应用程序的列表,但您可以通过此代码获取在后台运行的应用程序列表及其相关进程。

从viewDidLoad调用 -

[self printProcessInfo];

-(NSMutableString*) printProcessInfo {
 int mib[5];
 struct kinfo_proc *procs = NULL, *newprocs;
 int i, st, nprocs;
 size_t miblen, size;

 /* Set up sysctl MIB */
 mib[0] = CTL_KERN;
 mib[1] = KERN_PROC;
 mib[2] = KERN_PROC_ALL;
 mib[3] = 0;
 miblen = 4;

 /* Get initial sizing */
 st = sysctl(mib, miblen, NULL, &size, NULL, 0);

 /* Repeat until we get them all ... */
 do {
      /* Room to grow */
      size += size / 10;
      newprocs = realloc(procs, size);
      if (!newprocs) {
           if (procs) {
                free(procs);
           }
           perror("Error: realloc failed.");
           return (0);
      }
      procs = newprocs;
      st = sysctl(mib, miblen, procs, &size, NULL, 0);
 } while (st == -1 && errno == ENOMEM);

 if (st != 0) {
      perror("Error: sysctl(KERN_PROC) failed.");
      return (0);
 }

 /* Do we match the kernel? */
 assert(size % sizeof(struct kinfo_proc) == 0);

 nprocs = size / sizeof(struct kinfo_proc);

 if (!nprocs) {
      perror("Error: printProcessInfo.");
      return(0);
 }
 printf("  PID\tName\n");
 printf("-----\t--------------\n");
 self.lists = [[NSMutableString alloc] init];
 NSMutableString *localStr = [[NSMutableString alloc] init];
 for (i = nprocs-1; i >=0;  i--) {
      // printf("%5d\t%s\n",(int)procs[i].kp_proc.p_pid, procs[i].kp_proc.p_comm);


      localStr = [NSString stringWithFormat:@"%@,\nPID:-%5d,\tPROCESS_NAME:-%s\n",localStr,(int)procs[i].kp_proc.p_pid, procs[i].kp_proc.p_comm ];
      NSString *pathStr = [self print_argv_of_pid:(int)procs[i].kp_proc.p_pid];
      //NSString *pathStr = print_argv_of_pid:(((int)procs[i].kp_proc.p_pid));
      localStr = [NSString stringWithFormat:@"%@,\n%@\n",localStr,pathStr ];
     // [self getAttributesOfProcess];
       //printf("%s",path);


 }
 NSLog(@"%@",lists);

 free(procs);
 return localStr;
 //return (0);
}



-(NSString*) print_argv_of_pid:(int) pid {

 char path[1000];
 printf("%d\n", pid);
 int    mib[3], argmax, nargs, c = 0;
 size_t    size;
 char    *procargs, *sp, *np, *cp;
 extern int  eflg;
 int show_args = 1;

 mib[0] = CTL_KERN;
 mib[1] = KERN_ARGMAX;

 size = sizeof(argmax);
 if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
      return @"";
      //goto ERROR_A;
 }

 /* Allocate space for the arguments. */
 procargs = (char *)malloc(argmax);
 if (procargs == NULL) {
       return @"";
      //goto ERROR_A;
 }


 /*
  * Make a sysctl() call to get the raw argument space of the process.
  * The layout is documented in start.s, which is part of the Csu
  * project.  In summary, it looks like:
  *
  * /---------------\ 0x00000000
  * :               :
  * :               :
  * |---------------|
  * | argc          |
  * |---------------|
  * | arg[0]        |
  * |---------------|
  * :               :
  * :               :
  * |---------------|
  * | arg[argc - 1] |
  * |---------------|
  * | 0             |
  * |---------------|
  * | env[0]        |
  * |---------------|
  * :               :
  * :               :
  * |---------------|
  * | env[n]        |
  * |---------------|
  * | 0             |
  * |---------------| <-- Beginning of data returned by sysctl() is here.
  * | argc          |
  * |---------------|
  * | exec_path     |
  * |:::::::::::::::|
  * |               |
  * | String area.  |
  * |               |
  * |---------------| <-- Top of stack.
  * :               :
  * :               :
  * \---------------/ 0xffffffff
  */
 mib[0] = CTL_KERN;
 mib[1] = KERN_PROCARGS2;
 mib[2] = pid;


 size = (size_t)argmax;
 if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
      //goto ERROR_B;
       return @"";
 }

 memcpy(&nargs, procargs, sizeof(nargs));
 cp = procargs + sizeof(nargs);

 /* Skip the saved exec_path. */
 for (; cp < &procargs[size]; cp++) {
      if (*cp == '\0') {
           /* End of exec_path reached. */
           break;
      }
 }
 if (cp == &procargs[size]) {
      //goto ERROR_B;
       return @"";
 }

 /* Skip trailing '\0' characters. */
 for (; cp < &procargs[size]; cp++) {
      if (*cp != '\0') {
           /* Beginning of first argument reached. */
           break;
      }
 }
 if (cp == &procargs[size]) {
      //goto ERROR_B;
       return @"";
 }
 /* Save where the argv[0] string starts. */
 sp = cp;

 /*
  * Iterate through the '\0'-terminated strings and convert '\0' to ' '
  * until a string is found that has a '=' character in it (or there are
  * no more strings in procargs).  There is no way to deterministically
  * know where the command arguments end and the environment strings
  * start, which is why the '=' character is searched for as a heuristic.
  */
 for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
      if (*cp == '\0') {
           c++;
           if (np != NULL) {
                /* Convert previous '\0'. */
                *np = ' ';
           } else {
                /* *argv0len = cp - sp; */
           }
           /* Note location of current '\0'. */
           np = cp;

           if (!show_args) {
                /*
                 * Don't convert '\0' characters to ' '.
                 * However, we needed to know that the
                 * command name was terminated, which we
                 * now know.
                 */
                break;
           }
      }
 }

 /*
  * sp points to the beginning of the arguments/environment string, and
  * np should point to the '\0' terminator for the string.
  */
 if (np == NULL || np == sp) {
      /* Empty or unterminated string. */
      // goto ERROR_B;
       return @"";
 }

 /* Make a copy of the string. */
 // printf("%s\n", sp);
 //path = sp;
 memset(path,0,1000);
 strcpy(path, sp);
 NSString *pathStr = [NSString stringWithFormat:@"%s",path];
 NSLog(@"%@",pathStr);
 // printf("%s\n", path);
 /* Clean up. */
 free(procargs);
 return pathStr;

ERROR_B:
 free(procargs);
ERROR_A:
 printf("(%d)", pid);

}

答案 5 :(得分:0)

魔术师的回答和Victor对头文件链接的评论帮助我解决了这个问题。

我确实想补充一点,你必须将MobileInstallation.framework添加到Xcode中的“Linked Frameworks and Libraries”。我在这里找到了这个框架:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/System/Library/PrivateFrameworks

我可以确认这适用于非越狱设备。应用程序商店对我来说不是一个问题。

这是我使用的代码:

NSDictionary *options = [NSDictionary dictionaryWithObject:@"Any" forKey:@"ApplicationType"];
NSDictionary *apps = (__bridge NSDictionary *) MobileInstallationLookup((__bridge CFDictionaryRef) options);