Created
February 4, 2017 04:53
-
-
Save apvasanth03/ed903535aed12c93e30b102d9596c399 to your computer and use it in GitHub Desktop.
Android PDF Generator example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 + '\'' + | |
'}'; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could you please implement for kotlin language?