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

Posted

技术标签:

【中文标题】获取 iphone Objective-c 上已安装应用程序的列表【英文标题】:get list of installed applications on iphone objective-c 【发布时间】:2011-12-27 13:51:23 【问题描述】:

我有一个应用程序需要获取设备上已安装(其他,可能是第三方)应用程序的列表。如何做呢?还是完全可以做到?

【问题讨论】:

这是重复的,请参考以下线程-***.com/questions/4614114/… 是否存在任何第三方库来做到这一点? 感谢@rishi。我错过了。请用您的评论回答我的问题。 我怀疑是否有可用的东西,但您可以使用以下链接-iphonedevsdk.com/forum/iphone-sdk-development/…,借助此链接,您可以检查所有应用程序都存在。 请用您的评论回答我的问题(它将被标记为已接受) 【参考方案1】:

您可以通过苹果私有框架“MobileInstallationInstall”扫描您所有的应用程序。

方法如下:

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

只能在JB设备中使用。

【讨论】:

其实。它也可以在被监禁的设备上使用。但是,您无法将带有此代码的应用程序下载到 AppStore,因为它是私有 API。 如何获取 MobileInstallationInstall 的标头? @EwyynTomato:可以在此处找到标头作为示例:github.com/Cykey/ios-reversed-headers/blob/master/…【参考方案2】:
-(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 的已安装应用程序的名称数组

【讨论】:

在 iOS 6 下无法在设备上运行。该文件不存在。【参考方案3】:

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

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

从 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);


【讨论】:

【参考方案6】:

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

我确实想补充一点,您必须将 MobileInstallation.framework 添加到 Xcode 中的“链接框架和库”中。我在这里找到了这个框架:

/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);

【讨论】:

以上是关于获取 iphone Objective-c 上已安装应用程序的列表的主要内容,如果未能解决你的问题,请参考以下文章

Myeclipse中添加Oracle

iPhone:如何从Objective-C中的货币符号字符串中获取数字

如何在 Objective-C 中获取当前工作目录的绝对路径?

iPhone Objective-C CoreLocation:想要使用基于当前位置的数据填充表格

如何获取数组Objective-C中每个项目的索引

iPhone(Objective-c)和Java之间的AES区别