Skip to content

Instantly share code, notes, and snippets.

@apvasanth03
Created February 4, 2017 04:53
Show Gist options
  • Save apvasanth03/ed903535aed12c93e30b102d9596c399 to your computer and use it in GitHub Desktop.
Save apvasanth03/ed903535aed12c93e30b102d9596c399 to your computer and use it in GitHub Desktop.
Android PDF Generator example
package com.vm.trinity.common.ui;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.pdf.PdfDocument;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Log;
import android.view.View;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
/**
* A Class used to generate PDF for the given Views.
*/
@TargetApi(VMConstant.NUMBER_NINETEEN)
public class PDFUtil {
/**
* TAG.
*/
private static final String TAG = PDFUtil.class.getName();
/**
* Page width for our PDF.
*/
public static final double PDF_PAGE_WIDTH = 8.3 * 72;
/**
* Page height for our PDF.
*/
public static final double PDF_PAGE_HEIGHT = 11.7 * 72;
/**
* Page width for our PDF in inch.
*/
// public static final double PDF_PAGE_WIDTH_INCH = 8.3;
/**
* Page height for our PDF in inch.
*/
// public static final double PDF_PAGE_HEIGHT_INCH = 11.7;
/**
* Singleton instance for PDFUtil.
*/
private static PDFUtil sInstance;
/**
* Constructor.
*/
private PDFUtil() {
}
/**
* Return singleton instance of PDFUtil.
*
* @return singleton instance of PDFUtil.
*/
public static PDFUtil getInstance() {
if (sInstance == null) {
sInstance = new PDFUtil();
}
return sInstance;
}
/**
* Generates PDF for the given content views to the file path specified.
* <p/>
* Method gets List of views as the input and each view will be written to the single page in
* the PDF.
* <p/>
* If API is not support then PDFUtilListener's pdfGenerationFailure method will be called with
* APINotSupportedException.
*
* @param contentViews List of Content Views to be converted as PDF.
* @param filePath FilePath where the PDF has to be stored.
* @param listener PDFUtilListener to send callback for PDF generation.
*/
public final void generatePDF(final List<View> contentViews, final String filePath,
final PDFUtilListener listener) {
//Check Api Version.
int currentApiVersion = Build.VERSION.SDK_INT;
if (currentApiVersion >= Build.VERSION_CODES.KITKAT) {
// Kitkat
new GeneratePDFAsync(contentViews, filePath, listener).execute();
} else {
// Before Kitkat
Log.e(TAG, "Generate PDF is not available for your android version.");
listener.pdfGenerationFailure(
new APINotSupportedException("Generate PDF is not available for your android version."));
}
}
/**
* Listener used to send PDF Generation callback.
*/
public interface PDFUtilListener {
/**
* Called on the success of PDF Generation.
*/
void pdfGenerationSuccess();
/**
* Called when PDF Generation failed.
*
* @param exception Exception occurred during PDFGeneration.
*/
void pdfGenerationFailure(final Exception exception);
}
/**
* Async task class used to generate PDF in separate thread.
*/
private class GeneratePDFAsync extends AsyncTask<Void, Void, Boolean> {
// mContentViews.
private List<View> mContentViews;
// mFilePath.
private String mFilePath;
// mListener.
private PDFUtilListener mListener = null;
// mException.
private Exception mException;
/**
* Constructor.
*
* @param contentViews List of Content Views to be converted as PDF.
* @param filePath FilePath where the PDF has to be stored.
* @param listener PDFUtilListener to send callback for PDF generation.
*/
public GeneratePDFAsync(final List<View> contentViews, final String filePath, final PDFUtilListener listener) {
this.mContentViews = contentViews;
this.mFilePath = filePath;
this.mListener = listener;
}
/**
* Do In Background.
*
* @param params Params
* @return TRUE if PDF successfully generated else FALSE.
*/
@Override
protected Boolean doInBackground(Void... params) {
boolean isPdfSuccessfullyGenerated;
try {
// Create PDF Document.
PdfDocument pdfDocument = new PdfDocument();
// Write content to PDFDocument.
writePDFDocument(pdfDocument);
// Save document to file.
savePDFDocumentToStorage(pdfDocument);
isPdfSuccessfullyGenerated = true;
} catch (Exception exception) {
Log.e(TAG, exception.getMessage());
isPdfSuccessfullyGenerated = false;
}
return isPdfSuccessfullyGenerated;
}
/**
* On Post Execute.
*
* @param isPdfSuccessfullyGenerated boolean value to check if the pdf is successfully generated.
*/
@Override
protected void onPostExecute(Boolean isPdfSuccessfullyGenerated) {
super.onPostExecute(isPdfSuccessfullyGenerated);
if (isPdfSuccessfullyGenerated) {
//Send Success callback.
mListener.pdfGenerationSuccess();
} else {
//Send Error callback.
mListener.pdfGenerationFailure(mException);
}
}
/**
* Writes given PDFDocument using content views.
*
* @param pdfDocument PDFDocument to be written.
*/
private void writePDFDocument(final PdfDocument pdfDocument) {
for (int i = 0; i < mContentViews.size(); i++) {
//Get Content View.
View contentView = mContentViews.get(i);
// crate a page description
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.
Builder((int) PDF_PAGE_WIDTH, (int) PDF_PAGE_HEIGHT, i + 1).create();
// start a page
PdfDocument.Page page = pdfDocument.startPage(pageInfo);
// draw view on the page
Canvas pageCanvas = page.getCanvas();
int pageWidth = pageCanvas.getWidth();
int pageHeight = pageCanvas.getHeight();
int measureWidth = View.MeasureSpec.makeMeasureSpec(pageWidth, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(pageHeight, View.MeasureSpec.EXACTLY);
contentView.measure(measureWidth, measuredHeight);
contentView.layout(0, 0, pageWidth, pageHeight);
contentView.draw(pageCanvas);
// finish the page
pdfDocument.finishPage(page);
}
}
/**
* Save PDFDocument to the File in the storage.
*
* @param pdfDocument Document to be written to the Storage.
* @throws java.io.IOException
*/
private void savePDFDocumentToStorage(final PdfDocument pdfDocument) throws IOException {
FileOutputStream fos = null;
// Create file.
File pdfFile = new File(mFilePath);
//Create parent directories
File parentFile = pdfFile.getParentFile();
if (!parentFile.exists() && !parentFile.mkdirs()) {
throw new IllegalStateException("Couldn't create directory: " + parentFile);
}
boolean fileExists = pdfFile.exists();
// If File already Exists. delete it.
if (fileExists) {
fileExists = !pdfFile.delete();
}
try {
if (!fileExists) {
// Create New File.
fileExists = pdfFile.createNewFile();
}
if (fileExists) {
// Write PDFDocument to the file.
fos = new FileOutputStream(pdfFile);
pdfDocument.writeTo(fos);
//Close output stream
fos.close();
// close the document
pdfDocument.close();
}
} catch (IOException exception) {
Log.d(this.getClass().getName(), VMConstant.EXCEPTION_DESCRIPTION, exception);
if (fos != null) {
fos.close();
}
throw exception;
}
}
}
/**
* APINotSupportedException will be thrown If the device doesn't support PDF methods.
*/
private static class APINotSupportedException extends Exception {
// mErrorMessage.
private String mErrorMessage;
/**
* Constructor.
*
* @param errorMessage Error Message.
*/
public APINotSupportedException(final String errorMessage) {
this.mErrorMessage = errorMessage;
}
/**
* To String.
*
* @return error message as a string.
*/
@Override
public String toString() {
return "APINotSupportedException{" +
"mErrorMessage='" + mErrorMessage + '\'' +
'}';
}
}
}
package com.vm.trinity.common.ui;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.vm.trinity.R;
import com.vm.trinity.techtool.model.SummaryPdf;
import java.util.ArrayList;
import java.util.List;
/**
* Summary PDF Util.
* 1. Used to create list of views of size A4. 2. Generate PDF from the views.
*/
public class SummaryPdfUtil {
// TAG.
public static final String TAG = SummaryPdfUtil.class.getName();
// PDF_PAGE_WIDTH_PX.
private static final int PDF_PAGE_WIDTH_PX = 595;
// PDF_PAGE_HEIGHT_PX.
private static final int PDF_PAGE_HEIGHT_PX = 842;
// MARGIN_TOP_PX.
private static final int MARGIN_TOP_PX = 54;
// MARGIN_LEFT_PX.
private static final int MARGIN_LEFT_PX = 54;
// MARGIN_RIGHT_PX.
private static final int MARGIN_RIGHT_PX = 37;
// MARGIN_BOTTOM_PX.
private static final int MARGIN_BOTTOM_PX = 103;
// sInstance.
private static SummaryPdfUtil sInstance;
/**
* Constructor.
*/
private SummaryPdfUtil() {
}
/**
* Get Instance.
*
* @return Singleton sInstance of SummaryPdfUtil.
*/
public static SummaryPdfUtil getInstance() {
if (sInstance == null) {
sInstance = new SummaryPdfUtil();
}
return sInstance;
}
/**
* Generate Summary PDF.
*
* @param activity Activity.
*/
public final void generateSummaryPdf(final SummaryPdf summaryPdf, final String filePath,
final Activity activity, final SummaryPdfListener listener) {
// Generate Summary Pdf
new GenerateSummaryPdfViewAsync(summaryPdf, filePath, activity, listener).execute();
}
/**
* Listener used to send Summary PDF Generation callback.
*/
public interface SummaryPdfListener {
/**
* Called on the success of Generation of summary PDF.
*/
void generateSummaryPdfSuccess();
/**
* Called on the failure of Generation of summary PDF.
*
* @param exception Exception occurred during PDFGeneration.
*/
void generateSummaryPdfFailure(final Exception exception);
}
/**
* Generate Summary PDF View Async.
*/
private class GenerateSummaryPdfViewAsync extends AsyncTask<Void, Void, Boolean>
implements PDFUtil.PDFUtilListener {
// mSummaryPdf.
private SummaryPdf mSummaryPdf;
// mFilePath.
private String mFilePath;
// mContext.
private Context mContext;
// mListener.
private SummaryPdfListener mListener;
// mException.
private Exception mException;
// mInflater.
private LayoutInflater mInflater;
// mPdfPageViews.
private List<View> mPdfPageViews = null;
// mPdfPageView.
private ViewGroup mPdfPageView;
// mPdfPageAvailableHeight
private int mPdfPageAvailableHeight;
/**
* Constructor.
*/
public GenerateSummaryPdfViewAsync(final SummaryPdf summaryPdf, final String filePath,
final Activity activity, final SummaryPdfListener listener) {
// Initialize.
this.mSummaryPdf = summaryPdf;
this.mFilePath = filePath;
this.mContext = activity;
this.mListener = listener;
mInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
/**
* Do In Background.
*
* @param params Input Params.
* @return True if Generate Summary PDF view is successful, else FALSE.
*/
@Override
protected Boolean doInBackground(Void... params) {
boolean isGenerateSummaryViewSuccessful;
try {
// Create List View.
mPdfPageViews = new ArrayList<>();
// Create First Page of our PDF.
mPdfPageView = getPdfPageView();
// Summary Header View.
View summaryHeaderView = getSummaryHeaderView();
addViewToPage(summaryHeaderView);
// What you told us View.
View whatWeToldUs = getSummaryContentView(mSummaryPdf.getWhatYouToldUs(),
R.drawable.icon_pdf_customer_problem, mContext.getString(R.string.what_you_told));
addViewToPage(whatWeToldUs);
// What We Found View.
View whatWeFound = getSummaryContentView(mSummaryPdf.getWhatWeFound(),
R.drawable.icon_pdf_what_we_found, mContext.getString(R.string.what_we_found));
addViewToPage(whatWeFound);
// How We Improved Things View.
View howWeImprovedThings = getSummaryContentView(mSummaryPdf.getHowWeImprovedThings(),
R.drawable.icon_pdf_how_we_improved_things, mContext.getString(R.string.how_we_improve));
addViewToPage(howWeImprovedThings);
// Your Internet Speed.
View yourInternetSpeed = getSummaryInternetSpeedContentView(mSummaryPdf.getYourInternetSpeed(),
R.drawable.icon_pdf_internet_speed, mContext.getString(R.string.your_internet_speed));
addViewToPage(yourInternetSpeed);
// Your Current Status View.
View yourCurrentStatus = getSummaryContentView(mSummaryPdf.getYourCurrentStatus(),
R.drawable.icon_pdf_current_status, mContext.getString(R.string.current_status));
addViewToPage(yourCurrentStatus);
// Your Wifi BlackSpots
View yourWifiBlackSpots = getSummaryContentView(mSummaryPdf.getYourWifiBlackSpots(),
R.drawable.icon_pdf_wifi_black_spots, mContext.getString(R.string.wifi_blackspots));
addViewToPage(yourWifiBlackSpots);
// Add view.
mPdfPageViews.add(mPdfPageView);
isGenerateSummaryViewSuccessful = true;
} catch (Exception exception) {
this.mException = exception;
Log.e(TAG, exception.getMessage());
isGenerateSummaryViewSuccessful = false;
}
return isGenerateSummaryViewSuccessful;
}
/**
* On Post Execute.
*
* @param isGenerateSummaryViewSuccessful boolean value to check generated summary view is successful.
*/
@Override
protected void onPostExecute(Boolean isGenerateSummaryViewSuccessful) {
super.onPostExecute(isGenerateSummaryViewSuccessful);
if (isGenerateSummaryViewSuccessful) {
PDFUtil.getInstance().generatePDF(mPdfPageViews, mFilePath, this);
} else {
mListener.generateSummaryPdfFailure(mException);
}
}
/**
* Get PDF Page View.
*
* @return View.
*/
private ViewGroup getPdfPageView() {
ViewGroup pdfPageView = (ViewGroup) mInflater.inflate(R.layout.summary_pdf_page, null);
pdfPageView.setPadding(MARGIN_LEFT_PX, MARGIN_TOP_PX, MARGIN_RIGHT_PX, MARGIN_BOTTOM_PX);
//setMargins(mPdfPageView, MARGIN_LEFT_PX, MARGIN_TOP_PX, MARGIN_RIGHT_PX, MARGIN_BOTTOM_PX);
int measureWidth = View.MeasureSpec.makeMeasureSpec(PDF_PAGE_WIDTH_PX, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(PDF_PAGE_HEIGHT_PX, View.MeasureSpec.EXACTLY);
pdfPageView.measure(measureWidth, measuredHeight);
mPdfPageAvailableHeight = PDF_PAGE_HEIGHT_PX;
mPdfPageAvailableHeight -= MARGIN_TOP_PX + MARGIN_BOTTOM_PX;
return pdfPageView;
}
/**
* Get Summary Header View.
*
* @return Summary Header View.
*/
private View getSummaryHeaderView() {
View summaryHeaderView = mInflater.inflate(R.layout.summary_pdf_title, null);
int measureWidth = View.MeasureSpec.makeMeasureSpec(PDF_PAGE_WIDTH_PX, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.UNSPECIFIED;
summaryHeaderView.measure(measureWidth, measuredHeight);
return summaryHeaderView;
}
/**
* Get Summary Content View.
*
* @return Summary Content View.
*/
private View getSummaryContentView(final List<String> summaryContentList, final int titleIcon,
final String titleText) {
View summaryContentView = mInflater.inflate(R.layout.summary_pdf_content, null);
// Title Icon.
ImageView imageViewTitleIcon = (ImageView) summaryContentView.
findViewById(R.id.SummaryPdfContentImageViewTitleIcon);
imageViewTitleIcon.setImageResource(titleIcon);
// Title Text.
TextView textViewTitleText = (TextView) summaryContentView.
findViewById(R.id.SummaryPdfContentTextViewTitleText);
textViewTitleText.setText(titleText);
// Title Content.
TextView textViewContentText = (TextView) summaryContentView.
findViewById(R.id.SummaryPdfContentTextViewTitleContent);
textViewContentText.setVisibility(View.GONE);
// Content.
ViewGroup contentViewGroup = (ViewGroup) summaryContentView.
findViewById(R.id.SummaryPdfContentLinearLayoutContent);
if (summaryContentList != null && summaryContentList.size() > 0) {
for (String whatYouToldUs : summaryContentList) {
TextView textViewContent = (TextView) mInflater.inflate(R.layout.summary_pdf_content_text, null);
textViewContent.setText(whatYouToldUs);
contentViewGroup.addView(textViewContent);
}
}
int measureWidth = View.MeasureSpec.makeMeasureSpec(PDF_PAGE_WIDTH_PX, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.UNSPECIFIED;
summaryContentView.measure(measureWidth, measuredHeight);
return summaryContentView;
}
/**
* Get Summary Content View.
*
* @return Summary Content View.
*/
private View getSummaryInternetSpeedContentView(final String summaryContent, final int titleIcon,
final String titleText) {
View summaryContentView = mInflater.inflate(R.layout.summary_pdf_content, null);
// Title Icon.
ImageView imageViewTitleIcon = (ImageView) summaryContentView.
findViewById(R.id.SummaryPdfContentImageViewTitleIcon);
imageViewTitleIcon.setImageResource(titleIcon);
// Title Text.
TextView textViewTitleText = (TextView) summaryContentView.
findViewById(R.id.SummaryPdfContentTextViewTitleText);
textViewTitleText.setText(titleText);
// Title Content.
TextView textViewContentText = (TextView) summaryContentView.
findViewById(R.id.SummaryPdfContentTextViewTitleContent);
textViewContentText.setText(summaryContent);
// Content.
ViewGroup contentViewGroup = (ViewGroup) summaryContentView.
findViewById(R.id.SummaryPdfContentLinearLayoutContent);
contentViewGroup.setVisibility(View.GONE);
int measureWidth = View.MeasureSpec.makeMeasureSpec(PDF_PAGE_WIDTH_PX, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.UNSPECIFIED;
summaryContentView.measure(measureWidth, measuredHeight);
return summaryContentView;
}
/**
* Add View to Page.
*
* @param view view.
*/
private void addViewToPage(final View view) {
// Check if we have height to append view to page.
int measuredHeight = view.getMeasuredHeight();
if (mPdfPageAvailableHeight > measuredHeight) {
// We have available height.
mPdfPageView.addView(view);
mPdfPageAvailableHeight -= measuredHeight;
} else {
// We don't have available height.
// Add previous page to list.
mPdfPageViews.add(mPdfPageView);
// Create new page.
mPdfPageView = getPdfPageView();
// Add view to page.
mPdfPageView.addView(view);
mPdfPageAvailableHeight -= measuredHeight;
}
}
/**
* PDF Util Listener.
* Call on the success of PDF Generation.
*/
@Override
public void pdfGenerationSuccess() {
mListener.generateSummaryPdfSuccess();
}
/**
* Called on the Failure of PDF Generation.
*
* @param exception Exception occurred during PDFGeneration.
*/
@Override
public void pdfGenerationFailure(Exception exception) {
mListener.generateSummaryPdfFailure(exception);
}
}
}
@sim-nbc
Copy link

sim-nbc commented Nov 4, 2022

Could you please implement for kotlin language?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment