如何通过应用程序标识确定哪些应用程序是背景和iOS应用程序的前台

使用 this question中描述的方法,我可以得到在iOS设备上运行的应用程序的列表.
我知道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
- (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也是.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...