Showing posts with label Android Pdf generator. Show all posts

How to convert web link to PDF without using iText Library in Android


Introduction:

In this article, we will learn how to convert any web url to pdf file in Android. To create PDF in Android, we will use iText Library. But here, we will not use any third party libraries like iText Library.

iText Library:

This library is awesome and very useful. But the iText Community licensed this library with AGPL license. So, we need to license our own application under AGPL license.

Reference Link: http://developers.itextpdf.com/

But google provided print API for Android to print any content directly from mobile app. We can use same Print API for generating and saving the pdf file. Without any introduction, we will skip into the coding part.

Reference Link: https://developer.android.com/training/printing/

Coding Part 

I have detailed the article in the following sections. 
  1. Creating a new project with Empty activity. 
  2. Setting up the project with Print Adapter Extension.
  3. Implementation of URL to PDF file generation.

Step 1: Creating New Project with Empty Activity.

  1. Creating New Project with Android Studio Open Android Studio and Select Create new project. 
  2. Name the project as your wish and select your activity template.

  3. Click “finish” button to create new project in Android Studio.

Step 2: Setting up the project with Print Adapter Extension

  1. To create pdf file, we need to use “PrintDocumentAdapter.LayoutResultCallback” and it cannot be used by any class.
  2. So, we need to create a class with package name as “android.print” and we will named the class as “PdfPrint.java”
  3. Then paste the following code with callback interface.
    @SuppressWarnings("ALL")
    public class PdfPrint {
        private static final String TAG = PdfPrint.class.getSimpleName();
        private final PrintAttributes printAttributes;
    
        public PdfPrint(PrintAttributes printAttributes) {
            this.printAttributes = printAttributes;
        }
    
        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        public void print(final PrintDocumentAdapter printAdapter, final File path, final String fileName,
                          final CallbackPrint callback) {
            printAdapter.onLayout(null, printAttributes, null,
                    new PrintDocumentAdapter.LayoutResultCallback() {
                        @Override
                        public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
                            printAdapter.onWrite(new PageRange[]{PageRange.ALL_PAGES}, getOutputFile(path, fileName),
                                    new CancellationSignal(), new PrintDocumentAdapter.WriteResultCallback() {
                                        @Override
                                        public void onWriteFinished(PageRange[] pages) {
                                            super.onWriteFinished(pages);
                                            if (pages.length > 0) {
                                                File file = new File(path, fileName);
                                                String path = file.getAbsolutePath();
                                                callback.onSuccess(path);
                                            } else {
                                                callback.onFailure(new Exception("Pages length not found"));
                                            }
    
                                        }
                                    });
                        }
                    }, null);
        }
    
        private ParcelFileDescriptor getOutputFile(File path, String fileName) {
            if (!path.exists()) {
                path.mkdirs();
            }
            File file = new File(path, fileName);
            try {
                file.createNewFile();
                return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE);
            } catch (Exception e) {
                Log.e(TAG, "Failed to open ParcelFileDescriptor", e);
            }
            return null;
        }
        public interface CallbackPrint {
            void onSuccess(String path);
            void onFailure(Exception ex);
        }
    }

Step 3: Implementation of URL to PDF file generation

In this part, we will learn how to use the Printer Extension created in the last step and How to create a PDF file.

  1. Open your activity_main.xml file and Paste the following code.
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.androimads.androidpdfmaker.MainActivity">
    
        <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/webView"
            android:layout_above="@id/textView"/>
    
        <TextView
            android:visibility="gone"
            android:background="@color/colorBackground"
            android:padding="2dp"
            android:text="Saving..."
            android:gravity="center"
            android:textColor="#FFFFFF"
            android:layout_alignParentBottom="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/textView"/>
    
    </RelativeLayout>
  2. Then open your Activity file, in my case “MainActivity.java” and initialize “WebView” as shown below
    webView = findViewById(R.id.webView);
    webView.loadUrl("https://www.androidmads.info/");
    webView.setWebViewClient(new WebViewClient());
  3. Then create a pdf print adapter with print attributes what we need
    String fileName = String.format("%s.pdf", new SimpleDateFormat("dd_MM_yyyyHH_mm_ss", Locale.US).format(new Date()));
    final PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(fileName);
    PrintAttributes printAttributes = new PrintAttributes.Builder()
      .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
      .setResolution(new PrintAttributes.Resolution("pdf", "pdf", 600, 600))
      .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
      .build();
    Here, I have used default page size as “A4”. You can change as per your need.
  4. Then call your extension method with Callback as shown below
    new PdfPrint(printAttributes).print(
     printAdapter,
     file,
     fileName,
     new PdfPrint.CallbackPrint() {
      @Override
      public void onSuccess(String path) {
    
      }
    
      @Override
      public void onFailure(Exception ex) {
      }
     });
    The PdfPrint.Callback will return success or failure based on the extension method we created.

Full code of MainActivity:

Here you can find the full code of the MainActivity.java for generating pdf file.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private TextView textView;
    private int PERMISSION_REQUEST = 0;
    private boolean allowSave = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        webView = findViewById(R.id.webView);
        webView.loadUrl("https://www.androidmads.info/");
        webView.setWebViewClient(new WebViewClient());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.save) {
            savePdf();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void savePdf() {
        if(!allowSave)
            return;
        allowSave = false;
        textView.setVisibility(View.VISIBLE);
        if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PERMISSION_GRANTED) {
            String fileName = String.format("%s.pdf", new SimpleDateFormat("dd_MM_yyyyHH_mm_ss", Locale.US).format(new Date()));
            final PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(fileName);
            PrintAttributes printAttributes = new PrintAttributes.Builder()
                    .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
                    .setResolution(new PrintAttributes.Resolution("pdf", "pdf", 600, 600))
                    .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
                    .build();
            final File file = Environment.getExternalStorageDirectory();
            new PdfPrint(printAttributes).print(
                    printAdapter,
                    file,
                    fileName,
                    new PdfPrint.CallbackPrint() {
                        @Override
                        public void onSuccess(String path) {
                            textView.setVisibility(View.GONE);
                            allowSave = true;
                            Toast.makeText(getApplicationContext(),
                                    String.format("Your file is saved in %s", path),
                                    Toast.LENGTH_LONG).show();
                        }

                        @Override
                        public void onFailure(Exception ex) {
                            textView.setVisibility(View.GONE);
                            allowSave = true;
                            Toast.makeText(getApplicationContext(),
                                    String.format("Exception while saving the file and the exception is %s", ex.getMessage()),
                                    Toast.LENGTH_LONG).show();
                        }
                    });
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_REQUEST) {
            if (grantResults[Arrays.asList(permissions).indexOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)] == PERMISSION_GRANTED) {
                savePdf();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

Download Code

You can download the full source code of the article in GitHub. If you like this article, do star the repo in GitHub. Hit like the article.