I am using a UIWebView control and opening a web page URL on it in landscape mode only. In this URL on a particular event a PDF is getting opened. This time the PDF is not getting opened properly (it always shows only first page of the PDF file), and in the Output window i am getting "flatedecode decoding error".
Is there any way so that my application can catch that PDF opening event, and I can open the PDf in Safari or some other browser rather than UIWebView?
Or is there any way in Phonegap to achieve this?
I guess you only need a way to find out whether the specific link opening the PDF is clicked or not?
Make sure you make your viewcontroller a delegate for the webview. Then implement this method
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
navigationType will be UIWebViewNavigationTypeLinkClicked when a new page loads on link click.
request will tell you the URL being opened and you can listen if the URL is one of your PDF. If it is then you can handle it in the method however you want to - download it and open in another web view or open in safari.
More details here.
You can save PDF in your document directory by using this code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachePath = [paths objectAtIndex:0];
BOOL isDir = NO;
NSError *error;
//You must check if this directory exist every time
if (! [[NSFileManager defaultManager] fileExistsAtPath:cachePath isDirectory:&isDir] && isDir == NO)
{
[[NSFileManager defaultManager] createDirectoryAtPath:cachePath withIntermediateDirectories:NO attributes:nil error:&error];
}
NSString *filePath = [cachePath stringByAppendingPathComponent:#"QRScanner.pdf"];
//webView.request.URL contains current URL of UIWebView, don't forget to set outlet for it
NSData *pdfFile = [NSData dataWithContentsOfURL:webView.request.URL];
if(pdfFile)
{
[AppDelegate obj_appDelegate].Alertview.hidden = YES;
[[AppDelegate obj_appDelegate].activity stopAnimating];
}
[pdfFile writeToFile:filePath atomically:YES];
Related
Hi Friends I am Trying to create annotation of PDF page as something like bellow image in my app and this annotation is visible to all other PDF reader
For example:-
I create PDF document in My app and Add Annotation then i send this Document to My Friend Mail. Then my Friend Download this PDF and Open in to Preview App of Mac then this created Annotation of PDF that should be display.`
I doing RND of This stuff and Also Read iOS provide Doc about Quartz 2D. I successful read and create PDF using this Quartz 2D but now not getting any way to doing Annotation stuff.
I also study those kind of SO questions:-
Create PDF Annotations in iOS
Create PDF Annotations with Quartz (iOS)
pdf annotations in objective-c
I also done Annotation withing the App Reading PDF and store Point of x and y potion of Layer drage in to particular PDF page. Now issue is that what about when i send this PDF document to other user who open this Document in others PDF reader?
I also Discuss this SO chat Group. one of Stack-overflow User suggest me to Using CGLayer for doing this task But i am much Confused how to achieve this stuff and how to implement this.
Please Help me and Guide Me on this stuff.
The answer is simply no, you cannot create standard PDF annotations using the iOS APIs. The CGPDF* API is read-only and it can be used only to read PDF file and the CoreGraphics API with PDF context can only create simple PDF pages without annotations, form fields, bookmarks, etc.
If you create new PDF files you can switch to libHaru which supports annotations but if want to add annotations to existing PDF files you're out of luck (libHaru cannot load PDF files). There is also IFXPDFFactory but it is under development and I do not know if it supports annotations yet.
First I don't know is it only because of complexity that people suggest the costly PDF iOS libraries out there or they are promoting them by commenting that this and that cannot be done without prior testing.
You can add and save annotations in the pdf file and even export it.
NSURL *OriginalPdfPath = [[NSBundle mainBundle] URLForResource:#"yourPDFname" withExtension:#"pdf"];
NSString *string=[OriginalPdfPath path];
NSError *error;
//Load original pdf data:
NSData *pdfData = [NSData dataWithContentsOfFile:string options:NSDataReadingUncached error:&error];
if (error)
{
NSLog(#"%#", [error localizedDescription]);
return;
}
else {
NSLog(#"Data has loaded successfully.");
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pathLD = [documentsDirectory stringByAppendingPathComponent:#"dirName"]; // get directory
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:pathLD])
{
[fileManager createDirectoryAtPath:pathLD withIntermediateDirectories:YES attributes:nil error:nil];
}
pathLD = [pathLD stringByAppendingPathComponent:#"yourPDFname.pdf"]; // add file path
BOOL isDir;
if (![fileManager fileExistsAtPath:pathLD isDirectory:&isDir]) {
BOOL didsave=[fileManager createFileAtPath:pathLD contents:pdfData attributes:nil];
}
NSURL *url = [NSURL fileURLWithPath:string];
CGPDFDocumentRef document = CGPDFDocumentCreateWithURL ((__bridge_retained CFURLRef) url);
size_t count = CGPDFDocumentGetNumberOfPages(document);
if (count == 0)
{
NSLog(#"PDF needs at least one page");
return;
}
// Now work with the pdf File
UIGraphicsBeginPDFContextToFile(pathLD , CGRectZero, nil);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGPDFPageRef page = CGPDFDocumentGetPage (document, 1);
CGRect paperSize = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
UIGraphicsBeginPDFContextToFile(pathLD , CGRectZero, nil);
UIGraphicsBeginPDFPageWithInfo(paperSize, nil);
// Flip the context so that the PDF page is rendered right side up.
CGContextTranslateCTM(currentContext, 0.0, paperSize.size.height);
CGContextScaleCTM(currentContext, 1.0, -1.0);
CGContextDrawPDFPage (currentContext, page);
// Magic function here : Render the layer of the annotations view in the context
[drawingView.layer renderInContext:currentContext];
UIGraphicsEndPDFContext();
CGPDFDocumentRelease (document);
This saves all that you render in current pdf context back to the File Manager
you can test that with a model View display VC on a WebView:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self displayPdfinWebView];
}
-(void)displayPdfinWebView {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory =[paths objectAtIndex:0];
NSString *pathLD = [documentsDirectory stringByAppendingPathComponent:#"dirName"]; // get directory
pathLD = [pathLD stringByAppendingPathComponent:#"yourPDFname.pdf"]; // add file path
NSFileManager *fileManager = [NSFileManager defaultManager];
NSData *data;
NSURL* pdfUrl;
if ([fileManager fileExistsAtPath:pathLD])
{
pdfUrl = [NSURL fileURLWithPath:pathLD];
[webView loadRequest:[NSURLRequest requestWithURL:pdfUrl]];
}
}
I guess you can connect to iBooks with UIDocumentInteractionController for exporting.
My references is ApplePDF Drawing .
I want to load a webpage when user connected to network and store it offline(including with images/resources). If the user not connected to any network then i should load the previously stored webpage. I have tried NSData dataWithContentsOfURL:(NSURL *)url and NSString stringWithContentsOfURL but these stores only html content not the resources.
Thanks in advance.
You can do that with ASIHttpRequest. If you do not want to to use that project (it is no longer active) you can look into the code and what it does. Look at "how to cache a whole web page with images in iOS" for more info as well.
I think the simple solution is this - "Safari Client-Side Storage and Offline Applications Programming Guide", https://developer.apple.com/library/archive/documentation/iPhone/Conceptual/SafariJSDatabaseGuide/Introduction/Introduction.html
Only if you are making an app with HTML5 and webview, didn't test this method yet so far, so it might work.
Write this data into file using:
-(void)writeDataToFile:(NSString*)filename
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
if(filename==nil)
{
DLog(#"FILE NAME IS NIL");
return;
}
// the path to write file
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat: #"%#",filename]];
/*NSData *writeData;
writeData=[NSKeyedArchiver archivedDataWithRootObject:pArray]; */
NSFileManager *fm=[NSFileManager defaultManager];
if(!filePath)
{
//DLog(#"File %# doesn't exist, so we create it", filePath);
[fm createFileAtPath:filePath contents:self.mRespData attributes:nil];
}
else
{
//DLog(#"file exists");
[self.mRespData writeToFile:filePath atomically:YES];
}
NSMutableData *resData = [[NSMutableData alloc] init];
self.mRespData=resData;
[resData release];
}
and load it next time.
I don't know if there is one-line-solution like myWebView.cache4Offline = YES; , but I fear as long as you don't have access to the website's code (i.e. if you want to make any website available offline inside your app), you have to program this on your own. Thinking about it, it doesn't seem so difficult:
Scan the html string for image urls (and everything else you need)
Download those resources from the internet using NSData dataWithContentsOfURL (maybe a little annoying, because of relative/absolute URLs)
Save data to file with NSData writeToFile:options:error:
Replace URL in HTML with filePath from 3. (OR, better use a convention for converting their URLs in your file-URLs)
Hope it helps
I have stored a file (pdf) in the "documents" directory and I would like to know how could be possible to detect if there are applications (app) installed in the mobile device that can open this file (for example, "pdf" files can be opened using "iBooks", "DropBox", ...). I would like to detect this before calling the method "presentOpenInMenuFromRect"; which shows a list of the possible applications that can handle a specific file. The desired behavior is:
1) Given a pdf stored in the "Document" directory, check if there are "app's" installed in the iPhone/iPad, which can open this file (iBooks, DropBox, ...). This is what I do not know how to do.
2) If no application in de iPhone/iPad can open the application, then do nothing, otherwise draw a "Save" button and then, if the user presses this "Save" button, then the "presentOpenInMenuFromRect" method will be called in order to show a list of possible app which can open that file. I know the way to present a list of of applications which can open a file; here are the source code:
The source code related to the "Save" button is:
- (void) saveFile:(UIWebView*)webView
{
NSString* fileName = [[NSFileManager defaultManager] displayNameAtPath:webView.request.URL.absoluteString];
#if DEBUG
NSLog(#"<%p %#: %s line:%d> File name:%#", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __PRETTY_FUNCTION__, __LINE__, fileName);
#endif
NSURL* fileurl = [NSURL URLWithString:webView.request.URL.absoluteString];
NSData* data = [NSData dataWithContentsOfURL:fileurl];
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* docsDirectory = [paths objectAtIndex:0];
NSString* filePath = [docsDirectory stringByAppendingPathComponent:fileName];
[data writeToFile:filePath atomically:YES];
NSURL* url = [NSURL fileURLWithPath:filePath];
//UIDocInteractionController API gets the list of devices that support the file type
docController = [UIDocumentInteractionController interactionControllerWithURL:url];
[docController retain]; //Very important, if "retain" is not called, the application crashes
//Present a drop down list of the apps that support the file type,
//clicking on an item in the list will open that app while passing in the file.
BOOL isValid = [docController presentOpenInMenuFromRect:CGRectZero inView:webView animated:YES]; //Using "webView" instead of "self.view"
if (!isValid)
{
[self showAlertSaveFileError:fileName]; //Shows an alert message
}
}
Thanks in advance.
Note: The response time of calling the method "presentOpenInMenuFromRect" is about several seconds, so this is the reason why I would like to know if there is a another way to detect and get a list of possible app installed on the mobile device which can open a specific file (pdf, ...)
Check out ihasapp.
http://www.ihasapp.com/
it says that it is an iOS framework that lets developers detect apps that are currently installed on their users' devices.
I have a hybrid (Objective C + HTML) application and I would like to be able to periodically save a remote file (images and css) to a user's device but in such a way that it can be loaded by a browser within a webview instance in the same application.
I don't think it's possible to save files to the resource bundle itself (though in the simulator you can), so I assume I would have to save the file somewhere else. But I'm not sure what path to use where the HTML document could still access it.
Basically, I'd like to do something like this:
NSURL* url = [NSURL URLWithString:#"http://myserver.com/August.png"];
NSString* filePath = #"[?????]/MonthlyImage.png";
NSData* data = [NSData dataWithContentsOfURL:url];
if (data)
{
NSError* error;
if ([data writeToFile:filePath options:NSDataWritingAtomic error:&error])
{
NSLog(#"Wrote");
}
if (error != nil)
{
NSLog(#"ERROR: %#", [error description]);
}
}
Then in my webview, I'd like to be able to load the image like this:
<img src="[??????]/MonthlyImage.png" />
What values can I use in place of the ?????? that will work? Is it even possible?
Saving to the bundle is not allowed because it is not allowed to modify the app binary.
You could try and store the file in the documents folder, then retrieve it from there. The important point, to make it work, is specifying also a baseURL when creating the UIWebVIew.
You can retrieve the documents directory in this way:
NSString *documentsDirectory = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([paths count] > 0) {
documentsDirectory = [paths objectAtIndex:0];
}
Then you store there your file, and when you want to load it in your UIWebView, execute:
[_label loadHTMLString:htmlString baseURL:[NSURL fileURLWithPath:documentsDirectory]];
Now, <img src="MonthlyImage.png" /> will look for the png in your documents directory.
I have some local html files in resources.on launch one html,say a.html, is loaded in webview. there are some hyperlinks in that webview(or say the html content) which are links to other html files in my resources.now on click of those links I want to open them in in-app browser.
how to do this.
Any idea????
thnx!!!!
I've not tried this, but it might work!
Create your UIWebView and load the first html file from your bundle
NSString *file = [[NSBundle mainBundle] pathForResource:#"a" ofType:#"html"];
NSString *html = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:[NSString stringWithFormat:#"<html><head></head><body>%#</body></html>", html] baseURL:baseURL];
webView.delegate = self;
Then get when the user taps a link
-(BOOL)webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if (inType == UIWebViewNavigationTypeLinkClicked) {
// Find which link is selected, get the file and load it into the UIWebView
}
return YES;
}