Open Maps app from Code - Where/How to find the "Current Location"? - iphone

I am opening Maps app to show directions from user's Current Location to a destination coordinate, from my code. I am using the following code to open the Maps app. I am calling this code when a button is pressed. getCurrentLocation is a method that returns the recently updated location.
- (void)showDirectionsToHere {
CLLocationCoordinate2D currentLocation = [self getCurrentLocation]; // LINE 1
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f",
currentLocation.latitude,
currentLocation.longitude,
destCoordinate.latitude,
destCoordinate.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
Here [self getCurrentLocation] in LINE 1 uses CLLocationManager to determine the Current Location and returns the value.
Note: I have not yet implemented the code in LINE1. I've just planned to do it that way.
My questions are:
Is this good practice to calculate the Current Location, at the time the Maps app is called?
Will [self getCurrentLocation] return the Current Location before openURL gets called?
Do I have to determine the Current Location well before opening the Maps app?
I am little bit confused about these things. Kindly guide me. Thanks.

You don't have to determine the user's current location yourself, the Maps app will take care of it.
Instead of passing a latitude/longitude pair you can pass Current%%20Location and Maps will determine the user's current location itself.
%20 is a url-encoded space character, and the extra % escapes the actual % so it won't be interpreted as a format substitution.
Thanks to #Carlos P for pointing out my escape character blunder in the original answer.

Using "Current Location" as saddr only works if the user has the system language set to English. The best options is really to get the current position from Core Location and use that as saddr.

As pazustep pointed out, "Current Location" works only for English. In Italian, for example, the correct string is "Posizione attuale".
Sniffing in the iPhone firmware I detected all the "Current Location" translations and I wrote a class that provides the correct string needed for any (currently) supported language.
There's a post about this (source code included) on my blog: http://www.martip.net/blog/localized-current-location-string-for-iphone-apps.

You can use the new MKMapItem class for iOS 6. See the Apple API docs here
Basically, you will use something like this, if routing to destination coordinates (destCoordinate):
MKPlacemark* place = [[MKPlacemark alloc] initWithCoordinate: destCoordinate addressDictionary: nil];
MKMapItem* destination = [[MKMapItem alloc] initWithPlacemark: place];
destination.name = #"Name Here!";
NSArray* items = [[NSArray alloc] initWithObjects: destination, nil];
NSDictionary* options = [[NSDictionary alloc] initWithObjectsAndKeys:
MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsDirectionsModeKey, nil];
[MKMapItem openMapsWithItems: items launchOptions: options];
In order to support both iOS 6+ and pre iOS 6 in the same code, I'd recommend using something like this code that Apple has on the MKMapItem API doc page:
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
// iOS 6 MKMapItem available
} else {
// use pre iOS 6 technique
}
This would assume that your Xcode Base SDK is iOS 6 (or Latest iOS).
In this other answer, I offer a robust technique for iOS 5.1 and lower

Related

Detecting programmatically an installed app

I am trying to detect installed Instagram on my device , formerly I used this code to detect an app , but it seems it does not work with iOS 6 or non-JB devices :
NSString *filePath = #"/Applications/Instagram.app";
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
[self checkingInstalledApp];
}
else
{
NSLog(#"no instagram installed");
}
I check this question but his answer gives me a lot errors ! any solution ?
This is invalid code for two reasons.
1) It attempts to interact with an area outside of its sandbox.
2) It relies on an undocumented implementation detail (Perhaps the install location has moved or the application name has changed?)
What you need to do is use the canOpenURL: method on UIApplication to determine if the system can launch an application via its custom scheme (note: If the App has no custom scheme then you are out of luck)
Custom URL Scheme Opening instagram://, followed by one of the following parameters, will open our app and perform a custom action.
For example, for camera, you would direct users on the iPhone to the
custom URL instagram://camera.
NSURL *instagramURL = [NSURL URLWithString:#"instagram://location?id=1"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
[[UIApplication sharedApplication] openURL:instagramURL];
}
From Instagram iPhone Hooks

iphone default map app open with different language

I successfully open Iphone default app with current user location but if user has selected a different language (e.g.. for Dutch Current Location = Aktueller Ort) then current location and route is totally wrong.
NSString *mystr=[[NSString alloc] initWithFormat:#"http://maps.google.com/maps?saddr=Current+Location&daddr=Destination"];
NSURL *myurl=[[NSURL alloc] initWithString:mystr];
[[UIApplication sharedApplication] openURL:myurl];
Although we can detect current language and match using switch case but we need to translate "Current Location" to all supported languages by iphone map app.
I tried wiki link for parameters and found hl parameter but not worked for me I think method for apply parameter by me is wrong or something.
So how can I open map app with particular fix language like english even when user selected different language?
thanx for any help!
You can get the current user location by the Core Location Framework and pass latitude and longitude to the google maps url. Or you can check the current language and translate "Current Location" in a lot of lang and pass it to the url.
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];

Link to pdf within app

I've got an iOS app that at one point opens a link to a website in a webview. These links are kept in a plist file (so it is easy to maintain them as the app evolves). What I want to do next is to also link to PDF's (or any picture of text file format, of even a html format, this is flexible) that are kept within the app. And I would like to do this as much as possible from within the existing app structure. So, is it possible to create a link that can be put in the plist as a web-link, but instead opens a file on the device itself (possibly in the webview)? And how would I go about that? Any ideas?
Thanx in advance for your help!
You will need to create the links at runtime. I would suggest having a certain prefix to a local url, such as mylocalfile:filename. Then, in the code that loads the plist, check for the prefix and create the link when necessary. You could also just create these links once and store them in a separate file, then load that instead of the original.
NSArray *links = nil; //I assumed your plist is an array. Change to dictionary if required
NSString *pathToStoredFile; //Get the path for the file you create with the updated links
if([[NSFileManager defaultManager] fileExistsAtPath:pathToStoredFile]) {
links = [NSArray arrayWithContentsOfFile:pathToStoredFile];
} else {
NSArray *tmp = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ListOfLinks" ofType:#"plist"]];
if(!tmp) {
//handle error
}
NSMutableArray *tmpLinks = [[NSMutableArray alloc] initWithCapacity:[tmp count]];
for(NSString *link in tmp) {
if([link hasPrefix:#"mylocalfile:"]) {
link = [link substringFromIndex:12]; //12 is the length of mylocalfile:
NSURL *url = [[NSBundle mainBundle] urlForResource:[link stringByDeletingPathExtension] withExtension:[link pathExtension]];
[tmpLinks addObject:[url absoluteString]];
} else [tmpLinks addObject:link];
}
links = [tmpLinks copy];
[tmpLinks release];
[links writeToFile:pathToStoredFile atomically:NO];
}
Yes, I would go with a UIWebView. iOS should be able automatically handle certain URL handlers and your app can register to handle the rest, as necessary.
iOS knows how to handle certain file types already. For example, if Safari (or a UIWebView) encounters http://somesite.com/afile.pdf, it know which apps can handle the file type. Another example is a phone number: skype://8005555555. iOS knows to open Skype and pass the number to it. iOS also knows that iBooks can handle PDf files.
Register your app for the appropriate file handlers and types. Then, users can tap and hold on the link to see a menu of available apps to handle the link. If it's a link that's only used by one app, the user doesn't even need to hold, a tap will suffice.
As far as making a link pointing to a local file, you can, and you would use the C function NSDocumentsDirectory() and append that to a url handler. (Example: http://NSDocumentsDirectory()/filename.pdf)

Mapping data from RSS feed with no latitude/longitude using MapKit

Having follow the tutorial at http://mithin.in/2009/06/22/using-iphone-sdk-mapkit-framework-a-tutorial/ to integrate the MapKit into my application. However, I want to be able to display an annotation for a dynamic "incident" on the map. Here's where I'm having problems.
Basically my apps an RSS reader, and it downloads everything and saves each item of the feed (as in Story 1, Story 2) as currentItem. The data I want to grab and use to map the annotation can be found under currentItem.title - but I can't seem to get it to work in this tutorial's code or find the right place to put it.
The RSS feed I'm using doesn't have any latitude/longitude information either - making it even harder.
Any help would be great - I've been working on this for a couple of days now with still no luck.
UPDATE: I'm even considering launching the Google Maps application instead showing the annotation. But this in itself is raising issues. Below is the code I'm using but its throwing errors everywhere.
NSString *title = currentItem.title;
int zoom = 13;
NSString *stringURL = [NSString stringWithFormat:#"http://maps.google.com/maps?q=%##%1.6f,%1.6f&z=%d", title, zoom];
NSURL *url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
In the end I just mapped the title using reverse lookup, and added the country afterwards so results would only be in the country where the address is. Not ideal, but it seems to work OK.

Using tel: url to initiate a call doesn't return control

I have an app that worked just fine in version 2.2.1 of the iphone, but have ran into an issue when I upgraded my dev iphone to 3.1.2. Before, dialing a number worked fine, as when the call was ended, my application was loaded. Now, after I hit end call, it loads the default phone application. Does anybody know why this is? I've looked at the diff's from sdk 2.x to 3.x and can't find any reason why this would change. Thanks
This was indeed changed from 3.0 to 3.1. If you need the "prompt-for-call" and "relaunch-app-after-call" there are 2 work-arounds:
Option 1: Create a UIWebView and load your tel: URL.
// assuming you have an ivar to store a weak reference to a UIWebView:
// UIWebView *phoneCallWebView;
- (void) dialPhoneNumber:(NSString *)aPhoneNumber
{
NSURL *phoneURL = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#",aPhoneNumber]];
if ( !phoneCallWebView ) {
phoneCallWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
}
[phoneCallWebView loadRequest:[NSURLRequest requestWithURL:phoneURL]];
}
- (void) dealloc
{
// cleanup
[phoneCallWebView release], phoneCallWebView = nil;
[super dealloc];
}
Option 2: Initiate your call with with the telprompt:<number> URL scheme instead of tel:<number>. Note that this is an undocumented API feature, but it's what UIWebView uses when you tap on a phone number link in a webview (or in MobileSafari). If you are targeting iPhone >= 3.0, there are not any problems using telprompt: (tel: and telprompt: are identical on 3.0). I'm not sure about iPhone OS 2.x.
In general, option 2 works and is easier, but option 1 is actually a "legal" workaround. Unfortunately, there does not seem to be a way to separate the "prompt-for-call" and "relaunch-after-call" behaviors. On iPhoneOS >= 3.1, you can either get both, or neither.
Yes, Apple changed this behavior from 3.0 to 3.1 (I believe, could also be from 2.x to 3.0). They have acknowledged that the change was deliberate and not a bug. There is no workaround that I know of. You just have to live with it a file an enhancement request if you think the old behavior should be made available again.
But both UIWebView and telepump will introduce a "pop up box" require user to confirm if user would like to dial the number. I am wondering if there are some solutions that could get rid of "pop up box" Thank you.
NSURL* url = [[NSURL alloc] initWithString:[NSString stringWithFormat:#"telprompt:%#",[SLUser sharedInstance].ivrNumber]];
[[UIApplication sharedApplication] openURL:url];