views:

310

answers:

6

I want to find the pressure of the touch. I just don't know how to accomplish that result with out jailbreaking it and getting the raw touch data. Does anyone know How I would do this?

+1  A: 

It's not possible with the SDK. It does not expose that data in anyway. And the screen does not sense pressure, and wether it even reports touch "size" to the OS is unknown. So sadly, what you are trying to do is not possible on a legit application.

I know because I asked the same thing: http://stackoverflow.com/questions/524584/can-the-iphone-detect-the-size-of-a-touch

Squeegy
It does sense the size of the touch but the information is discarded. See my answer.
KennyTM
@Kenny: where is your answer and can i access the discarded information, and use it in the app without it being rejected?
Jaba
+2  A: 

Its not possible. The hardware hasnt been designed to pick up varying levels of pressure.

how do iphone touch screens work

It seems they've been looking into it though.

Mongus Pong
+8  A: 

You cannot get the pressure from the SDK nor undocumented methods. However you can detect the size of touch with undocumented methods.


In the GSEvent, which is a lower-level representation of UIEvent, there is a structure known as GSPathInfo with members:

typedef struct GSPathInfo {
    unsigned char pathIndex;        // 0x0 = 0x5C
    unsigned char pathIdentity;     // 0x1 = 0x5D
    unsigned char pathProximity;    // 0x2 = 0x5E
    CGFloat pathPressure;               // 0x4 = 0x60
    CGFloat pathMajorRadius;        // 0x8 = 0x64
    CGPoint pathLocation;           // 0xC = 0x68
    GSWindowRef pathWindow;         // 0x14 = 0x70
} GSPathInfo;

We notice that there is a pathPressure and pathMajorRadius. I can assure you the pressure member is useless – it always gives 0. However pathMajorRadius does contain meaningful information – it gives the major radius of the touch in millimeters. You can therefore give an extremely rough estimation if it's a heavy touch or light touch from the radius.

  -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
     GSEventRef gsevent = [event _gsEvent];
     GSPathInfo first_touch = GSEventGetPathInfoAtIndex(gsevent, 0);
     if (first_touch.pathMajorRadius >= 9)
        NSLog(@"huge (heavy) touch");
     else
        NSLog(@"little (light) touch");
  }

Let me warn you again this is undocumented and you should not use it in AppStore apps.


Edit: On 3.2 and above the pathMajorRadius of a GSPathInfo is also available as an undocumented property in UITouch:

@property(assign, nonatomic, setter=_setPathMajorRadius:) CGFloat _pathMajorRadius;

so the code above could be rewritten using pure Objective-C:

  -(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
     UITouch* any_touch = [touches anyObject];
     if (any_touch._pathMajorRadius >= 9)
        NSLog(@"huge (heavy) touch");
     else
        NSLog(@"little (light) touch");
  }
KennyTM
Would apple reject the app for that reason. Because it is undocumented?
Jaba
@Jaba: Yes. To use `GSEventGetPathInfoAtIndex` you'll need to link to the private framework `GraphicsServices`. Even if you do late binding, Apple will still find the strings `_gsEvent` and `GSEventGetPathInfoAtIndex` and reject that.
KennyTM
Is there a backdoor that I could explore, like another way to get this to work, or could I access this private file through another pathway?
Jaba
Wow, that's pretty damn cool. But if you use it you can guarantee yourself a nice little rejection.
Squeegy
@Jaba: You could "encode" your binary like Skype did (not that Skype uses undocumented methods though). But I don't think it worths the effort. And this solution isn't very accurate either, consider a fat finger...
KennyTM
A: 

In iOS 3.2 and 4.0 you can get the value more directly like this:

UITouch* touch = ... float radius = [[touch valueForKey:@"pathMajorRadius"] floatValue];

Still not App Store approved, but handy for custom stuff.

Josh
A: 

After which events is pathMajorRadius updated?

Is it possible get updates on the radius when the finger does not move after the first screen contact but it might press harder on screen?

Thank you for our answers!

Christian
A: 

It is updated before each event sent. Your finger can't possibly be so accurate that pressure will change without move events - many moves will be registered if you press a little harder. This value you get back is a bit jittery and varies from person to person For me it is giving something from 7..10 through normal use, can easily go up to 15, etc. My five year old daughter gets smaller values in normal use. You can easily control it by rolling your finger to adjust touch area size - it's very natural, and actually an independent control parameter from pressure.

All I can say is that this truly is the secret sauce to making a realistic music instrument, but you have to make the call fail-safe (the float exists but comes back zero in simulator for instance, but the float might come back null in new releases, prepare for it to come back with a wildly larger or smaller value than you planned for, and umm... be careful to not include it in your app store build in case The Guardians have a problem with making your app umm... meet its requirements).

You have to do a little signal processing on this value if the jitter is a problem for your app, but it works great.

Rob