【问题标题】:how to make GSSendEvent call and simulate a touch event如何进行 GSSendEvent 调用并模拟触摸事件
【发布时间】: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


【解决方案1】:

1) struct GSTouchEvent *touchEvent = (struct GSTouchEvent *) malloc(sizeof(struct GSTouchEvent));

内存不够 需要touchEvent->handInfo.pathInfos[0] 的更多路径信息 由于它在 struct 中的定义没有内存,数组“pathInfos”的长度为 0,但你使用了 1struct GSTouchEvent

2) GSHandInfo touchEventHandInfo 的内存应该被重置

bzero(&touchEventHandInfo, sizeof(GSHandInfo));

【讨论】:

    猜你喜欢
    • 2013-04-16
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    相关资源
    最近更新 更多