最近做一个需要将APP里的一个报告通过打印机打印出来的项目,我是小白,在网上看了很多有关打印机的程序,还是一头雾水,最后发现一个简单的方法(虽然有点甩锅的嫌疑),能实现打印的目的。
首先说一下思路,因为需要打印的报告是在程序里生成的(其实就是一个布局页面,只是需要往控件里填数据),如果把数据全传给网络打印机的话,非常繁琐。何不直接传一个图片或者文件。于是我就把整个页面保存为图片存在SD卡文件夹中。然后将图片生成PDF文件,再通过WPS或者Office打开并用自带的打印功能进行打印(这就是把打印的事甩给了第三方)。还有就是单独的图片其实也是可以打印的(手机的功能真是强大),不需要生成PDF,但是考虑到需要打印多个界面时,一张张打实在是费事,而且打印效果也不是很理想,因此生成PDF会好很多。今天生成PDF成功了,因此把方法分享并保存下来,以便以后回顾。下面是我的简单的Demo。
首先,生成PDF我用的是Itext(虽然网上有的说并不好用,但是只是将图片生成PDF的话,还是这种方法简单。),添加Itext的依赖,可以在http://mvnrepository.com/artifact/com.itextpdf/itextpdf这里找到,各个版本都有,找到Gradle方式的依赖,将compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.13'添加到app下的build.gradle中,5.5.13是目前的最新版本。值得注意的是gradle版本到4.1以后不再用compile添加,而用implementation。
然后申请权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/zong" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#ffffff" > <ImageView android:id="@+id/back_ground" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:id="@+id/text1" android:text="aaaaaa" android:layout_width="match_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/take_photo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:text="生成PDF"/> </RelativeLayout>
布局很简单,其中ImageView的背景图片是在程序中添加的,主要是当时不知是否是保存初始页面,还是保存更改了信息后的页面。因此来区分验证一下。
其中有几个重要的方法
将要保存的View生成Bitmap对象。
private Bitmap getBitmap(View view){ view.setDrawingCacheEnabled(true); view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(),view.getMeasuredHeight() ); Bitmap bitmap=view.getDrawingCache(); return bitmap; }
随机生成一个文件名。
private static String generateFileName() { return UUID.randomUUID().toString(); }
将Bitmap对象以jpg格式保存在SD卡中,并返回保存的路径,SD_PATH和IN_PATH是随便定义的文件夹。
private String saveBitmap(Context context, Bitmap mBitmap) { String savePath; File filePic; if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { savePath = SD_PATH; } else { savePath = context.getApplicationContext().getFilesDir() .getAbsolutePath() + IN_PATH; } try { filePic = new File(savePath + generateFileName() + ".jpg"); if (!filePic.exists()) { filePic.getParentFile().mkdirs(); filePic.createNewFile(); } FileOutputStream fos = new FileOutputStream(filePic); mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.flush(); fos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } imagepath = filePic.getAbsolutePath(); Log.d("sssssssss","---------"+imagepath); return imagepath; }
将图片生成.pdf格式文件,其中imagepath是要被生成的图片的路径,pdfpath是生成的pdf文件被保存的路径。
public boolean imageToPDF(String imagepath,String pdfpath)throws IOException{ File file = new File(imagepath); if (file.exists()){ Document document = new Document(); FileOutputStream fos = null; try { fos = new FileOutputStream(pdfpath); PdfWriter.getInstance(document,fos); // 添加PDF文档的某些信息,比如作者,主题等等 document.addAuthor("arui"); document.addSubject("test pdf."); // 设置文档的大小 document.setPageSize(PageSize.A4); // 打开文档 document.open(); // 写入一段文字 //document.add(new Paragraph("JUST TEST ...")); Image image = Image.getInstance(imagepath); float imageHeight=image.getScaledHeight(); float imageWidth=image.getScaledWidth(); int i=0; while(imageHeight>500||imageWidth>500) { image.scalePercent(100 - i); i++; imageHeight = image.getScaledHeight(); imageWidth = image.getScaledWidth(); System.out.println("imageHeight->" + imageHeight); System.out.println("imageWidth->" + imageWidth); } image.setAlignment(Image.ALIGN_CENTER); // //设置图片的绝对位置 //image.setAbsolutePosition(0, 0); //image.scaleAbsolute(500, 400); // 插入一个图片 document.add(image); }catch (DocumentException dc){ dc.printStackTrace(); }catch (IOException ioe){ ioe.printStackTrace(); } document.close(); fos.flush(); fos.close(); Toast.makeText(this,"生成PDF成功",Toast.LENGTH_SHORT).show(); return true; }else { return false; } }
然后就是调用对应的方法即可,就可以将页面(包括任意一块布局)在制定文件夹中生成pdf文件,记得调用imageToPDFS方法时记得抛异常就行了,我是新手,还在学习中,哪里有错欢迎大佬们指出,共同进步。
效果图