How to implement report generation in a mobile app

Users expect a 'Download PDF' button, but developers face device memory limits, asynchronous generation, and complex multi-page layout. Recently, a client came to us with a report of 5,000 rows — on Android it triggered `OutOfMemoryError`, and we urgently re-architected to server-side generation. Ou

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
How to implement report generation in a mobile app
Medium
~3-5 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    898
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    784
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1219
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    600

Users expect a 'Download PDF' button, but developers face device memory limits, asynchronous generation, and complex multi-page layout. Recently, a client came to us with a report of 5,000 rows — on Android it triggered OutOfMemoryError, and we urgently re-architected to server-side generation. Our team has 5+ years of experience in implementing report generation systems for mobile apps — we guarantee stable operation even with large data volumes. We will evaluate your project and offer a cost-optimal solution.

Without the right approach, reports can consume too much memory, throw errors on opening, or display empty rectangles instead of Cyrillic. We've stepped on these rakes on dozens of projects and know how to avoid typical pitfalls. As Apple recommends: Use UIActivityViewController to let users export files.

How to implement report generation in a mobile app

Successful implementation requires choosing an approach, formatting data, rendering, and exporting to the required format. Let's look at three main ways to generate PDF.

Three approaches to PDF generation

Native rendering via Canvas

On iOS — UIGraphicsPDFRenderer, the most controllable option. Draw each element manually via Core Graphics:

func generateReport(data: ReportData) -> Data { let pageRect = CGRect(x: 0, y: 0, width: 595, height: 842) // A4 in points let renderer = UIGraphicsPDFRenderer(bounds: pageRect) return renderer.pdfData { context in context.beginPage() let ctx = context.cgContext // Header let titleFont = UIFont.boldSystemFont(ofSize: 18) let title = data.title as NSString title.draw(at: CGPoint(x: 40, y: 40), withAttributes: [ .font: titleFont, .foregroundColor: UIColor.black ]) // Data table drawTable(ctx, rows: data.rows, startY: 80, pageWidth: pageRect.width) // If data doesn't fit — new page if needsNewPage { context.beginPage() // continue... } } } 

Labor-intensive, but the result is precise control over pixel output. Good for a fixed report template.

On Android via PdfDocument:

val document = PdfDocument() val pageInfo = PdfDocument.PageInfo.Builder(595, 842, 1).create() val page = document.startPage(pageInfo) val canvas = page.canvas val paint = Paint().apply { textSize = 18f; isFakeBoldText = true } canvas.drawText(data.title, 40f, 60f, paint) document.finishPage(page) val stream = ByteArrayOutputStream() document.writeTo(stream) document.close() 

HTML → PDF via WebView

Generate an HTML template and convert it to PDF. Easier for complex layouts, tables, and text blocks — HTML/CSS is more flexible than Canvas. On Flutter use printing + pdf package:

import 'package:pdf/widgets.dart' as pw; import 'package:printing/printing.dart'; Future<Uint8List> buildPdf(ReportData data) async { final doc = pw.Document(); final font = await PdfGoogleFonts.notoSansRegular(); final boldFont = await PdfGoogleFonts.notoSansBold(); doc.addPage( pw.MultiPage( pageFormat: PdfPageFormat.a4, build: (context) => [ pw.Header(text: data.title, textStyle: pw.TextStyle(font: boldFont, fontSize: 18)), pw.SizedBox(height: 16), pw.TableHelper.fromTextArray( headers: data.headers, data: data.rows, cellStyle: pw.TextStyle(font: font, fontSize: 10), ), ], ), ); return doc.save(); } 

pw.MultiPage automatically splits into pages — solving the main problem of long reports.

Server-side generation (recommended for complex reports)

Reports with large data volumes, complex charts, or corporate branding are better generated on the server. Puppeteer (Node.js) renders HTML + Charts into PDF with browser engine accuracy. The client receives a link or file via WebSocket after completion.

This is the only right path if the report needs interactive charts (Echarts, Highcharts) — you can't render them on the device without WebView.

Parameter Native Canvas HTML → PDF WebView Server-side generation
Implementation complexity High Medium Low (client)
Layout control Full Depends on CSS Depends on HTML/CSS
Data volume Up to 50 pages Up to 100 pages Unlimited
Interactive charts No Via WebView Yes (Puppeteer)
Device memory High Medium Low

To choose the optimal solution, contact us — we will analyze your data and propose an approach.

Which report format to choose?

Besides PDF, CSV and Excel are often required. CSV is the lightest: data is written in delimiter-separated rows. The main nuance is encoding: Excel opens CSV in UTF-8 only with BOM (\uFEFF). Otherwise, Cyrillic turns into gibberish. Excel (xlsx) is more complex: you need a library that supports formulas, styles, and multiple sheets. For simple tables, CSV is sufficient. In practice, CSV with 10,000 rows generates on the device in under a second, while PDF with the same number of rows requires pagination.

Format Implementation complexity Style support File size Universality
PDF High Yes (fixed layout) Medium High (opens everywhere)
CSV Low No Small Medium (Excel, Numbers)
Excel Medium Yes (formulas, colors) Large High (Excel, Google Sheets)

What to choose: native rendering or HTML in PDF?

The choice depends on the complexity of the layout and data volume. For a fixed template with a small number of pages, native rendering is suitable. For complex tables and charts — HTML to PDF or server. Our experience shows that 80% of projects use a hybrid approach: simple reports on the device, complex ones on the server. We will help you choose the optimal turnkey solution.

CSV export

Simpler than PDF, but there are encoding nuances. Excel expects UTF-8 with BOM — otherwise Cyrillic displays as garbage. On Flutter:

String buildCsv(List<List<dynamic>> rows) { final buffer = StringBuffer(); buffer.write('\uFEFF'); // UTF-8 BOM for correct opening in Excel for (final row in rows) { buffer.writeln(row.map((cell) { final str = cell.toString(); // Escape cells with commas and quotes return str.contains(',') || str.contains('"') ? '"${str.replaceAll('"', '""')}"' : str; }).join(',')); } return buffer.toString(); } 

Sharing the generated file

share_plus on Flutter, UIActivityViewController on iOS, FileProvider + Intent.ACTION_SEND on Android. Saving to gallery / Files — via path_provider + open_filex.

On iOS you need NSPhotoLibraryAddUsageDescription in Info.plist for saving to Photos, UIFileSharingEnabled for file access via Files.app.

What typical problems occur during report generation?

Generating a PDF with a table of 10,000 rows on the device — OutOfMemoryError on Android or memory warning on iOS. Solution: data pagination, page-by-page generation, for large volumes — server.

Cyrillic in PDF without an embedded font — white rectangles instead of letters. Be sure to embed a custom font with Unicode support via pw.Font.ttf(...).

Problems with Excel: if using a library like excel (Dart), don't forget about row styles — otherwise the file won't open in old versions of Excel. We recommend always testing on real office suite versions.

Steps to implement report generation

  1. Analyze data and layouts: determine the format, volume, and type of reports.
  2. Choose an approach: native, HTML→PDF, or server-side.
  3. Develop templates with layout and font embedding.
  4. Integrate export and sharing.
  5. Test with real data (empty, large, with Cyrillic).
  6. Optimize memory and performance.

What's included in the work

  • Choosing the approach based on data specifics and layout (native / HTML→PDF / server)
  • Implementing report templates (PDF/CSV/Excel)
  • Integrating file sharing and saving
  • Handling edge cases: empty data, large volumes, page breaks

Timeframes

One PDF report template with basic formatting: 2–3 days. Multiple report types with charts and server-side generation: 1–2 weeks. Cost is calculated individually. Get a consultation for your project — we will implement a turnkey reporting system. Order development, and we will offer the optimal solution considering your data and budget.

More about Excel libraries

For Flutter, use the excel package (version 4.x) — it supports styles, cell merging, and formulas. For Android — Apache POI (via JNI or server). For iOS — SwiftExcel or xlsxwriter. The choice depends on report complexity and development time.