I have working Objective-C code that uses ScriptingBridge to make Safari open a URL. Something like:
#import "Safari.h" /* created by executing "sdef /Applications/Google\ Chrome.app | sdp -fh --basename GoogleChrome" */
if ((safariApp = [SBApplication applicationWithBundleIdentifier:#"com.apple.Safari"]) == nil) {
NSLog(#"couldn't access Google Chrome");
} else {
NSString *theUrl = [NSString stringWithUTF8String:"http://www.ford.com"];
NSDictionary *theProperties = [NSDictionary dictionaryWithObject:theUrl forKey:#"URL"];
SafariDocument *doc = [[[safariApp classForScriptingClass:#"document"] alloc] initWithProperties:theProperties];
[[safariApp documents] addObject:doc];
}
I'd like to create similar code that will do the same thing for Chrome instead of Safari. Obviously I need to change "Safari.h" to "GoogleChrome.h" and "com.apple.Safari" to "com.google.Chrome". I'm not sure how to change the last three lines - there's no definition of "GoogleDocument" in GoogleChrome.h
GoogleChromeApplication *application = [SBApplication applicationWithBundleIdentifier:#"com.google.Chrome"];
GoogleChromeWindow *window = [[[application classForScriptingClass:#"window"] alloc] initWithProperties:nil];
[application.windows addObject:window];
window.activeTab.URL = #"http://www.example.com";
[window release];
[application activate];
The only way I found to get what you need is with AppleScript.
NSString *script = #"tell application \"Google Chrome\" to \
open location \"http://www.ford.com\"";
NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource: script];
[appleScript executeAndReturnError:nil];
This works with Safari and Firefox as well (of course you need to change \"Google Chrome\" with \"Safari\" or \"Firefox\").
Related
I'm quite frustrated with an issue I'm experiencing that Is coming with a lack of information. I'm unable to locate any information regarding my issue and I'm starting to believe It isn't possible what I want to do. Here is my issue and thank you for reading.
I would like for a button on my ViewController to open Apple Maps from Longitude and Latitude coordinates that are stored in my Sqlite database Tables. I have been able to successfully do this by adding a MapView. I want to reproduce this function and have the user be able to click "Get Directions" button and It will popup the Apple Maps app with the end address setup automatically. By using #"finishLat" and #"finishLng" I'm able to collect the database information. Is this possible when using the Apple URL Scheme?
This is a sample of what the Mapview does with the information. The only part I want from this is the #"finishLat" and #"finishLng". I will also need to use the "Run" feature as well to collect the correct address.
[super viewDidLoad];
CGRect bounds = self.view.bounds;
mapview = [[MapView alloc] initWithFrame:CGRectMake(0, 0, bounds.size.width, bounds.size.height)];
[self.view addSubview:mapview];
NSArray *result = [_runs objectForKey:#"results"];
NSDictionary *arr = [result objectAtIndex:0];
arr = [arr objectForKey:#"run"];
NSMutableArray *arrPlaces = [[NSMutableArray alloc] init];
NSArray *arrDirvers = [arr objectForKey:#"drivers"];
for (int i =0; i < [arrDirvers count]; i++) {
NSDictionary *asdfg = [arrDirvers objectAtIndex:i];
Place *startPt = [[Place alloc] init];
Place *endPt = [[Place alloc] init];
NSString *temp = [asdfg objectForKey:#"startLat"];
startPt.latitude = [temp floatValue];
temp = [asdfg objectForKey:#"startLng"];
startPt.longitude = [temp floatValue];
startPt.name = [asdfg objectForKey:#"name"];
temp = [asdfg objectForKey:#"finishLat"];
endPt.latitude = [temp floatValue];
temp = [asdfg objectForKey:#"finishLng"];
endPt.longitude = [temp floatValue];
endPt.name = [asdfg objectForKey:#"name"];
[arrPlaces addObject:startPt];
[arrPlaces addObject:endPt];
This is what I have.
- (IBAction)GetDirections:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://maps.apple.com/?q"]];
}
Rather than using openURL: you can create an instance of MKMapItem and use openInMapsWithLaunchOptions:. You can supply the MKLaunchOptionsDirectionsModeKey option to request directions from the users current location.
Alternatively, use openMapsWithItems:launchOptions: to navigate between 2 known locations.
To open in the Apple Maps app use:
- (IBAction)GetDirections:(id)sender
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: #"http://maps.apple.com/?ll=<lattitude>,<longitude>"]];
}
If you want to open Apple Maps to a driving directions screen, you will need to use this url:
http://maps.apple.com/?saddr=<origin>&daddr=<destination>
You can also set one of these to be "Current%20Location" to use the user's current location.
I'm trying to send via MFMailComposeViewController a custom url scheme so that the receipient could tap on the embedded link and open my application on his iphone.
So far the receipient gets an email but nothing happens when he taps on the LINK.
here is the code:
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self; // <- very important step if you want feedbacks on what the user did with your email sheet
[picker setSubject:#"Incoming task"];
// Fill out the email body text
NSString * types = #"";
for(NSString *type in task.location_types){
types = [types stringByAppendingFormat:#"%#|",type];
}
if(types.length > 1){
types = [types substringToIndex:types.length - 1];
}
NSString *desc = [task.description stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *link = [NSString stringWithFormat:#"helpy://?taskid=%d&desc=%#&types=%#\"",task.TaskId,desc,types];
NSString *emailBody = [NSString stringWithFormat:#"TAP HERE<script type=\"text/javascript\" charset=\"utf-8\">function doSomething() { window.location = \"%#\;return false;}</script>",link];
[picker setMessageBody:emailBody isHTML:YES];
picker.navigationBar.barStyle = UIBarStyleBlack;
[controller presentModalViewController:picker animated:YES];
[picker release];
helpy://?taskid=..... is my custom registered URL Scheme and if I type it from the address bar of the browser it opens up my application on the iPhone.
For some reason when this link is embedded into email, tapping it does not do anything.
Any help?
thanks
I highly doubt that Mail will execute JavaScript on iOS (even on the desktop I highly doubt it, but haven't tried it though). Simply set the URL as the href attribute of your hyperlink and everything should work fine. Any reason why you want to do it with JavaScript? I'm just curious ;-)
NSString *link = [NSString stringWithFormat:#"helpy://?taskid=%d&desc=%#&types=%#\"",task.TaskId,desc,types];
NSString *emailBody = [NSString stringWithFormat:#"TAP HERE", link];
Here is a strange problem: My app should be able to call the built in Maps in iOS (both 5.1 and 6). Turns out that it works just fine under iOS6 but not under iOS5.1. The maps in iOS6 is called and the directions from saddr to daddr is traced but when I am in iOS5 the maps app is called but just one pin is put at the daddr. For some unknown reason the initial coordinates (saddr) are not showing and no direction is traced.
Here is my code:
addr = [NSString stringWithFormat: #"maps://saddr=%f,%f&daddr=%f,%f", newLocation.coordinate.latitude, newLocation.coordinate.longitude, oldLatitude, oldLongitude];
NSURL *url = [NSURL URLWithString:addr];
[[UIApplication sharedApplication] openURL:url];
I have tried change the URL to "http://maps.google.com/something" but it calls Safari instead of built in Maps app. I have noticed that the variables are being passed properly to the URL.
Any ideas?
Thanks in advance!
I had a similar problem and I had to create some conditional OS code to deal with the fact that the Google Maps application has been removed. From the new MKMapItem Reference
//first create latitude longitude object
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude,longitude);
//create MKMapItem out of coordinates
MKPlacemark* placeMark = [[MKPlacemark alloc] initWithCoordinate:coordinate addressDictionary:nil];
MKMapItem* destination = [[MKMapItem alloc] initWithPlacemark:placeMark];
if([destination respondsToSelector:#selector(openInMapsWithLaunchOptions:)])
{
//using iOS6 native maps app
[destination openInMapsWithLaunchOptions:#{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving}];
}
else
{
//using iOS 5 which has the Google Maps application
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=Current+Location&daddr=%f,%f", latitude, longitude];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: url]];
}
[placeMark release];
[destination release];
To get walking directions:
For iOS 6 maps - You can set MKLaunchOptionsDirectionsModeWalking instead of MKLaunchOptionsDirectionsModeDriving
For Google maps - Add &dirflg=w to the url.
I think it's better to use the openInMapsWithLaunchOptions in iOS6 because it gives you complete control over how the maps application will respond.
You can use MKPlacemark and MKMapItem to launch the Maps app with both a coordinate and a title on the map pin:
NSString *pinTitle;
CLLocationCoordinate2D coordinate;
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate addressDictionary:#{(id)kABPersonAddressStreetKey: pinTitle}];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
if ([mapItem respondsToSelector:#selector(openInMapsWithLaunchOptions:)])
{
[mapItem openInMapsWithLaunchOptions:#{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving}];
}
else
{
// Google Maps fallback
NSString *urlString = [NSString stringWithFormat:#"http://maps.google.com/maps?daddr=%f,%f&saddr=Current+Location", locationItem.coordinate.latitude, locationItem.coordinate.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
Note that you'll need to link against AddressBook.framework and also add #import <AddressBook/AddressBook.h> somewhere in your code to make use of the kABPersonAddressStreetKey constant.
In the application I'm creating, I load a long page of HTML into a webView and then print it to a PDF using the following:
-(void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
{
if ([frame isEqual:[[self doc] mainFrame]])
{
NSMutableData *newData = [[NSMutableData alloc] init];
NSPrintInfo *newInfo = [NSPrintInfo sharedPrintInfo];
NSView *docView = [[[[self doc] mainFrame] frameView] documentView];
NSPrintOperation *newPrintOp = [NSPrintOperation PDFOperationWithView:docView insideRect:docView.bounds toData:newData printInfo:newInfo];
BOOL runPrint = [newPrintOp runOperation];
if (!runPrint)
{
NSLog(#"Print Failed");
}
PDFDocument *newDoc = [[PDFDocument alloc] initWithData:newData];
[newData release];
[self setPdf:newDoc];
//Other code here
}
}
The problem is that when I look at newDoc, it is a huge PDF of a single page. What I would prefer would be the printing acting the same as it does from the "save as PDF..." dialog - that is, splitting the PDF into multiple reasonably-sized pages.
Does anyone know how to accomplish this?
I attempted inserting the following after NSPrintInfo *newInfo = [NSPrintInfo sharedPrintInfo];
[newInfo setVerticalPagination:NSAutoPagination];
[newInfo setHorizontalPagination:NSAutoPagination];
NSAutoPagination is described in the docs as the following:
NSAutoPagination
The image is divided into equal-sized rectangles and placed in one column of pages.
Available in Mac OS X v10.0 and later.
Declared in NSPrintInfo.h.
This had no effect on the printed PDF.
You get a file with one large page because + PDFOperationWithView: method doesn't support pagination at all. For that reason calling - setVerticalPagination: or - setHoriziontalPagination: doesn't change anything.
You could try use "classical" + printOperationWithView:printInfo: method, configure it to save PDF to temporary location and then create PDFDocument with contents of obtained file. I hope that fragment of code below will help.
NSMutableDictionary *dict = [[NSPrintInfo sharedPrintInfo] dictionary];
[dict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
[dict setObject:temporaryFilePath forKey:NSPrintSavePath];
NSPrintInfo *pi = [[NSPrintInfo alloc] initWithDictionary:dict];
[pi setHorizontalPagination:NSAutoPagination];
[pi setVerticalPagination:NSAutoPagination];
NSPrintOperation *op = [NSPrintOperation printOperationWithView:[[[webView mainFrame] frameView] documentView] printInfo:pi];
[pi release];
[op setShowsPrintPanel:NO];
[op setShowsProgressPanel:NO];
if ([op runOperation] ){
PDFDocument *doc = [[[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath: temporaryFilePath]] autorelease];
// do with doc what you want, remove file, etc.
}
Here is the code:
- (IBAction) charlieImputText:(id)sender {
NSAppleScript *keystrokeReturn = [[NSAppleScript alloc] initWithSource:#"tell application \"System Events\" to keystroke return"];
[keystrokeReturn executeAndReturnError:nil];
[progressBarText startAnimation:self];
charlieImputSelf = [sender stringValue];
NSAppleScript *sendCharlieImput = [[NSAppleScript alloc] initWithSource:[NSString stringWithFormat:#"tell application \"Terminal\" to do shell script %#", charlieImputSelf]];
[sendCharlieImput executeAndReturnError:nil];
NSDictionary* errorDict;
NSAppleScript* script=[[NSAppleScript alloc]
initWithContentsOfURL:[NSURL fileURLWithPath:#"/applications/jarvis/scripts/getTextCharlieResponce.scpt" ]
error:&errorDict];
NSAppleEventDescriptor* desc=[script executeAndReturnError:&errorDict];
NSString* result=[desc stringValue];
self.charlieOutput.stringValue = result;
charlieOutput.textColor = [NSColor greenColor];
[script release];
[progressBarText stopAnimation:self];
}
Ok what this does is it sends what's ever in the text field to terminal and displays terminal's response on a text label. However, this does not work the way I want it to. It does not send the user input to terminal. Any ideas?
You need to quote the argument to do shell script. Also, this depends on there being a directory at the path /Applications/jarvis/scripts, which is kind of odd though not impossible.
First: Does charlieImputSelf the value you expect?
Second: try passing an NSError into your [sendCharlieImput executeAndReturnError:nil]; Do something like:
NSAppleEventDescriptor * ourRes = [theScript executeAndReturnError: &errorDict];
if (ourRes == nil)
{
// error...
[NSApp activateIgnoringOtherApps: YES];
showNSAlert( #"AppleScript error", [errorDict valueForKey:NSAppleScriptErrorMessage]);
}
(I'll leave you to provide the implementation of showNSAlert, or just use NSLog here...)