问题
How can I programmatically trigger the shake event in iOS?
I've tried the following but it keeps crashing...
+ (void)shake {
NSLog(@"TEST");
UIMotionEventProxy *m = [[NSClassFromString(@"UIMotionEvent") alloc] _init];
m->_subtype = UIEventSubtypeMotionShake;
m->_shakeState = 1;
[[[UIApplication sharedApplication] keyWindow] motionBegan:UIEventSubtypeMotionShake withEvent:m];
[[[UIApplication sharedApplication] keyWindow] motionEnded:UIEventSubtypeMotionShake withEvent:m];
}
What does apple do in the simulator under Hardware > Shake Gesture
?
回答1:
Changing the UIMotionEventProxy class (adding two setter methods) seemed to do the trick. I simply added two methods setShakeState
and _setSubtype
, shown below.
-(void)setShakeState:(int)fp8 {
_shakeState = fp8;
}
-(void)_setSubtype:(int)fp8 {
_subtype = fp8;
}
I then changed my code to the following...
UIMotionEventProxy *m = [[NSClassFromString(@"UIMotionEvent") alloc] _init];
[m setShakeState:1];
[m _setSubtype:UIEventSubtypeMotionShake];
[[UIApplication sharedApplication] sendEvent:m];
[[[UIApplication sharedApplication] keyWindow] motionBegan:UIEventSubtypeMotionShake withEvent:m];
[[[UIApplication sharedApplication] keyWindow] motionEnded:UIEventSubtypeMotionShake withEvent:m];
Seems to be working flawlessly for both simulator and physical device. Here are main and header files available for download if anyone wants to see the full UIMotionEventProxy files.
回答2:
Try to replace
UIMotionEventProxy *m = [[NSClassFromString(@"UIMotionEvent") alloc] _init];
with
UIMotionEventProxy *m = [[UIMotionEventProxy alloc] _init];
I guess it's crushing when NSClassFromString(@"UIMotionEvent")
returns nil.
回答3:
Do you want to use in Jailbreak app or Apple compliant use ?
For your question about simulator, Apple use a private function.
Here is a little explanation:
When you use "Shake Gesture", the simulator call sendButtonEvent:0x3fc
sendButtonEvent is a function in Simulator, who:
- get frontmostAppPort
- send a message via sendPurpleEvent or HIDEvent
In a jailbreak application, you can do something like (not tested, but should works):
struct UIEvent {
int subtype;
double timestamp;
int type;
} * event;
bzero(event, sizeof(event));
event->type = UIEventTypeMotion;
event->subtype = UIEventSubtypeMotionShake;
event->timestamp = GSCurrentEventTimestamp();
NSString* bundle = [[NSBundle mainBundle] bundleIdentifier];
mach_port_t port = GSCopyPurpleNamedPort([bundle UTF8String]);
GSEventRecord* record = (GSEventRecord*)event;
GSSendEvent(record, port);
来源:https://stackoverflow.com/questions/24433763/programmatically-trigger-shake-event-ios