使用
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也是.