如何在Android应用程序中创建PDF文件?

158

有没有办法从 Android 应用程序中创建 PDF 文件?


6
如果Android的图像模型能够从Qt的模型中汲取一些灵感,那不是很好吗?Qt证明了生成PDF或SVG可以像在屏幕上绘制一样简单。看看QPrinter、QSvgGenerator和QWidget从QPaintDevice派生的模式。 - Calaf
1
在iOS中也是一样的。PDF生成是内置的。 - Fabian Zeindl
2
我相信Kit Kat有一个生成PDF的功能,但我不知道它是否向后兼容。我在下面发布了一个选项,以下网站列出了几个选项,从商业到免费:http://stefan.fenz.at/creating-pdfs-on-android-an-evaluation/ - IcedDante
8
关闭这个帖子作为“不相关主题”太荒谬了。 - Joe Coder
3
为什么这篇帖子被关闭了?Stackoverflow对其范围要求太严格了,这个问题已经有175,000次浏览了。作为一个编码资源网站,它应该允许像这样非常常见的事情。规则需要修改,我们读得太多了"不在话题范围内"的字面文字,而忽略了规则的核心。我已经申请重新开放,希望其他人也会投赞成票。 - Albert Renshaw
显示剩余3条评论
8个回答

157

57
iText 的唯一问题在于它采用 GPLv3 许可证,否则你必须购买商业许可证。 - Tony Maro
5
iText 的早期版本存在一些缺失的依赖项,例如 java.awt.Color,在 Dalvik 上不受支持。 - k-deux
3
@kape123 很有幽默感 :-) - AZ_
10
CommonsWare通用的失败主义回答...被黑了。 - moonlightcheese
2
商业许可证每个Android设备约为0.50美元(0.42欧元)。 (11-2013) - Chris623
显示剩余3条评论

110

如果您正在开发API级别为19或更高的设备,您可以使用内置的PrintedPdfDocument:http://developer.android.com/reference/android/print/pdf/PrintedPdfDocument.html

// open a new document
PrintedPdfDocument document = new PrintedPdfDocument(context,
     printAttributes);

// start a page
Page page = document.startPage(0);

// draw something on the page
View content = getContentView();
content.draw(page.getCanvas());

// finish the page
document.finishPage(page);
. . .
// add more pages
. . .
// write the document content
document.writeTo(getOutputStream());

//close the document
document.close();

2
最终,它成为了Android的一部分,就像它是iOS的一部分一样。 - lalitm
6
我认为您是指“KitKat”… :) - android developer
7
在 iOS 中生成的 PDF 具有可选择的文本,而在 Android 中生成的 PDF 则是一个图像。 - Kantesh
2
@WillThomson 你的 GitHub 链接是不是应该是 这个,还是其他什么链接? - jk7
3
非常感谢 - 有用的链接在这里 https://github.com/IanDarwin/Android-Cookbook-Examples/blob/master/PdfShare/src/main/java/com/example/pdfshare/MainActivity.java - Kibi
显示剩余3条评论

31
一个制作具有复杂功能的 PDF 的技巧是创建一个带有所需 XML 布局的虚拟活动。然后,您可以打开这个虚拟活动,使用编程方式 截屏 并使用此库将图像转换为 PDF。当然,存在一些限制,例如无法滚动,不超过一页,但对于有限的应用程序,这是快速且简便的。希望这可以帮助某些人!

2
它至少应该得到1个赞。 - Rahul Rastogi
对我来说很有效。这是一个简单的实现。 - TharakaNirmana
那是一个很棒的解决方法。 - Kumar Saurabh
这个评论给了我正确的方向。但是:
  1. 您不需要启动活动来截取屏幕截图!您只需在运行时膨胀XML布局并将其转换为位图如此处建议的那样;
话虽如此,您可以使用不同的布局生成多个页面。正如所说,不支持滚动,但是您可以使用例如线性布局来实现列表。
- r.pedrosa

11

在 Android 中,将任意包含非英语字母的 HTML 转换为 PDF 并找到完整的解决方案并不容易,我已经测试了俄语 Unicode 字母。

我们使用三个库:

(1) Jsoup (jsoup-1.7.3.jar),用于从 HTML 转换为 XHTML,

(2) iTextPDF (itextpdf-5.5.0.jar),

(3) XMLWorker (xmlworker-5.5.1.jar)。

public boolean createPDF(String rawHTML, String fileName, ContextWrapper context){
    final String APPLICATION_PACKAGE_NAME = context.getBaseContext().getPackageName();
    File path = new File( Environment.getExternalStorageDirectory(), APPLICATION_PACKAGE_NAME );
    if ( !path.exists() ){ path.mkdir(); }
    File file = new File(path, fileName);

    try{

    Document document = new Document();
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    document.open();

    // Подготавливаем HTML
    String htmlText = Jsoup.clean( rawHTML, Whitelist.relaxed() );
    InputStream inputStream = new ByteArrayInputStream( htmlText.getBytes() );

    // Печатаем документ PDF
    XMLWorkerHelper.getInstance().parseXHtml(writer, document,
        inputStream, null, Charset.defaultCharset(), new MyFont());

    document.close();
    return true;

    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return false;
    } catch (DocumentException e) {
        e.printStackTrace();
        return false;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    } 

使用iTextPDF的XMLWorker库在 PDF 中显示俄文字母是一个难点。为此,我们需要创建自己的 FontProvider 接口实现:

public class MyFont implements FontProvider{
    private static final String FONT_PATH = "/system/fonts/DroidSans.ttf";
    private static final String FONT_ALIAS = "my_font";

    public MyFont(){ FontFactory.register(FONT_PATH, FONT_ALIAS); }

    @Override
    public Font getFont(String fontname, String encoding, boolean embedded,
        float size, int style, BaseColor color){

        return FontFactory.getFont(FONT_ALIAS, BaseFont.IDENTITY_H, 
            BaseFont.EMBEDDED, size, style, color);
    }

    @Override
    public boolean isRegistered(String name) { return name.equals( FONT_ALIAS ); }
}

我们在这里使用标准的Android字体Droid Sans,该字体位于系统文件夹中:

private static final String FONT_PATH = "/system/fonts/DroidSans.ttf";

1
谢谢你的分享!我有一个问题:我们可以将任何CSS规则应用于HTML吗? - Phuong

6
稍微晚了一些,我自己还没有测试过,但是另一个遵循BSD许可证的库是Android PDF Writer更新:我已经尝试过这个库。它可以用于简单的pdf生成(提供添加文本、线条、矩形、位图、字体的方法)。唯一的问题是生成的PDF存储在内存中的字符串中,这可能会在大型文档中导致内存问题。

有人能告诉我,Android PDF Writer不能做什么,而“itext”可以吗? - M. Usman Khan
1
不再维护!!最后更新时间:2015年12月14日 - Mahdi Alkhatib

2

PDFJet提供了一个开源版本的库,可以处理任何基本的PDF生成任务。这是一个纯Java解决方案,据称与Android兼容。还有一个商业版,具有一些额外的功能,价格似乎不太昂贵。


6
不再开源。 - Joshy Francis

0

您也可以使用PoDoFo库。主要目标是它发布在LGPL下。由于它是用C++编写的,您应该使用NDK进行交叉编译,并编写C端和Java包装器。一些第三方库可以从OpenCV项目中使用。此外,在OpenCV项目中,您可以找到android.toolchain.cmake文件,它将帮助您生成Makefile


0
虽然有些晚,但仍与请求相关并希望有所帮助。如果使用外部服务(如CommonsWare的回复中建议的),那么Docmosis有一个云服务可能会有所帮助——将处理任务卸载到一个进行重型处理的云服务上。这种方法在某些情况下非常理想,但当然需要网络连接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接