如何根据应用程序ID确定哪些应用程序是背景以及哪些应用程序是iOS上的前景
使用这个问题中描述的方法,我可以得到在iOS设备上运行的应用程序列表。 我知道PID,并有权访问他们的kinfo_proc
结构。 我怎样才能确定哪些是前台进程,哪些是后台(假设我的应用程序是背景)?
我试图根据kinfo_proc
信息(请参阅第一个链接),通过kp_proc.p_priority
find这个信息,但是看起来不可能从优先级推断出背景/前景状态。
我真的不在乎,如果这适用于AppStore审查正确的,但我宁愿一种方法,将工作没有越狱(即私人API是好的,但哪些?)。 我希望这至less在iOS 5上工作
我考虑编写一个简单的MobileSubstrate
扩展,将其注入到所有的应用程序,并钩住每个人的applicationDidBecomeActive
,但这需要越狱,是太侵入。
那么,看起来来自模拟器的SpringBoardServices二进制的nm和IDA的一些使用帮助我。 以下代码适用于运行在iPod Touch 4,iPhone 4和iPad1上的iOS 5.0.1 WiFi(所有非JB)当然,您不应该尝试将其提交给AppStore
- (NSArray*) getActiveApps { mach_port_t *p; void *uikit = dlopen(UIKITPATH, RTLD_LAZY); int (*SBSSpringBoardServerPort)() = dlsym(uikit, "SBSSpringBoardServerPort"); p = (mach_port_t *)SBSSpringBoardServerPort(); dlclose(uikit); void *sbserv = dlopen(SBSERVPATH, RTLD_LAZY); NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) = dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers"); //SBDisplayIdentifierForPID - protype assumed,verification of params done void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) = dlsym(sbserv, "SBDisplayIdentifierForPID"); //SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not) void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) = dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier"); //Get frontmost application char frontmostAppS[256]; memset(frontmostAppS,sizeof(frontmostAppS),0); SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS); NSString * frontmostApp=[NSString stringWithFormat:@"%s",frontmostAppS]; //NSLog(@"Frontmost app is %@",frontmostApp); //get list of running apps from SpringBoard NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO); //Really returns ACTIVE applications(from multitasking bar) /* NSLog(@"Active applications:"); for(NSString *identifier in allApplications) { // NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier); NSLog(@"Active Application:%@",identifier); } */ //get list of all apps from kernel 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--){ int ruid=process[i].kp_eproc.e_pcred.p_ruid; int uid=process[i].kp_eproc.e_ucred.cr_uid; //short int nice=process[i].kp_proc.p_nice; //short int u_prio=process[i].kp_proc.p_usrpri; short int prio=process[i].kp_proc.p_priority; NSString * processID = [[NSString alloc] initWithFormat:@"%d", process[i].kp_proc.p_pid]; NSString * processName = [[NSString alloc] initWithFormat:@"%s", process[i].kp_proc.p_comm]; BOOL systemProcess=YES; if (ruid==501) systemProcess=NO; char * appid[256]; memset(appid,sizeof(appid),0); int intID,intID2; intID=process[i].kp_proc.p_pid,appid; SBDisplayIdentifierForPID(p,intID,appid);/ NSString * appId=[NSString stringWithFormat:@"%s",appid]; if (systemProcess==NO) { if ([appId isEqualToString:@""]) { //final check.if no appid this is not springboard app NSLog(@"(potentially system)Found process with PID:%@ name %@,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio); } else { BOOL isFrontmost=NO; if ([frontmostApp isEqualToString:appId]) { isFrontmost=YES; } NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost]; NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil] forKeys:[NSArray arrayWithObjects:@"ProcessID", @"ProcessName",@"AppID",@"isFrontmost", nil]]; NSLog(@"PID:%@, name: %@, AppID:%@,isFrontmost:%d",processID,processName,appId,isFrontmost); [array addObject:dict]; } } } free(process); return array; } } } dlclose(sbserv); }
当然第二循环并不是绝对必要的,但我也需要非本地化的名称和PID。
很好的回答! 但是在你的代码中有一个小的错字,它应该是:
首先确保定义了SBSERVPATH并包含正确的头文件:
#import <sys/sysctl.h> #import <dlfcn.h> #define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
然后首先find正确的SB端口:
mach_port_t *port; void *lib = dlopen(SBSERVPATH, RTLD_LAZY); int (*SBSSpringBoardServerPort)() = dlsym(lib, "SBSSpringBoardServerPort"); port = (mach_port_t *)SBSSpringBoardServerPort(); dlclose(lib);
然后find活动的应用程序:
mach_port_t * port = [self getSpringBoardPort]; // open springboard lib void *lib = dlopen(SBSERVPATH, RTLD_LAZY); // retrieve function SBFrontmostApplicationDisplayIdentifier void *(*SBFrontmostApplicationDisplayIdentifier)(mach_port_t *port, char *result) = dlsym(lib, "SBFrontmostApplicationDisplayIdentifier"); // reserve memory for name char appId[256]; memset(appId, 0, sizeof(appId)); // retrieve front app name SBFrontmostApplicationDisplayIdentifier(port, appId); // close dynlib dlclose(lib);
这在我所有的IOS设备上都适用:
#define UIKITPATH "/System/Library/Framework/UIKit.framework/UIKit" #define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices" - (NSArray*) getActiveApps { mach_port_t *p; void *uikit = dlopen(UIKITPATH, RTLD_LAZY); int (*SBSSpringBoardServerPort)() = dlsym(uikit, "SBSSpringBoardServerPort"); p = (mach_port_t *)SBSSpringBoardServerPort(); dlclose(uikit); if(self.frameWorkPath == nil || self.frameWorkPath.length == 0) { self.frameWorkPath = @SBSERVPATH; self.frameWorkPath = [self.frameWorkPath stringByTrimmingCharactersInSet:[NSCharacterSet newlineCharacterSet]]; } const char *cString = [self.frameWorkPath cStringUsingEncoding:NSUTF8StringEncoding]; //const char *bar = [self.frameWorkPath UTF8String]; void *sbserv = dlopen(cString, RTLD_LAZY); NSArray* (*SBSCopyApplicationDisplayIdentifiers)(mach_port_t* port, BOOL runningApps,BOOL debuggable) = dlsym(sbserv, "SBSCopyApplicationDisplayIdentifiers"); //SBDisplayIdentifierForPID - protype assumed,verification of params done void* (*SBDisplayIdentifierForPID)(mach_port_t* port, int pid,char * result) = dlsym(sbserv, "SBDisplayIdentifierForPID"); //SBFrontmostApplicationDisplayIdentifier - prototype assumed,verification of params done,don't call this TOO often(every second on iPod touch 4G is 'too often,every 5 seconds is not) void* (*SBFrontmostApplicationDisplayIdentifier)(mach_port_t* port,char * result) = dlsym(sbserv, "SBFrontmostApplicationDisplayIdentifier"); //Get frontmost application char frontmostAppS[512]; memset(frontmostAppS,sizeof(frontmostAppS),0); SBFrontmostApplicationDisplayIdentifier(p,frontmostAppS); NSString * frontmostApp=[NSString stringWithFormat:@"%s",frontmostAppS]; if([self iOsMajorVersion] >= 7){ NSNumber *topmost = [NSNumber numberWithBool:YES]; NSMutableDictionary * dict = [[NSMutableDictionary alloc] init]; NSMutableArray * splitted = [frontmostApp componentsSeparatedByString:@"."]; if(frontmostApp.length > 0 && splitted != nil && splitted.count > 1 && topmost.boolValue == YES){ NSString *appname = [splitted lastObject]; [dict setObject:[appname capitalizedString] forKey:@"ProcessName"]; [dict setObject:frontmostApp forKey:@"ProcessID"]; [dict setObject:frontmostApp forKey:@"AppID"]; [dict setObject:topmost forKey:@"isFrontmost"]; NSLog(@"Running TOPMOST App %@",dict); return @[dict]; } else{ return nil; } } //NSLog(@"Frontmost app is %@",frontmostApp); //get list of running apps from SpringBoard NSArray *allApplications = SBSCopyApplicationDisplayIdentifiers(p,NO, NO); //Really returns ACTIVE applications(from multitasking bar) NSLog(@"Active applications:"); for(NSString *identifier in allApplications) { // NSString * locName=SBSCopyLocalizedApplicationNameForDisplayIdentifier(p,identifier); NSLog(@"Active Application:%@",identifier); } //get list of all apps from kernel 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--){ int ruid=process[i].kp_eproc.e_pcred.p_ruid; int uid=process[i].kp_eproc.e_ucred.cr_uid; //short int nice=process[i].kp_proc.p_nice; //short int u_prio=process[i].kp_proc.p_usrpri; short int prio=process[i].kp_proc.p_priority; NSString * processID = [[NSString alloc] initWithFormat:@"%d", process[i].kp_proc.p_pid]; NSString * processName = [[NSString alloc] initWithFormat:@"%s", process[i].kp_proc.p_comm]; BOOL systemProcess=YES; if (ruid==501){ systemProcess=NO; } char * appid[256]; memset(appid,sizeof(appid),0); int intID,intID2; intID=process[i].kp_proc.p_pid,appid; SBDisplayIdentifierForPID(p,intID,appid); NSString * appId=[NSString stringWithFormat:@"%s",appid]; if (systemProcess==NO) { if ([appId isEqualToString:@""]) { //final check.if no appid this is not springboard app //NSLog(@"(potentially system)Found process with PID:%@ name %@,isSystem:%d,Priority:%d",processID,processName,systemProcess,prio); } else { BOOL isFrontmost=NO; if ([frontmostApp isEqualToString:appId]) { isFrontmost=YES; } NSNumber *isFrontmostN=[NSNumber numberWithBool:isFrontmost]; NSDictionary * dict = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:processID, processName,appId,isFrontmostN, nil] forKeys:[NSArray arrayWithObjects:@"ProcessID", @"ProcessName",@"AppID",@"isFrontmost", nil]]; NSLog(@"PID:%@, name: %@, AppID:%@,isFrontmost:%d",processID,processName,appId,isFrontmost); [array addObject:dict]; } } } free(process); return array; } } } dlclose(sbserv); }