【发布时间】:2014-03-14 10:51:55
【问题描述】:
嗨极客, 我制作了一个应用程序,它在后台运行 1 小时(通过播放音乐 1 小时)。通过这个应用程序,我尝试在另一个应用程序中模拟任何触摸事件。我点击链接http://blog.lazerwalker.com/blog/2013/10/16/faking-touch-events-on-ios-for-fun-and-profit 做 GSSendEvent。我已经在我的 AppDelegate 中实现了该方法
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 10.0
target:self
selector:@selector(invokeAction)
userInfo:nil
repeats:NO];
}
这个方法在 10 秒后调用 invokeAction
-(mach_port_t)getFrontMostAppPort{
bool locked;
bool passcode;
void *lib = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSSpringBoardServerPort)() = dlsym(lib, "SBSSpringBoardServerPort");
void* (*SBGetScreenLockStatus)(mach_port_t* port, bool *lockStatus, bool *passcodeEnabled) = dlsym(lib, "SBGetScreenLockStatus");
machPort = (mach_port_t *)SBSSpringBoardServerPort();
dlclose(lib);
SBGetScreenLockStatus(machPort, &locked, &passcode);
void *(*SBFrontmostApplicationDisplayIdentifier)(mach_port_t *port, char *result) = dlsym(lib, "SBFrontmostApplicationDisplayIdentifier");
char appId[256];
memset(appId, 0, sizeof(appId));
SBFrontmostApplicationDisplayIdentifier(machPort, appId);
NSString * frontmostApp=[NSString stringWithFormat:@"%s",appId];
NSLog(@"app is %@",frontmostApp);
if([frontmostApp length] == 0 || locked)
return GSGetPurpleSystemEventPort();
else
return GSCopyPurpleNamedPort(appId);
}
-(void)invokeAction{
NSLog(@"1");
CGPoint touchBeginPoint = CGPointMake(600.0,510.0);
[self sendEventForPhase:UITouchPhaseBegan touchedPoint:touchBeginPoint];
double delayInSeconds = 0.5;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
CGPoint touchBeginPoint = CGPointMake(600.0,510.0);
[self sendEventForPhase:UITouchPhaseEnded touchedPoint:touchBeginPoint];
});
}
这里我构造了一个CGPoint并调用sendEVentForPhase。
- (void)sendEventForPhase:(UITouchPhase)phase touchedPoint:(CGPoint)point{
NSLog(@"called ");
static mach_port_t port_;
// structure of touch GSEvent
struct GSTouchEvent {
GSEventRecord record;
GSHandInfo handInfo;
} ;
struct GSTouchEvent *touchEvent = (struct GSTouchEvent *) malloc(sizeof(struct GSTouchEvent));
bzero(touchEvent, sizeof(touchEvent));
touchEvent->record.type = kGSEventHand;
touchEvent->record.subtype = kGSEventSubTypeUnknown;
touchEvent->record.location = point;
touchEvent->record.windowLocation = point;
touchEvent->record.infoSize = sizeof(GSHandInfo) + sizeof(GSPathInfo);
NSLog(@"time %lld",GSCurrentEventTimestamp());
touchEvent->record.timestamp = GSCurrentEventTimestamp();
touchEvent->record.senderPID = getpid();
NSLog(@"pr is %d",getpid());
//touchEvent->record.window = (__bridge GSWindowRef)(self.window);
bzero(&touchEvent->handInfo, sizeof(GSHandInfo));
bzero(&touchEvent->handInfo.pathInfos[0], sizeof(GSPathInfo));
GSHandInfo touchEventHandInfo;
touchEventHandInfo._0x5C = 0;
touchEventHandInfo.deltaX = 0;
touchEventHandInfo.deltaY = 0;
touchEventHandInfo.height = 0;
touchEventHandInfo.width = 0;
touchEvent->handInfo = touchEventHandInfo;
touchEvent->handInfo.type = (phase == UITouchPhaseBegan) ? kGSHandInfoTypeTouchDown : kGSHandInfoTypeTouchUp;
touchEvent->handInfo.deltaX = 1;
touchEvent->handInfo.deltaY = 1;
touchEvent->handInfo.pathInfosCount = 0;
touchEvent->handInfo.pathInfos[0].pathMajorRadius = 1.0;
touchEvent->handInfo.pathInfos[0].pathPressure = 1.0;
touchEvent->handInfo.pathInfos[0].pathIndex = 1;
touchEvent->handInfo.pathInfos[0].pathIdentity = 2;
touchEvent->handInfo.pathInfos[0].pathProximity = (phase == UITouchPhaseBegan) ? 0x03 : 0x00 ;
touchEvent->handInfo.pathInfos[0].pathLocation = point;
port_ = [self getFrontMostAppPort];
GSSendEvent((GSEventRecord*)touchEvent ,port_);
}
在此应用程序进入后台 10 秒后,将触发 invokeAction 方法。到那时我去我想要的应用程序。当应用程序在后台运行时,我访问在前台运行的应用程序。我将 CGPoint 作为前台应用程序中按钮的中心(我知道这一点,因为我有项目代码)。然后我构造 GSEventRecord。现在通过获取前台应用程序的紫色端口,我发送了这两个值(GSEventRecord 和 mach 端口),我创建了 GSSendEvent。函数名为 But,
现在我面临很多问题如下 1、触摸调用结果不一致。有时它只是执行完整的触摸事件,一切正常。 2. 有时只有 touchDown 有效,而我的后台应用程序在调用 touchUp 之前退出,这使得前台应用程序只是被蓝色突出显示的按钮击中,就好像手指没有从按钮上取下一样。
我正在使用 ios 6.1.3 的 ipad 上对其进行测试
为什么会有这样的不一致。我想念什么吗。请帮帮我。一个小小的帮助将让我忙碌的 3 天一去不复返。
【问题讨论】:
-
我已经更改了源代码和描述分开的问题。感谢您指出。
-
你能帮我解决这个问题吗...我在这里被打了 2 天...
-
嗨内特,我编辑了这个问题。现在我可以向应用程序发送事件,但我面临一些问题。请看透。
-
您是否尝试过在触地和触地之间留出一些时间?在我看来,
invokeAction正在一个接一个地注入这两个触摸事件。把他们之间的延迟。注意:不要做类似线程sleep()的事情。使用dispatch_after()之类的方式安排 100 毫秒左右后的第二次调用。 -
另外,您正在测试哪个版本的 iOS?
标签: ios objective-c iphone-privateapi