使用
this question中描述的方法,我可以得到在iOS设备上运行的应用程序的列表.
我知道PID并访问他们的kinfo_proc结构.
如何确定哪些是前台进程,哪些是背景(假设我的应用程序是背景)?
我知道PID并访问他们的kinfo_proc结构.
如何确定哪些是前台进程,哪些是背景(假设我的应用程序是背景)?
我试图通过kp_proc.p_priority在kinfo_proc(见第一个链接)中找到这个信息,但是看起来不可能从优先级推断背景/前景状态.
我不太在乎AppStore Review是否正常工作,但我宁愿使用一种无越狱的方法(即私有API可以,但是哪些?).我希望这至少在iOS 5上运行
我考虑编写一个简单的MobileSubstrate扩展,将其注入到所有应用程序中,并且只是钩住每个人的applicationDidBecomeActive,但这需要越狱,并且是太侵入性的.
解决方法
那么,看起来像一些使用nm和IDA在SpringBoardServices二进制从模拟器帮助我这个.
以下代码适用于在iPod Touch 4,iPhone 4和iPad1 WiFi(所有非JB)上运行的iOS 5.0.1
当然你也不应该试图把它提交给AppStore
以下代码适用于在iPod Touch 4,iPhone 4和iPad1 WiFi(所有非JB)上运行的iOS 5.0.1
当然你也不应该试图把它提交给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,"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,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,process,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,appId,isFrontmostN,nil] forKeys:[NSArray arrayWithObjects:@"ProcessID",@"ProcessName",@"AppID",@"isFrontmost",nil]]; NSLog(@"PID:%@,name: %@,AppID:%@,isFrontmost:%d",isFrontmost); [array addObject:dict]; } } } free(process); return array; } } } dlclose(sbserv); }
当然,第二个循环并不是绝对必要的,但是我需要非本地化的名称& PID也是.