Monthly Archives: October 2012

PDF Generation using UIPrintPageRenderer

AirPrint enabled printers accept PDF files and UIPrintPageRenderer prints that content to PDF file. Hence UIPrintPageRenderer can draw to PDF context though there are none public API provided to use this functionality. In this post we will explore this possibility.

There are several StackOverFlow question which talk about how to use private API to achieve pdf generation utilizing UIPrintPageRenderer:

Is there any way to generate PDF file from a XML/HTML template in iOs
Generating a PDF using the new printing stuff in iOS 4.2
How to pretend to be a Printer on iOS like the Apps Save2PDF or Adobe® CreatePDF?

In this post we have employed the methods explained in above stack overflow questions. Following steps lead to PDf generation from simple text, html or a view:

1) Create a Print Formatter: This is basically the content you want to generate PDF with. A print formatter can be an instance of UISimpleTextPrintFormatter, UIMarkupTextPrintFormatter, or UIViewPrintFormatter. These allow to create pdf with simple text, html or a view respectively.

NSString *html = @”<b>Hello <i>World!</i></b>”;

UIMarkupTextPrintFormatter *fmt = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html];

2) Assign print formatter to UIPrintPageRenderer: Once you have created your print formatter add it to UIPrintPageRenderer at proper index. Method addPrintFormatter:startingAtPageAtIndex: allows any print formatter to be added. One has to pass appropriate index as well.

UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];

[render addPrintFormatter:fmt startingAtPageAtIndex:0];

3) Assign paperRect and printableRect: There is no public API to assign these values hence we need to use setValue:forKey: to assign these values. First we calculate the proper CGRect for these values and then use setValue:forKey: to assign these.

CGRect page;

page.origin.x=0;

page.origin.y=0;

page.size.width=792;

page.size.height=612;

CGRect printable=CGRectInset( page, 0, 0 );

[render setValue:[NSValue valueWithCGRect:page] forKey:@”paperRect”];

[render setValue:[NSValue valueWithCGRect:printable] forKey:@”printableRect”];

4) Create PDF Context and draw: Now we create PDF context UIGraphicsBeginPDFContextToData and draw using UIPrintPageRenderer.

NSMutableData * pdfData = [NSMutableData data];

UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );

for (NSInteger i=0; i < [render numberOfPages]; i++)

{

UIGraphicsBeginPDFPage();

CGRect bounds = UIGraphicsGetPDFContextBounds();

[render drawPageAtIndex:i inRect:bounds];

}

UIGraphicsEndPDFContext();

5) Save PDF file:Once the drawing is complete we can save this in a file in documents directory.

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *documentsDirectory = [paths objectAtIndex:0];

NSString * pdfFile = [[documentsDirectory stringByAppendingPathComponent:@”test.pdf”] retain];

[pdfData writeToFile:pdfFile atomically:YES];

Source code to generate PDF using UIPrintPageRenderer.

 

 

ChartBoost Static Library and Flex Native Extension

During one of the project there was requirement to create a native extension for ChartBoost SDK as explained by Sameer in this post. ChartBoost gives a static library as form of SDK with couple of header files. Using header files in an XCode project I created a static library from which an extension can be easily created using adt. Though the problem was to merge the static library from ChartBoost with the library I created for extension. On top of that the library from ChartBoost had symbols for both armv7 and i386 architecture while for extension we needed only the armv7 architecture.

So the first step was to extract the armv7 library from the ChartBoost static library.

lipo -output libChartBoostarmv7.a -thin armv7 libChartBoost.a

Above commands extracts the armv7 symbols in another static library package. Its very important to specify -thin so we don’t end up with another fat library. We copied libChartBoostarmv7.a and libChartBoostExtension.a in one folder.

mkdir CombinedStaticLib

cp libChartBoostarmv7.a CombinedStaticLib/

cp libChartBoostExtension.a CombinedStaticLib/

Now we extract symbols from both the libraries and combine them using the ar command:

ar -x libChartBoostExtension.a
ar -x libChartBoostarmv7.a
ar -crs libCB.a *.o

libCB.a is the final static library. Using following command one can easily create the ANE file:

Flex_SDK_PATH/bin/adt -package -target ane ../release/ChartBoostExtension.ane extension.xml -swc ChartBoost.swc -platform  iPhone-ARM library.swf libCB.a

I hope you enjoyed some technical process behind the extension we created.

 

Changing app package for Android in Eclipse

When I started learning to develop Augmented Reality based app on Android I started with Qualcomm’s SDK. As usual I start with sample code provided with any SDK and build upon that. Also that way I am able to check the functionality easily.

Hence I needed to change the name of the package after I built a bit on top of the provided sample app. I found Troubleshooting Resources for Android  useful as it provided the initial directions on how to do that

For example, here’s how you could do this in Eclipse:

  1. Right-click on the package name (src/com.android.gesture.builder).
  2. Select Refactor > Rename and change the name, for example to com.android.gestureNEW.builder.
  3. Open the manifest file. Inside the <manifest> tag, change the package name to com.android.gestureNEW.builder.
  4. Open each of the two Activity files and do Ctrl-Shift-O to add missing import packages, then save each file.
  5. Run the GestureBuilder application on the emulator.

It works well but its not all that you are supposed to do if you are using JNI. There are couple more changes you would need to do:

Java_com_first_second_class_Function( JNIEnv* env, jobject obj)
Change com_first_second to the package name you are changing to. This enables Java would be able to call the native function.

jmethodID functionMethodID = env->GetMethodID(activityClass, “function_name”, “(I)Lcom/first/second/Class;”);
Again change com/first/second to the package name you are changing to. And this enables for native library to call the function in Java.

This should help you get going with package name changes.

Capture image on a Adobe AIR application running on iOS and save to iOS disk

Some of you could ask why this post as it can be achieved using bitmap data and save to camera roll or to app storage using Byte Array?

So to answer if you save bitmap data to camera roll you can not save a reference to that image in your application in case you want to show creations of the user. Only option is to save it in a directory you have access to either in Application Directory or in Document Directory. If you go with that option you have to use byte array to save the image on the disk. It will work fine if you have small images but it wont work well if you have large image or say an image of screen size of iPhone. Read more »

Adobe AIR Native Extension For Chartboost Advertise Network

This is our first post and there are chances of mistakes so please bear with me.

Scenario
We got a project from a client to create an ios game from a flash action script 3.0 game. He have bought the game code and given us to modify it so it can be played back on iPhone and iPod. This was not a big deal for a company like us. We made the game and it got approved straight away. So we got another project with a new requirement of displaying ads from chartboost. We have read through Adobe forums and find out about the Native Extension so we made a deal with client. Read more »