Some good news and some less good news today (it seems they always come together :-0).
I have been playing around intensively trying to hook into the CoreLocation framework by using the MobileSubstrate platform. Rodrigo, a customer from Portugal, dropped me an email two weeks ago with some very useful source code and a link for a MobileSubstrate tutorial on using MobileSubstrate to trick the Springboard.
Rodrigo pretty much figured out how to feed the CoreLocation framework coordinates and accuracy data. I decided to dig in a little more and managed to also feed the CoreLocation framework fake (generated by a random number generator) altitude, speed and heading data. It was a little bit tricky to get the speed and heading in as it required upgrading the Toolchain to 2.2 (I was at 2.0.1, but am currently at 2.2). It looks like Saurik has updated his instructions for building the 2.x Toolchain and it seems to be pretty straightforward now assuming you follow instructions as outlined (I have done it a few times now and have gotten the hang of it :-)
So what have we been able to do? I installed a bunch of free AppStore apps on my iPhone 2G that are GPS related: Google Earth, GPSLite, Beacon, Speedometer, GPS Tracker, GPS Ally, GPS-R and Trailguru.
Here are the most interesting ones:
- GPS Tracker: this app has a nice readout on its screen of the location data (see top left screenshot above) and was therefore most helpful in trying to figure out the hooks. I signed up for a device key on the InstaMapper website so that my location data could be uploaded to their site. Due to the override of the location accuracy, the GPS tracker shows "tracking" on its screen (it doesn't matter what you set the slider at), but it only seems to send the location data to their servers once (right after I start the application). The data on the iPhone screen is however updated continuously.
- Google Earth: this app also displays the fake latitude and longitude data after pressing the little bulls eye in the lower left corner. Also here, the data is only updated once (when you press the bulls eye). Make sure to turn the latitude/longitude display on under the settings in Google Earth. The altitude shown is actually not related to the CoreLocation altitude as it is the altitude for the zoomlevel of the satellite image that is active.
- GPS Ally: this app shows the current location data on its screen as well (see top right screenshot above), but here also, the data is only updated once (after starting the app). You can re-update it manually by hitting the "Update On/Off" button in the lower left corner twice.
- Trailguru: this app also shows the latitude, longitude and altitude/elevation (see the bottom center screenshot above), but doesn't seem to use the speed data (probably because it was written for firmware < 2.2). Here again, the actual app doesn't seem to use the changing CoreLocation data even though the values are changing on its screen. An interesting thing is however that if you press on the "Map" icon at the bottom, the center of the map does move around according the the fake data the CoreLocation framework is fed.
So now for the less good news...
I am currently stuck as I haven't figured out how to tell an app that new CoreLocation data is available so that e.g. the GPS tracker app will continuously use the new data and send a new point to its servers. The same for Google Earth, GPS Ally and Trailguru.
What I think is that we need to do something with the CoreLocationManager framework and/or the CoreLocationManagerDelegate framework and their delegates. We would need to somehow tell the CoreLocationManager object of the app that the CoreLocation object (which I am succesfully feeding fake location data) has a new data set so that it will actually use that new data.
So I am counting on some help from you in getting this figured out as I have pretty much run out of ideas.
You can do some reading around in Apple's documentation and on the forums to see if we can find what needs to be done.
I have also uploaded the source code for the CoreLocation hook here. If you wish to try it out, make sure to have Toolchain 2.2 installed (if you have Toolchain < 2.2 installed, just comment out the speed hooks and any other ones that the compiler complains about in the source code). Also make sure to install MobileSubstrate through Cydia on your device and also put the libsubstrate.dylib file into your filesystem library directory on your desktop so the compiler can find it. Make sure to "ldid -S" the ExampleHook.dylib file after it is put in /Library/MobileSubstrate/DynamicLibraries on the phone. You can take a look at the Makefile as most of the process is automated in it.
If it turns out to be possible and we do find the solution, it will be great news as it means that we can use our iGPS360 module with the majority of the AppStore apps!
38 comments:
This is absolutley fantastic! Unfortunatley, I'm not an in-depth programmer, or I would help. I really can't wait when a polished version comes out.
Wow, I was looking forward for this... This will make iGPS360 even cooler!!
I am definitely a non-programmer, but from the little I understand going over the example code here are my 2-cents:
It seems like you are overriding the system calls and just doing the obvious update to the relevant variable (member of the object). Maybe the calls are more sophisticated and they use some sort of timestamps or some flag updates and by overriding the way you did you are simply skipping those steps. Maybe a better way is that the overriding function as a first step calls the original system function and then does the update.
Cheers.
I'm sorry, maybe I didn't understand what you're trying to say, but if you look at the documentation in xcode, and then type LocationManager, isn't there a "start updating location" or something similar? and isn't there a property called "distanceFilter" or something similar again? I repeat, maybe I didn't understand what you're trying to say, but I think these two elements are useful for what you're trying to do...
Beautiful! I'm not a programmer and I can not help you, but I hope that you will succeed! You are fantastic guys! $ 75 well spent!
wow... really really congrats for this hack!! I'll see if I can follow the guide and check what I can do with it!
Thanks sooo much!
saludos! bye! :D
@anonymous and @vik: the CLLocation class does have a timestamp property which can be successfully faked, but this did not seem to matter for the app. The distanceFilter is a property of the CLLocationManager class. However, it is not clear when this class (and thus the hook) gets accessed. The only hooks I tried are property hooks. I still need to figure out how to override and instance method. Maybe someone has code for this?
@GPS: Yes, I did see the timestamp, but this was not what I meant. Since we do not know what are the inner workings of the system calls, maybe by overriding them you may be skipping some crucial steps that they are making (timestamping was a simple suggestion, but it may be doing many other stuff that we simply can't know). My suggestion was therefore to first call the original system call - I saw this was possible in the example - that way you can be sure all the voodoo it does runs, and after it returns your hook changes the right properties. So in your code this would basically mean to add a line at the beginning of every method calling the original method.
Like I said, I am not a programmer (but I do understand some a bit), and I don't have a running toolchain to try out some code. But, here is a code snippet that should implement (if I understood the tutorial) my suggestion:
static CLLocationCoordinate2D __$ExampleHook_CLLoc_coordinate(CLLocation (ExampleHook) *_CLLocation) {
// NOTE: the (Example Hook) in the line above should be in triangular brackets only the blogger comments cannot accept these as it this they are html tags.
// launch original:
[_CLLocation __OriginalMethodPrefix_launch];
CLLocationCoordinate2D _coordinates;
_coordinates.latitude = (CLLocationDegrees) (34.69+ 0.001 * rand() / (((double) RAND_MAX +1 )));
_coordinates.longitude = (CLLocationDegrees) (-107.773735 + 0.001 * rand() / (((double) RAND_MAX +1 )));
}
Hope this helps.
ok, but if you look at the documentation, you see that you can implement your own class and then make it the delegate of CLLocationManager simply writing the protocol (triangular brackets)CLLocationManagerDelegate(close triangular brackets) just after the superclass of your own class...
For example:
@interface MyClass : NSObject (triangular brackets)CLLocationManagerDelegate(close triangular brackets) {
}
@end
simple as that.. and then in this class you can implement the methods of the delegate, i.e.:
override the
- (id) init {
[super init];
[self setDelegate:yourDelegate];
[self setDistanceFilter:yourDistance];
[self startUpdatingLocation];
}
that's it (I think).
Let me know if it works..
Just an idea, I realize the dev-team guys are crazy busy and Chronic-dev the same, but myabe they could offer some guidance. They seem to know the guts of the iphone and touch better then most.
@anonymous: I tried what you mentioned, but it doesn't work; crashes the app. Note that these hooks are property hooks and they only change the value of a variable.
@Vik: the problem is that the app has already defined its LocationManager and LocationManagerDelegate so I can't just define my own.
I need to find out how to send the app's LocationManager a message that the location data has been updated from the CoreLocation hooks.
The LocatonManager usually has code like this:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
so we need to figure out how to trigger this event.
I think the key is to make delegate hook work to catch the pointer to the delegate, then you could use it to call back the application code by sending - (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation when you want to update the location
I can't understand really what you want but if you need to send a message to the app's location manager... well if the location manager is defined as a variable in the appDelegate class, you can still retrieve it from any point in any class you want, and then send a message to it.. but only if it's defined in the appDelegate class as a variable... do you know if it's defined in the appDelegate class?
sorry for the double comment, I understood what you're trying to do by reading the post again... maybe my last post could be still useful?
@vik and @anonymous: so the question is indeed, how do we get the pointer to the CLLocationManager from within the CLLocation class.
This would be such a nice thing and makes the GPS Modul much more attractive ;-)
maybe some project like ispaxio could help.
How would i go about installing the files provided. ? do i need to compile something?
@Nate: install MobileSubstrate through Cydia on your device and then put the ExampleHook.dylib file in /Library/MobileSubstrate/DynamicLibraries on the phone. Run "ldid -S" on the ExampleHook.dylib and you should be good to go (install e.g. GPS tracker and run it).
If you no longer want the hook, just delete the ExampleHook.dylib file. Post if you have any succes.
Is this the real deal?With this copy/paste I can really have all apps functionality?There is a new app from sygic coming out, that really is the real deal.Will it work with this hack?
Impressive work, looking forward to see some progress here.
Just an observation. I try to load the ExampleHook.dylib on my iphone 2G, the one coming in the zip file. I start the standard maps application of the iphone. It locates me at the random coordinate provided by the Hook. Interesting is that if I lock the screen and then unlock (maps app still running) the location point briefly move twice. So the Hook is working and the iphone is updating the movements.
Now my question is why the position indicator remain in the "target" shape and do not turn into the flashing blue dot as in the iphone 3G, see the video http://www.apple.com/iphone/features/maps.html
1) Is the fake accuracy too low or some parameter are missing and the iphone do not turn from "position estimation" to "tracking"?
2) Are there some restriction/differece on the iphone 2G/3G that do not allow the 2G to do "tracking" but only "position estimation". For example iTunes complain when I try to install "Geotags" saying the application is not compatible.
Can someone with an iphone 3G thy to run this Hook? What is the result?
Just my 2 cents :)
@nico: that's a very good point you make. I don't have a 3G phone... on the 2G you can keep on hitting the little bulls-eye button in the left lower corner and the app will keep on tracking the random hook coordinates (moving the map around).
If someone with a 3G phone could try out the hook and let us know if it tracks or not.
Any news?
Is there any new development?
Looks like the new sdk will allow us to communicate with the serial port in the dock connector and bluetooth!
What does the iphone 3.0 firmware's ability to have bluetooth conductivity do to this GPS project? I imagine that any bluetooth GPS receiver will soon work with the iphone.
Of course, this also means that getting external gps data to apps should be resolved as well.
@GPS: I installed your hook at my iPhone 3G and google maps does not flash the blue dot like it normally does when you get normal GPS signal, the position indicator remains in the "target" shape. So I think its not "tracking" and just "estimating the position".
I need to hook this function too to fix the gps lat/long as my position is a little moved to the left and there is no option like calibrate to fix this.
If you need more information about running this on iPhone 3G, please let me know.
@Plak and @Lucas: thanks for the update Lucas. What you are reporting is actually good news in the sense that it is not something specific to the 2G iPhone that is not working since the iPhone 3G behaves the same :-) We just need to figure out what the code is to get the phone to "track". The hook actually just generates random lat/lon coordinates around a fixed point (see the source code). So the position it gives is not related at all to your actual location. If it is, it might be using the WiFi (just turn WiFi of and see what it does).
@Labrugice: indeed, legitimate serial port access will be good for additional applications that work with the GPS module. The questions is of course if Apple requires an authentication chip in the accessories or not. It would be best if they simply enable read/write access to the serial port with no restrictions.
@DK: Regarding bluetooth, from the answers that Apple gave, it looks like they are only going to unlock certain capabilities of the bluetooth hardware and on certain devices. Especially, for the iPod Touch 1G and the 2G iPhone, bluetooth use will most likely be limited judging from their answers.
Regarding impact on this project, I will keep on producing the module as long as people want it. The iGPS360 module is a very small direct plug-in with excellent performance, directly powered from the iPhone/iPod. I guess each GPS receiver has its own advantages and disadvantages, so in the end it will come down to the choice of the consumer.
@PmgR: This is great news. Keep us posted! What's the situation on the iControlPad?
I am new to this blog, having bought my new iPod Touch 2G after my old 1G got bricked by downgrading from 3.0 to 2.2.1. As a iPhone developer with access to OS 3.0, I highly suggest that you study closely the API enhancements and accessory communication with external devices in order to enhance the work on your product... probably even releasing it as a legal product.
This might be a stupid question but... I put over the file and in mobile terminal i tried ldid'ing the file, however it says command not found (ldid -S ExampleHook.dylib). Is it because I don't have 2.2 toolchain (where do I get this, I can only find 2.0?)
Okay, as it turns out, intalling 2.0 toolchain did enable the cmd, however everything crashes now. calendar, sms, maps, you name it. If i delete ExampleHook.dylib everything works fine again. :(
Hey guys, as a person lightyears away from programming I don't want to interrupt you. Just want to say that iGPS360 ist really great and your attempt here is even cooler! If I could use apps from the AppStore I would be very happy! Keep on!
Some news?
iPhone OS seems to provide an oppurtunity for this topic. Or is "Made for iPhone" a problem?
How is the chance that mobile substrate is changed in 3.0 such that AppStore App connection isn't possible?
Any news?
Did this project come to an end?
There is a new Cydia release called iDA. It it a complete (off-line) GPS program. The problem is that it is only for iphone 3G. Is there any way we can get it working in iphone 2G?
Just asking
Where are the files????
I get a 404 ERROR for the link you provided:
http://www.orangegadgets.com/MobileSubstrate/
/Tommy
Fantastic indeed. Sad for me because im not really the in depth in programming. Im still practicng my scripting.
Post a Comment