Updating PhoneGap’s ChildBrowser Plugin to Handle Local Files

Recently, I have been working on an iPad sales tool application with Shawn Crowley and Marissa Christy. We are using a framework called PhoneGap to build the application. PhoneGap allows us to write the majority of the app using HTML and JavaScript.

HTML and JavaScript have been excellent for 95% of the application, but these two features are more cleanly implemented using the built-in iOS widgets.

  1. Email Support
  2. PDF Display Support

It turns out that our needs for this functionality are not uncommon.

Matt Kane created a github project called phonegap-plugins that solves both of these problems.

https://github.com/phonegap/phonegap-plugins.git

Thanks for the plugins Matt, they have been a great help.

We used the EmailComposer plugin to solve the email support feature and the ChildBrower plugin to solve the pdf display support feature. The EmailComposer plugin solved our need with no additional changes. The ChildBrowser plugin, however, needed to be slightly modified to fit our use-case.

The ChildBrowser plugin allows external webpages to be displayed within a PhoneGap application. This is exactly the functionality we wanted to render our pdf files, but the ChildBrower plugin was designed to load external files not local files that are distributed with the app.

We made the following additions to the ChildBrower plugin to allow it load local pdf files.

Client JavaScript Code:

// load the child browser with the full path of our pdf relative to the root of our xcode project
window.plugins.childBrowser.showWebPage("www/assets/folder/file.pdf");

Updated ChildBrowserCommand.m:


- (void) showWebPage:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options // args: url
{  
  if(childBrowser == NULL)
  {
    childBrowser = [[ ChildBrowserViewController alloc ] initWithScale:FALSE ];
    childBrowser.delegate = self;
  }
  
  /* // TODO: Work in progress
  NSString* strOrientations = [ options objectForKey:@"supportedOrientations"];
  NSArray* supportedOrientations = [strOrientations componentsSeparatedByString:@","];
  */

  PhoneGapViewController* cont = (PhoneGapViewController*)[ super appViewController ];
  childBrowser.supportedOrientations = cont.supportedOrientations;
  [ cont presentModalViewController:childBrowser animated:YES ];
  
  NSString *path = (NSString*) [arguments objectAtIndex:0];
  
  // ADDED Code
  // This breaks apart the path and uses the pathForResource method to correctly find the resource
  // in the bundle.
  NSString *ofType = [path pathExtension];
  NSString *pathForResource = [[[path lastPathComponent] componentsSeparatedByString:@"."] objectAtIndex:0];
  NSString *inDirectory = [path stringByDeletingLastPathComponent];
  
  NSString *url = [[NSBundle mainBundle] pathForResource:pathForResource 
                          ofType:ofType 
                          inDirectory:inDirectory];
    
  [childBrowser loadURL:url];

}

Updated ChildBrowserViewController.m


- (void)loadURL:(NSString*)url
{
  NSLog(@"Opening Url : %@",url);

  imageURL = @"";
  isImage = NO;
  // ADDED Code
  // use fileURLWithPath method instead
  NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:url]];
  [webView loadRequest:request];

  webView.hidden = NO;
}
Conversation
  • Ben Rousch says:

    I’m curious about why you went with PhoneGap for mobile development over Appcelerator Titanium. If you find the time, would you post about how you made the decision?

  • Hi Ben. We selected PhoneGap because we inherited the codebase and it already used PhoneGap. That being said I have been very happy with PhoneGap and would use it again. Personally, I do not know as much about Appcelerator Titanium, but I heard that it is also good.

  • Alex says:

    Hi Michael. I’m trying to implement this code in the project I am doing and I’m not too sure where to put window.plugins.childBrowser.showWebPage(“www/assets/folder/file.pdf”);
    I am guessing somewhere in the childbrowser.js file but I’m not too sure where. Any help would be hugely appreciated.
    Cheers.

  • Hi Alex,

    The showWebPage method is part of ChildBrowser and is defined in the childbrowser.js file. In order to call this method you need to include childbrowser.js in your code, and follow the instructions in the ChildBrowser repository to install. After this is complete you can call the window.plugins.childBrowser.showWebPage(“www/assets/folder/file.pdf”) method in your javascript. For example, you could register for a click event on a button and then popup the ChildBrowser with this call.

  • Greg Hudy says:

    Michael –
    I am trying to incorporate your updated ChildBrowser plugin code. It is working great showing a PDF but what also happens is that it shows a line of white text across the PDF which is what I am assuming is the link to the PDF – it displays file:///var/mobile/Applications/F621…..

    Any ideas what that is and how to get rid of it?
    Thanks!

  • Hi Greg,

    The white text is a label in the view. I removed it in my code by removing the label from the NIB file, and then removing the references in the code.

    I did not discuss that change in this blog post.

  • Greg Hudy says:

    Thanks for the tip –
    I also found in ChildBrowserViewController.m that I could just comment out the line that is setting the text then I added this after it:
    //addressLabel.text = request.URL.absoluteString;
    addressLabel.text = @””;

  • Mike Trampe says:

    Greg- I’m having trouble with the computer, need your help, [email protected] thanks!!!!

  • Darren Ehlers says:

    Actually, the reason the label is displaying in the middle of the screen is because the layout was setup for the iPhone screen (not the iPad screen).

    I went in and changes the values for some of the locations…specifically, in the ChildBrowserViewController.xib, here’s the new lines:

    Line 142:
    {{10, 680}, {984, 26}}

    and Line 173:
    {{994, 683}, {20, 20}}

    These changes will move the label down to the bottom (just above the Done button) and will also move the loading animation to the right of that same line.

  • Chris says:

    This is great – thank you for outlining the steps/changes for this!

    Any chance anyone playing w/this has figured out how to make the background transparent/opaque instead of black? I’d like to only give ChildBrowser a portion of my screen – not 100% of it!

  • Mike P. says:

    Very useful post, Thanks!

    I was able to take your code and easily get ChildBrowser to load both local pdfs and http web urls throughout various screens in my app (using PhoneGap 1.0).

    The only issue for me is how to use the Safari “compass” icon in the ChildBrowser window when displaying a local PDF file. Safari does not open the local PDF when the compass is clicked… would like to at least have iBooks open the PDF… or it would even be good to have a print function in ChildBrowser in it’s place.

  • ralph says:

    hi!
    yes, child browser open with the codes changes from above pdfs docs and so on.
    (using latest phone gap and child browser)
    but what what if i want to open a remote webpage and using child browser? at the moment nothing happens – it opens the safari or it misses the xib. – any ideas?
    thank you!!

  • James King says:

    Once the childbowser is open, how do you close it and return to the original application?

  • Hi James,

    The ‘done’ button calls ‘closeBrowser’ in ChildBrowserViewController.m. The ‘closeBrowser’ method calls a delegate that has been attached to the ‘onClose’ method in ChildBrowserCommand.m. This method calls back into Javascript land. The ‘closeBroswer’ method next calls ‘dismissModalViewControllerAnimated’ to close the view.

    Calling ‘closeBrowser’ in ChildBrowserViewController.m should handle what you looking to do.

  • Enrico says:

    Hello,
    this tutorial is very usefull for me but i do not understand how to fit the 100% of the available space on ipad with this plugin.
    i do not find where change the dimension from the xib file for scale the browser to fit with ipad desing. i didn’t find the of Darren Ehlers post
    Line 142:
    {{10, 680}, {984, 26}}

    and Line 173:
    {{994, 683}, {20, 20}}
    wich is the original value for finding it in the newest file version?

    https://github.com/phonegap/phonegap-plugins/blob/master/iPhone/ChildBrowser/ChildBrowserViewController.xib

    there no way to permorm this operation directly from xcode?

    Thank you for your time.
    Enrico

    • Hi Enrico,

      I am confused by your question.

      I thought by default the plugin was full screen.

      Are you seeing something different?

  • enrico says:

    Hi Mike,
    thank for your reply.
    Yes the plugin is full screen but the webview just fit for iphone not for ipad, my question regarding this matter.
    how can do for fit the webview, and the file displayed, for the largest window of ipad
    by code or manually in xcode or like in the Darren Ehlers post?

  • enrico says:

    Hi Mike,
    thank for your reply.
    Very usefull, i’ll take a look.
    i’ll think could be more easiest, just open the xib with dashcode and change manually the references of the dimension of the frame. but i’m not uderstand exactly where for change the main windows dimensions.

  • Enrico says:

    Hello,
    the pdf file allowed to pass parameters as a url for open it at a specific page or set the zoom, ecc, for example in this way:
    pdfile.pdf#page=1&zoom=100

    is it possible made a change to the plugin for attached also some parameters for opening the pdf file?

    Actualy doesn’t works because i think the plugin searching in the local folder for the path pdfile.pdf#page=1&zoom=100 and do not find the file.

    Thanks

    • Interesting question Enrico.

      I believe that you are correct. Passing those extra parameters will most likely not work with the current code in the plugin.

      Is it possible to hack the plugin to find the file and then append the parameters before you load it?

  • enrico says:

    Thanks Mike,
    I think the same thing, find the file and a extra parameters. A way for call the file by command line but i do not know how to do this.

  • enrico says:

    Thanks Mike,
    I think the same thing, find the file and a extra parameters.

    A way for call the file by command line but i do not know how to do

  • enrico says:

    Thanks Mike,
    I think the same thing, find the file and a extra parameters.
    A way for call the file by command line but i do not know how to do this.

    • I would try loading the URL and then modifying the URL with the URLByAppendingPathComponent instance method.

      Good luck.

    • Luca says:

      Has anyone figured out how to add extra parameters to the URL of the pdf (whatever.pdf#show=200)?

  • Brian McIntosh says:

    What about printing? Childbrowser works great for opening PDFs, but I can’t figure out how to print a PDF from Childbrowser.

    • Hi Brian,

      I am not sure how you would do printing through Childbrowser.

      My guess is that you could add logic to send the loaded PDF to the printer, but I am unsure how printing works in IOS.

      Mike

      • Andrew Mitchell says:

        I’ve got code to handle Printing from a UIWebView,and it works just fine when I put it in a test App, but once I integrate it into ChildBrowser, the App crashes when the Print system is called and it goes to display the Print sheet. I expect that the View Hierarchy created by PhoneGap/ChildBrowser is to blame since the exact same code works just find outside of PhoneGap. If I get it working, I’m more then happy to share the code as its not that much code (minimum implementation is less then 10 lines).

  • enrico says:

    HI,
    i’ve some question for adding extra functions to ChildBrowser
    There’s a way for hidden / remove the back button by code?
    There’s a way for clear the cache of the webview for do not display the previos page visited with ChildBrowser?

    I tried to solve by myself but i’m not able to do it.

    Thanks for your help!

  • Chris says:

    Thank you very much for sharing your helpful work!
    At the moment i keep running into a “the requested url was not found on this server” error when loading a local HTML or a PDF file – (PhoneGap 1.2 + latest version of ChildBrowser).
    I tried setting a breakpoint in ChildBrowserCommand.m (Line 205) – it tells me: url = NSString
    Any ideas would be cery appreciated …

    Thanks,
    Chris

    • Hi Chris,

      I put this tutorial together over a year ago. I am unsure if it will still work with the latest PhoneGap and ChildBrower plugin.

      You might want to check if the resource you are trying to load is included in the project and compiled into the app?

      Good luck.

      Mike

      • phobox says:

        Confirmed. It does work with the latest (at this moment in time) Cordova 1.9.0;

        Thanks Mike!

        -F

  • Sneha says:

    Hello,
    Thank you so much for ur Post…
    I want to show(view) PDF using child-browser but for “Window phones”.

    Plz let me know how it can be done

    Thanks

    • Hi Sneha,

      I do not know how to show PDFs using Windows Phone.

      Let me know if you figure it out. Good luck.

      Mike

  • Just wanted to say thanks for this info, very helpful ; )

  • Steve says:

    Thanks so much; this absolutely worked! For info, I am using PhoneGap 1.7 and these instructions were a huge help. Thanks again!

  • kmxz says:

    Thanks. But is there any way to solve this under Android Phonegap?

    • I have not solved this problem for Android, but I am sure it’s possible. If you figure out how please post it back :)

      • mustafa says:

        Thanks for this useful tutorial Mike. It worked fine for me. But I have to make same app for Android. Now I’m very busy but I will try a javascript solution as soon as possible. If it works, I will let you know.

  • Gregor Gabriel says:

    I digged in this stuff and finally found a suprising answer in the following answer:

    + http://stackoverflow.com/questions/9998509/phonegap-1-5-childbrowser-cant-show-local-file

    It turned out that the ChildBrowser Plugin can display local content as it is without any modification.
    Just use valid URLs eg. file:///content/app%20ios/Documents/myfile.pdf and not
    file:///content/app ios/Documents/myfile.pdf (notice the blank!)

    That’s all

  • Chong Eva says:

    This works on Cordova 2.0! After looking through so many websites and failed tests for so many days, this finally solves my problem. Finally get to open local PDFs using ChildBrowser.
    Tried iFrames, HTML embed.. those can’t work, you can’t scroll the PDFs in iOS devices with those methods. But this solves it!
    Thanks for posting this method up!

  • But the problem viewing local pdf in application by using childbrowser in android .how to resolve it any help? thamks in advance.

  • Comments are closed.