I'm packaging a mobile website (over the network) in PhoneGap and would like to intercept links pointing to PDF's and open them using the ChildBrowser plugin. Is it 1: possible to trigger ChildBrowserfrom native code (I've already determined which links to intercept) and 2: is AppDelegate.m, .shouldStartLoadWithRequest() the right place to do it? And in that case: 3: how to correctly call ChildBrowser from native code?
I've tried this admittedly naive approach:
return [self exec:#"ChildBrowserCommand.showWebPage",
[url absoluteString]];
but it only resulted in an error along the lines of ...'NSInvalidArgumentException', reason: '-[AppDelegate exec:]: unrecognized selector sent to instance.
(PS: I'm aware this approach isn't ideal practice, but this project is only priced for 2 days work)
If you added (Child Browser) plugin classes in plugin folder then you have to play with the appDelegate.m file, #import "ChildBrowserViewController.h"
For example your html file has following html/javascript code, like this
window.location="http://xyz.com/magazines/magazines101.pdf";
To execute this url in Child Browser, you need to modify native shouldStartLoadWithRequest: method for request url which contain pdf extension files.
/**
* Start Loading Request
* This is where most of the magic happens... We take the request(s) and process the response.
* From here we can re direct links and other protocalls to different internal methods.
*/
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
NSURL *url = [request URL];
if([request.URL.absoluteString isEqualToString:#"about:blank"])
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
if ([[url scheme] isEqualToString:#"gap"]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
} else {
NSString *urlFormat = [[[url path] componentsSeparatedByString:#"."] lastObject];
if ([urlFormat compare:#"pdf"] == NSOrderedSame) {
[theWebView sizeToFit];
//This code will open pdf extension files (url's) in Child Browser
ChildBrowserViewController* childBrowser = [ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
childBrowser.modalPresentationStyle = UIModalPresentationFormSheet;
childBrowser.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[super.viewController presentModalViewController:childBrowser animated:YES ];
NSString* urlString=[NSString stringWithFormat:#"%#",[url absoluteString]];
[childBrowser loadURL:urlString];
[childBrowser release];
return NO;
}
else
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
}
thanks,
Mayur
Anyone looking for android equivalent, put below code inside shouldOverrideUrlLoading
ChildBrowser childBrowser = new ChildBrowser();
childBrowser.cordova = this;
childBrowser.showWebPage(url, null);
Related
I'm trying to get access token from Google,Yahoo.But I'm getting an error like WACloudAccessControlClient may not respond to setToken.How to declare setToken method here.
-(BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
if(_url)
{
/* make the call re-entrant when we re-load the content ourselves */
if([_url isEqual:[request URL]])
{
return YES;
}
[_url release];
}
_url = [[request URL] retain];
NSString* scheme = [_url scheme];
if([scheme isEqualToString:#"acs"])
{
// parse the JSON URL parameter into a dictionary
NSDictionary* pairs = [self parsePairs:[_url absoluteString]];
if(pairs)
{
WACloudAccessToken* accessToken;
accessToken = [[WACloudAccessToken alloc] initWithDictionary:pairs];
[WACloudAccessControlClient setToken:accessToken];
[self dismissModalViewControllerAnimated:YES];
}
return NO;
}
[NSURLConnection connectionWithRequest:request delegate:self];
return NO;
}
Any ideas? Thanks in advance.
You need to pass the message to an object not a class name so first get a reference to an object.
I'm not sure what is your usecase, just look at WACloudAccessControlClient api it will have some init or ...with... methods to create or get a reference to an object of the class.
This:
[WACloudAccessControlClient setToken:accessToken];
Should be something like (the init... method is made up, please replace with actual one):
[[WACloudAccessControlClient initSomethingSomehow] setToken:accessToken];
Are you after something like this?:
[[WACloudAccessControlClient accessControlClientForNamespace:#“namespace-name”
realm:#“realm-name”]
setToken:accessToken];
Edit:
Have a look at this example of how to interact with wa toolkit for iOS I've just skimmed through but it seems to have answers you are looking for.
I am receiving a description text in HTML format, and I am loading it in a webview, if a link clicked in the description so I load it in separate view controller. But shouldStartLoadWithRequest giving a some appended link. here is my code
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if(navigationType == UIWebViewNavigationTypeLinkClicked) {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
WebsiteViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"WebsiteViewController"];
vc.url = request.URL.absoluteString;
NSLog(#"link is : %#", [[request URL] absoluteString]);
[self.navigationController pushViewController:vc animated:YES];
return false;
}
return true;
}
it prints this
link is : applewebdata://038EEEBF-A4C9-4C7D-8FB5-32056714B855/www.yahoo.com
and I am loading it like this
[webViewDescription loadHTMLString:description baseURL:nil];
As you are using loadHTMLString and you are setting baseURL to nil therefore applewebdata URI scheme is used by iOS instead of the “http” in URIs used for accessing internal resources on the device. You could try setting the baseURL
I had a similar issue. In practice, setting the baseURL to 'http://' or something like that wasn't working for me either. I also only saw the applewebdata scheme about 50% of the time, the other 50% of the time I saw the correct scheme I was expecting.
To resolve this, I ended up intercepting -webView:shouldStartLoadWithRequest:navigationType: callbacks and using a regular expression to strip out Apple's applewebdata scheme. Here's what it ended up looking like
// Scheme used to intercept UIWebView callbacks
static NSString *bridgeScheme = #"myCoolScheme";
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
BOOL shouldStartLoad = YES;
NSURL *requestURL = request.URL;
// Strip out applewebdata://<UUID> prefix applied when HTML is loaded locally
if ([requestURL.scheme isEqualToString:#"applewebdata"]) {
NSString *requestURLString = requestURL.absoluteString;
NSString *trimmedRequestURLString = [requestURLString stringByReplacingOccurrencesOfString:#"^(?:applewebdata://[0-9A-Z-]*/?)" withString:#"" options:NSRegularExpressionSearch range:NSMakeRange(0, requestURLString.length)];
if (trimmedRequestURLString.length > 0) {
requestURL = [NSURL URLWithString:trimmedRequestURLString];
}
}
if ([requestURL.scheme isEqualToString:bridgeScheme]) {
// Do your thing
shouldStartLoad = NO;
}
return shouldStartLoad;
}
I have made a plugin for the iphone which is working fine. I can call all the native methods. I also made a custom view (.xib file) which i want to load. But i can't figure out how to do this with phonegap in the way.
Normally i would do something like:
[self addSubView:myView2];
But this doesn't work.
Anyone any idea how to load and display a custom made .xib file when using phonegap??
Have you used Child browser plugin so far, this plugin also contain ChildBrowserViewController.xib . So to call another xib in your Phonegap you need to modify your- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
method in appDelgate.m file.
Some how in your HTML and javascript code, you need to provide special link (using href or window.location method) that you need to handle in shouldStartLoadWithRequestmethod, import your #import MyCustomViewController.h in your appDelegate.m file.
Please have look at the following snippet-
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
NSURL *url = [request URL];
if([request.URL.absoluteString isEqualToString:#"about:blank"])
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
if ([[url scheme] isEqualToString:#"gap"]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
else {
NSString *urlFormat = [[[url path] componentsSeparatedByString:#"."] lastObject];
if ([urlFormat compare:#"xib"] == NSOrderedSame) {
[theWebView sizeToFit];
MyCustomViewController* customVC = [ [ MyCustomViewController alloc ] initWithScale:FALSE ];
customVC.modalPresentationStyle = UIModalPresentationFormSheet;
customVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[super.viewController presentModalViewController:customVC animated:YES ];
[customVC release];
//return YES;
return NO;
}
else
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
}
thanks,
mayur
I have an app in the process of upgrading to the iOS5 SDK and Phonegap 1.0.0
The Childbrowser plugin is working properly, but when a link to the iTunes app store is clicked - the link is opened in a Childbrowser window.
I would prefer it to open in Appstore directly, which is what happens if I do not use the ChildBrowser plugin.
This is the appstore link (points to a submit a review page within the appstore)
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=386470812&pageNumber=0&sortOrdering=1&type=Purple+Software&mt=8
and this is how AppDelegate is modified
AppDelegate.m, scroll way down and replace the following:
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
}
with this:
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:
(NSURLRequest *)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if ([[url scheme] isEqualToString:#"gap"] || [url isFileURL]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
else {
ChildBrowserViewController* childBrowser =
[ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
[super.viewController presentModalViewController:childBrowser
animated:YES ];
[childBrowser loadURL:[url description]];
[childBrowser release];
return NO;
}
}
I used the method outlined in this blogpost to get the Childbrowser up and running
http://iphonedevlog.wordpress.com/2011/09/24/installing-childbrowser-into-xcode-4-with-phonegap-1-0-mac-os-x-snow-leopard/
Any thoughts on how to change this to produce the desired action?
Many thanks..
You need to check whether your URL contain http://itunes.apple.com/ as a substring by using rangeOfString: method and location attribute.
Please confirm your javascript called the url like this, window.location="http://itunes.apple.com/us/app/code-check-basic-free-medical/id386470812?mt=8"; or you can use any jquery method.
Please replace shouldStartLoadWithRequest: method with the following snippet.
/**
* Start Loading Request
* This is where most of the magic happens... We take the request(s) and process the response.
* From here we can re direct links and other protocalls to different internal methods.
*/
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:
(NSURLRequest *)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
if ([[url scheme] isEqualToString:#"gap"] || [url isFileURL]) {
return [ super webView:theWebView shouldStartLoadWithRequest:request
navigationType:navigationType ];
}
else {
//here we will check whether urlString has http://itunes.apple.com/ as substring or not
NSString* urlString=[url absoluteString];
if ([urlString rangeOfString:#"http://itunes.apple.com/"].location == NSNotFound){
ChildBrowserViewController* childBrowser = [ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
childBrowser.modalPresentationStyle = UIModalPresentationFormSheet;
childBrowser.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[super.viewController presentModalViewController:childBrowser animated:YES ];
[childBrowser loadURL:urlString];
[childBrowser release];
return NO;
}
else
return YES;
}
}
thanks,
Mayur
I'm trying to use the ASIWebPageRequest to load a local html file so that I can use the built-in caching in ASIWebPageRequest. I know this might sound a bit pointless however I want to use remote images in my local files that only get updated once a week or so. If that makes sense.
Here is what I'm doing in code:
//OUTPUT: file:///Users/ledixonuk/Library/Application%20Support/iPhone%20Simulator/4.3.2/Applications/FDF21331-CC80-4ECB-9A33-16AEC073D117/Documents/ItemOne.html
NSURL *fileUrl = [[NSURL alloc] initFileURLWithPath:[FileSystemHelper dataFilePathInDocuments:#"ItemOne.html"]];
// Assume request is a property of our controller
// First, we'll cancel any in-progress page load
[[self webRequest] setDelegate:nil];
[[self webRequest] cancel];
[self setWebRequest:[ASIWebPageRequest requestWithURL:fileUrl]];
[[self webRequest] setDelegate:self];
[[self webRequest] setDidFailSelector:#selector(webPageFailed:)];
[[self webRequest] setDidFinishSelector:#selector(webPageFinished:)];
// Tell the request to replace urls in this page with local urls
//[[self webRequest] setUrlReplacementMode:ASIReplaceExternalResourcesWithLocalURLs];
// Tell the request to embed external resources directly in the page
[[self webRequest] setUrlReplacementMode:ASIReplaceExternalResourcesWithData];
// It is strongly recommended you use a download cache with ASIWebPageRequest
// When using a cache, external resources are automatically stored in the cache
// and can be pulled from the cache on subsequent page loads
[[self webRequest] setDownloadCache:[ASIDownloadCache sharedCache]];
// Ask the download cache for a place to store the cached data
// This is the most efficient way for an ASIWebPageRequest to store a web page
[[self webRequest] setDownloadDestinationPath:[[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:[self webRequest]]];
[[self webRequest] startAsynchronous];
And here is the error I'm getting:
404 Not Found
Not Found
The requested URL /Users/ledixonuk/Library/Application Support/iPhone Simulator/4.3.2/Applications/FDF21331-CC80-4ECB-9A33-16AEC073D117/Documents/ItemOne.html was > not found on this server.
Obviously the ASIWebPageRequest can not find the ItemOne.html file in the application document folder, however I've double checked and the file is definitely there.
Has anyone else had a similar issue to this? It's driving me mad trying to sort it out!
ASIWebPageRequest is a subclass of ASIHTTPRequest, and unfortunately ASIHTTPRequest doesn't support fetching file: URLs - only http and https ones.
Basically you have all the code you need, you just need to find a way to plumb it together. You could create a subclass of ASIHTTPRequest that can load file: URLs (essentially provide your own implement of startAsyncronous that instead just calls back the delegates after setting up the right data files), or create a subclass of ASIWebPageRequest that does it. I've not yet thought about it in detail so I have no idea which way would be best.
(I think you're seeing the 404 page as ASIHTTPRequest is managing to contact a web server somewhere - perhaps it's trying to fetch from http://127.0.0.1/Users/ledixonuk/Library/....)
See below the simple implementation I have added to my subclass of ASIHTTPRequest in order to support file:// based URLs. It's by no means complete and possibly missing some properties that should be set and it will not invoke all the delegates but for my own purposes this was enough.
- (void)startRequest
{
if ([url isFileURL])
{
// ASIHTTPRequest does not support handling file:// URLs, this is my own simple implementation here
if ([self isCancelled]) {
return;
}
[self performSelectorOnMainThread:#selector(requestStarted) withObject:nil waitUntilDone:[NSThread isMainThread]];
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
NSString *filePath = [url path];
BOOL isDirectory = NO;
if ([fileManager fileExistsAtPath:filePath isDirectory:&isDirectory] && !isDirectory)
{
responseStatusCode = 200;
[self setRawResponseData:[NSData dataWithContentsOfFile:filePath]];
[self setContentLength:rawResponseData.length];
[self setTotalBytesRead:[self contentLength]];
}
else
{
responseStatusCode = 404;
[self setContentLength:0];
[self setError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIFileManagementError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:#"Cannot open file at path '%#'",filePath],NSLocalizedDescriptionKey,error,NSUnderlyingErrorKey,nil]]];
}
complete = YES;
downloadComplete = YES;
[self requestFinished];
[self markAsFinished];
}
else
{
// let the original implementation deal with all the other URLs
[super startRequest];
}
}