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