How To Convert Web Link To PDF Without Using iText Library In Android

Introduction

In this article, we will learn how to convert a Web URL to a pdf file in Android. To create a PDF in Android, we usually use a third party library but here we will not use any third-party libraries.

iText Library

This library is awesome and very useful. But the iText Community licensed this library with the AGPL license. So, we need to license our own application under the AGPL license.
Reference Link - http://developers.itextpdf.com/
But Google provides a print API for Android to print any content directly from a mobile app. We can use the same Print API for generating and saving a web page content to a pdf file.
Reference Link - https://developer.android.com/training/printing/
Coding Part
I have detailed this article into the following 3 steps.

Creating a New Project with Android Studio

  1. Open Android Studio and select Create a new project.
  2. Name the project as per your wish and select your activity template.
    How To Convert Web Link To PDF Without Using iText Library In Android
  3. Click Finish button to create a new project in Android Studio.

Setting up the project with Print Adapter Extension

To create a pdf file, we need to use “PrintDocumentAdapter.LayoutResultCallback” and it cannot be used by any class.
Create a class with the package name “android.print” and the class name “PdfPrint.java”.
Paste the following code with a callback interface.
  1. package android.print;
  2. import android.os.Build;
  3. import android.os.CancellationSignal;
  4. import android.os.ParcelFileDescriptor;
  5. import android.support.annotation.RequiresApi;
  6. import android.util.Log;
  7. import java.io.File;
  8. @SuppressWarnings("ALL")
  9. public class PdfPrint {
  10. private static final String TAG = PdfPrint.class.getSimpleName();
  11. private final PrintAttributes printAttributes;
  12. public PdfPrint(PrintAttributes printAttributes) {
  13. this.printAttributes = printAttributes;
  14. }
  15. @RequiresApi(api = Build.VERSION_CODES.KITKAT)
  16. public void print(final PrintDocumentAdapter printAdapter, final File path, final String fileName,
  17. final CallbackPrint callback) {
  18. printAdapter.onLayout(null, printAttributes, null,
  19. new PrintDocumentAdapter.LayoutResultCallback() {
  20. @Override
  21. public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
  22. printAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(path, fileName),
  23. new CancellationSignal(), new PrintDocumentAdapter.WriteResultCallback() {
  24. @Override
  25. public void onWriteFinished(PageRange[] pages) {
  26. super.onWriteFinished(pages);
  27. if (pages.length > 0) {
  28. File file = new File(path, fileName);
  29. String path = file.getAbsolutePath();
  30. callback.onSuccess(path);
  31. } else {
  32. callback.onFailure(new Exception("Pages length not found"));
  33. }
  34. }
  35. });
  36. }
  37. }, null);
  38. }
  39. private ParcelFileDescriptor getOutputFile(File path, String fileName) {
  40. if (!path.exists()) {
  41. path.mkdirs();
  42. }
  43. File file = new File(path, fileName);
  44. try {
  45. file.createNewFile();
  46. return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
  47. } catch (Exception e) {
  48. Log.e(TAG, "Failed to open ParcelFileDescriptor", e);
  49. }
  50. return null;
  51. }
  52. public interface CallbackPrint {
  53. void onSuccess(String path);
  54. void onFailure(Exception ex);
  55. }
  56. }

Implementation of URL to PDF file generation

In this part, we will learn how to use the Printer Extension created in the last step to create a PDF file.
  1. Open your xml file and paste the following code.
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:tools="http://schemas.android.com/tools"
    4. android:layout_width="match_parent"
    5. android:layout_height="match_parent"
    6. tools:context="com.androimads.androidpdfmaker.MainActivity">
    7. <WebView
    8. android:layout_width="match_parent"
    9. android:layout_height="match_parent"
    10. android:id="@+id/webView"
    11. android:layout_above="@id/textView"/>
    12. <TextView
    13. android:visibility="gone"
    14. android:background="@color/colorBackground"
    15. android:padding="2dp"
    16. android:text="Saving..."
    17. android:gravity="center"
    18. android:textColor="#FFFFFF"
    19. android:layout_alignParentBottom="true"
    20. android:layout_width="match_parent"
    21. android:layout_height="wrap_content"
    22. android:id="@+id/textView"/>
    23. </RelativeLayout>
  1. Open your Activity file, in my case “MainActivity.java” and initialize “WebView” as shown below.
    1. webView = findViewById(R.id.webView);
    2. webView.loadUrl("https://www.androidmads.info/");
    3. webView.setWebViewClient(new WebViewClient());
  1. Create a pdf print adapter with print attributes what we need.
    1. String fileName = String.format("%s.pdf", new SimpleDateFormat("dd_MM_yyyyHH_mm_ss", Locale.US).format(new Date()));
    2. final PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(fileName);
    3. PrintAttributes printAttributes = new PrintAttributes.Builder()
    4. .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
    5. .setResolution(new PrintAttributes.Resolution("pdf", "pdf", 600, 600))
    6. .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
    7. .build();
    Here, I have used a default page size as “A4”.
  1. Call your extension method with the callback as shown below.
    1. new PdfPrint(printAttributes).print(
    2. printAdapter,
    3. file,
    4. fileName,
    5. new PdfPrint.CallbackPrint() {
    6. @Override
    7. public void onSuccess(String path) {
    8. }
    9. @Override
    10. public void onFailure(Exception ex) {
    11. }
    12. });
    The PdfPrint.Callback will return success or failure based on the extension method we created.
Full code of MainActivity
The following listing is the full code of the MainActivity.java for generating a pdf file.
  1. @TargetApi(Build.VERSION_CODES.LOLLIPOP)
  2. public class MainActivity extends AppCompatActivity {
  3. private WebView webView;
  4. private TextView textView;
  5. private int PERMISSION_REQUEST = 0;
  6. private boolean allowSave = true;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. textView = findViewById(R.id.textView);
  12. webView = findViewById(R.id.webView);
  13. webView.loadUrl("https://www.androidmads.info/");
  14. webView.setWebViewClient(new WebViewClient());
  15. }
  16. @Override
  17. public boolean onCreateOptionsMenu(Menu menu) {
  18. getMenuInflater().inflate(R.menu.main, menu);
  19. return true;
  20. }
  21. @Override
  22. public boolean onOptionsItemSelected(MenuItem item) {
  23. if (item.getItemId() == R.id.save) {
  24. savePdf();
  25. return true;
  26. }
  27. return super.onOptionsItemSelected(item);
  28. }
  29. private void savePdf() {
  30. if(!allowSave)
  31. return;
  32. allowSave = false;
  33. textView.setVisibility(View.VISIBLE);
  34. if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
  35. == PERMISSION_GRANTED) {
  36. String fileName = String.format("%s.pdf", new SimpleDateFormat("dd_MM_yyyyHH_mm_ss", Locale.US).format(new Date()));
  37. final PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(fileName);
  38. PrintAttributes printAttributes = new PrintAttributes.Builder()
  39. .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
  40. .setResolution(new PrintAttributes.Resolution("pdf", "pdf", 600, 600))
  41. .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
  42. .build();
  43. final File file = Environment.getExternalStorageDirectory();
  44. new PdfPrint(printAttributes).print(
  45. printAdapter,
  46. file,
  47. fileName,
  48. new PdfPrint.CallbackPrint() {
  49. @Override
  50. public void onSuccess(String path) {
  51. textView.setVisibility(View.GONE);
  52. allowSave = true;
  53. Toast.makeText(getApplicationContext(),
  54. String.format("Your file is saved in %s", path),
  55. Toast.LENGTH_LONG).show();
  56. }
  57. @Override
  58. public void onFailure(Exception ex) {
  59. textView.setVisibility(View.GONE);
  60. allowSave = true;
  61. Toast.makeText(getApplicationContext(),
  62. String.format("Exception while saving the file and the exception is %s", ex.getMessage()),
  63. Toast.LENGTH_LONG).show();
  64. }
  65. });
  66. } else {
  67. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
  68. }
  69. }
  70. @Override
  71. public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
  72. if (requestCode == PERMISSION_REQUEST) {
  73. if (grantResults[Arrays.asList(permissions).indexOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)] == PERMISSION_GRANTED) {
  74. savePdf();
  75. }
  76. }
  77. super.onRequestPermissionsResult(requestCode, permissions, grantResults);
  78. }
  79. }
Reference
Download
You can download the same code from GitHub. If you like this article, please like and share the article and start the repo in GitHub.

Summary

In this article, we learned about How To Convert Web Link To PDF Without Using iText Library In Android.