简介:
android是可以通过wifi调用打印机打印图片或者文档的,在API19之前,调用打印机是通过Socket通信然后打印东西的,Socket是比较原始的通信模式,也是相对比较底层的,一般通过端口连接是可以连接任意两台机器进行数据传输并操作的,打印机也不例外。但是API19之后,android有了自己的打印框架,就是Kit Kat Print,这个打印框架可以直接生成pdf或者打印图片或者html页面或者文档,这里的文档就是指类似于word之类的东西,直接操作View绘制文档,然后生成pdf或者通过wifi调用打印机打印。
注意:
Kit Kat Print这个打印框架只提供打印功能,至于搜索功能也不知道是没实现,还是根本就没有。我用的方式是先下载Hp print service 插件或Mopria PrintService”打印服务插件等其他打印服务插件,这是个移动端的service类型的app,提供搜索wifi下同一网段的打印机,安装后没有界面。如果没用这个插件的话,会显示一直在搜索中,安装完成后,在设置里面就会有打印机的选项了,某些机型里面是在设置里面,比如leX820,有些机型干脆就没有,比如Vivo,但是仍然能够扫描的到打印机。
Hpprint service插件可以直接在各种应用商店里面找,很容易搜得到的。
代码:
1.打印图片
1. private void doPhotoPrint() {
2. //申请sd卡权限
3. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE,
4. Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS},
5. 4);
6.
7. //实例化类
8. PrintHelper photoPrinter = new PrintHelper(this);
9. photoPrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT);//设置填充的类型,填充的类型指的是在A4纸上打印时的填充类型,两种模式
10.
11. //打印
12. Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/doctor/testprint.jpeg");
13. photoPrinter.printBitmap("jpgTestPrint", bitmap);//这里的第一个参数是打印的jobName
14. }
里面有部分需要解释下,填充类型ScaleMode一共两种,源码中的解释如下:
[java] view plain copy
1. /**
2. * image will be scaled but leave white space
3. */
4. public static final int SCALE_MODE_FIT = 1;
5.
6. /**
7. * image will fill the paper and be cropped (default)
8. */
9. public static final int SCALE_MODE_FILL = 2; (默认)
仍然解释的不是很明朗,解释下:Fit模式下,你所打印的图片会缩放至A4纸能够显示所有的图片内容;Fill模式下,你所打印的图片会把打印的图片拉伸直到某条边能够和对应的A4纸的边长度一致。
另外要注意的是printBitmap的第一个参数,如果打印2次以上的时候,每次传进去的参数最好不一致,这样不会打印错。
2.打印HTML文档
在Android上打印超出简单照片的内容需要在打印文档中合成文本和图形。 Android框架提供了一种使用HTML来编写文档并使用最少的代码打印文档的方法。
在Android 4.4(API级别19)中,WebView类已更新为启用打印HTML内容。 该类允许您加载本地HTML资源或从网络下载页面,创建打印作业并将其移交给Android的打印服务。
本节将向您展示如何快速构建包含文本和图形的HTML文档,并使用WebView进行打印。
1.加载HTML文档
使用WebView打印HTML文档涉及加载HTML资源或将HTML文档构建为字符串。 本节介绍如何构建HTML字符串并将其加载到WebView以进行打印。
此视图对象通常用作活动布局的一部分。 但是,如果您的应用程序没有使用WebView,您可以专门为打印目的创建类的实例。创建此自定义打印视图的主要步骤如下:
(1)创建在加载HTML资源后启动打印作业的WebViewClient。
(2)将HTML资源加载到WebView对象中。
下面的代码示例演示了如何创建一个简单的WebViewClient并加载一个动态创建的HTML文档:
privateWebView mWebView;
privatevoid doWebViewPrint(){
// Create a WebView object specifically for printing
WebView webView =newWebView(getActivity());
webView.setWebViewClient(newWebViewClient(){
publicbooleanshouldOverrideUrlLoading(WebView view,String url){
returnfalse;
}
@Override
publicvoid onPageFinished(WebView view,String url){
Log.i(TAG,"page finished loading "+ url);
createWebPrintJob(view);
mWebView =null;
}
});
// Generate an HTML document on the fly:
String htmlDocument ="<html><body><h1>TestContent</h1><p>Testing, "+
"testing,testing...</p></body></html>";
webView.loadDataWithBaseURL(null, htmlDocument,"text/HTML","UTF-8",null);
// Keep a reference to WebView object until you pass thePrintDocumentAdapter
// to the PrintManager
mWebView = webView;
}
注意:确保生成打印作业的调用发生在您在上一节中创建的WebViewClient的onPageFinished()方法中。如果不等到页面加载完成,打印输出可能不完整或空白,或可能完全失败。
注意:上面的示例代码保存了一个WebView对象的实例,因此在创建打印作业之前不会对其进行垃圾回收。确保您在自己的实现中执行相同操作,否则打印过程可能会失败。
如果要在页面中包含图形,请将图形文件放在项目的assets /目录中,并在loadDataWithBaseURL()方法的第一个参数中指定基本URL,如以下代码示例所示:
webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,
"text/HTML","UTF-8",null);
您还可以通过使用loadUrl()替换loadDataWithBaseURL()方法来加载要打印的网页,如下所示。
// Print an existing web page (remember to request INTERNET permission!):
webView.loadUrl("http://developer.android.com/about/index.html");
使用WebView创建打印文档时,应注意以下限制:
(1)您无法向文档中添加页眉或页脚(包括页码)。
(2)HTML文档的打印选项不包括打印页面范围的功能,例如:不支持打印10页HTML文档的第2页到第4页。
(3)WebView的一个实例一次只能处理一个打印作业。
(4)不支持包含CSS打印属性(如横向属性)的HTML文档。
(5)您不能在HTML文档中使用JavaScript来触发打印。
注意:包含在布局中的WebView对象的内容也可以在加载文档后打印。
如果要创建更定制的打印输出并完全控制打印页上的内容,请看下一节:Printing a Custom Document
2.创建打印作业
在创建WebView并加载HTML内容后,您的应用程序几乎完成了它的打印过程的一部分。接下来的步骤是访问PrintManager,创建打印适配器,最后创建打印作业。以下示例说明如何执行这些步骤:
privatevoid createWebPrintJob(WebView webView){
// Get a PrintManager instance
PrintManager printManager =(PrintManager) getActivity()
.getSystemService(Context.PRINT_SERVICE);
// Get a print adapter instance
PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();
// Create a print job with name and adapter instance
String jobName = getString(R.string.app_name)+" Document";
PrintJob printJob = printManager.print(jobName, printAdapter,
newPrintAttributes.Builder().build());
// Save the job object for later status checking
mPrintJobs.add(printJob);
}
此示例保存PrintJob对象的实例以供应用程序使用,这不是必需的。 您的应用程序可能会使用此对象来跟踪打印作业正在处理时的进度。 当您希望在应用程序中监视打印作业的完成,失败或用户取消操作的状态时,此方法非常有用。不需要创建应用程序内通知,因为打印框架会自动为打印作业创建系统通知。
3.打印自定义文档
1. //print picture in document
2. private void onPrintDoc(String jobName, String absPicturePath){
3. PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
4. PrintAttributes.Builder builder = new PrintAttributes.Builder();
5. builder.setColorMode(PrintAttributes.COLOR_MODE_COLOR);//设置色彩模式,黑白或者彩色,不管用
6. builder.setMinMargins(new PrintAttributes.Margins(300, 200, 300, 200));//设置页边距,就是打印的有效区域距离纸的边缘部分的距离,不管用
7. // builder.setDuplexMode(DUPLEX_MODE_SHORT_EDGE);//设置按照横着打印还是竖着打印,不管用
8. PrintAttributes.MediaSize temp = PrintAttributes.MediaSize.ISO_A4;//设置打印的纸张的类型,比如A4,A8等,不管用
9. temp.asLandscape();
10. Log.i("blb", "--------is portrait:" + temp.isPortrait());
11. builder.setMediaSize(temp);//这个也不管用
12. // builder.setResolution(new PrintAttributes.Resolution("white", "whiteRadish", 150, 150));//设置打印纸的分辨率,这个也不管用
13. MyPrintAdapter myPrintAdapter = new MyPrintAdapter(this, absPicturePath);
14. String jobName = getActivity().getString(R.string.app_name)+" Document";
15. printManager.print(jobName, myPrintAdapter, builder.build());
16. }
看到写了那么多参数其实一个都不管用,因为hp print service 并不接受这些参数设定,所以设定啥都不行。另外打印机的分辨率是可以设定的,比如300dpi,600dpi,如果不明白可以参考我之前写的像素的转换文章。
1. import android.annotation.TargetApi;
2. import android.content.Context;
3. import android.graphics.BitmapFactory;
4. import android.graphics.Canvas;
5. import android.graphics.Color;
6. import android.graphics.Paint;
7. import android.graphics.Path;
8. import android.graphics.pdf.PdfDocument;
9. import android.graphics.pdf.PdfDocument.PageInfo;
10. import android.os.Build;
11. import android.os.Bundle;
12. import android.os.CancellationSignal;
13. import android.os.Environment;
14. import android.os.ParcelFileDescriptor;
15. import android.print.PageRange;
16. import android.print.PrintAttributes;
17. import android.print.PrintDocumentAdapter;
18. import android.print.PrintDocumentInfo;
19. import android.print.pdf.PrintedPdfDocument;
20. import android.text.Layout;
21. import android.text.StaticLayout;
22. import android.text.TextPaint;
23. import android.util.Log;
24.
25. import java.io.File;
26. import java.io.FileOutputStream;
27. import java.io.IOException;
28. import java.util.ArrayList;
29. import java.util.List;
30.
31. /**
32. * Created by whiteRadish on 2017/6/14.
33. */
34.
35. @TargetApi(Build.VERSION_CODES.KITKAT)
36. public class MyPrintAdapter extends PrintDocumentAdapter {
37.
38. Context mContext;
39. private int pageHeight;
40. private int pageWidth;
41. public PdfDocument myPdfDocument;
42. public int totalpages = 1;//设置一共打印一张纸
43.
44. public MyPrintAdapter(Context context) {//这里传各种需要的参数就行
45. this.mContext = context;
46. }
47.
48. @Override
49. public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,
50. LayoutResultCallback callback,
51. Bundle metadata) {
52.
53. Log.i("blb", "--------run onLayout");
54. myPdfDocument = new PrintedPdfDocument(mContext, newAttributes); //创建可打印PDF文档对象
55.
56. pageHeight =
57. newAttributes.getMediaSize().getHeightMils() / 1000 * 72; //设置尺寸,为什么是1000 * 72, 72dpi
58. pageWidth =
59. newAttributes.getMediaSize().getWidthMils() / 1000 * 72;
60. // 自定义分页
// totalpages = computePageCount(newAttributes);
61. if (totalpages > 0) {
62. PrintDocumentInfo.Builder builder = new PrintDocumentInfo
63. .Builder("whiteRadish")
64. .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
65. .setPageCount(totalpages); //构建文档配置信息
66.
67. PrintDocumentInfo info = builder.build();
68. callback.onLayoutFinished(info, true);
69. } else {
70. callback.onLayoutFailed("Page count is zero.");
71. }
72. }
73.
private int computePageCount(PrintAttributes printAttributes) { int itemsPerPage; // default item count for portrait mode int printItemCount; if (flag == 1){ itemsPerPage = 1; PrintAttributes.MediaSize pageSize = printAttributes.getMediaSize(); if (!pageSize.isPortrait()) { // Six items per page in landscape orientation itemsPerPage = 1; } // // Determine number of print items printItemCount = result.size(); }else if (flag == 2){ itemsPerPage = 3; PrintAttributes.MediaSize pageSize = printAttributes.getMediaSize(); if (!pageSize.isPortrait()) { // Six items per page in landscape orientation itemsPerPage = 1; } printItemCount = result1.size(); }else{ itemsPerPage = 1; PrintAttributes.MediaSize pageSize = printAttributes.getMediaSize(); if (!pageSize.isPortrait()) { // Six items per page in landscape orientation itemsPerPage = 1; } // // Determine number of print items printItemCount = result.size(); } return (int) Math.ceil(printItemCount / itemsPerPage); }
74. @Override
75. public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal,
76. final WriteResultCallback callback) {
77.
78. Log.i("blb", "--------run onWrite");
79.
80. for (int i = 0; i < totalpages; i++) {
81. if (pageInRange(pageRanges, i)) //保证页码正确
82. {
83. PageInfo newPage = new PageInfo.Builder(pageWidth,
84. pageHeight, i).create();//创建对应的Page
85.
86. PdfDocument.Page page =
87. myPdfDocument.startPage(newPage); //创建新页面
88.
89. if (cancellationSignal.isCanceled()) { //取消信号
90. callback.onWriteCancelled();
91. myPdfDocument.close();
92. myPdfDocument = null;
93. return;
94. }
95. drawPage(page, i); //将内容绘制到页面Canvas上
96. myPdfDocument.finishPage(page);
97. }
98. }
99.
100. try {
101. myPdfDocument.writeTo(new FileOutputStream(
102. destination.getFileDescriptor()));
103. } catch (IOException e) {
104. callback.onWriteFailed(e.toString());
105. return;
106. } finally {
107. myPdfDocument.close();
108. myPdfDocument = null;
109. }
110.
111. callback.onWriteFinished(pageRanges);
112. }
113.
114. private boolean pageInRange(PageRange[] pageRanges, int page) {
115. for (int i = 0; i < pageRanges.length; i++) {
116. if ((page >= pageRanges[i].getStart()) &&
117. (page <= pageRanges[i].getEnd()))
118. return true;
119. }
120. return false;
121. }
122.
123. //页面绘制
124. private void drawPage(PdfDocument.Page page,
125. int pagenumber) {
126. Canvas canvas = page.getCanvas();
127.
128. //这里是页码。页码不能从0开始
129. pagenumber++;
130.
131. Paint paint = new Paint();
132.
133. PageInfo pageInfo = page.getInfo();
134.
135. //draw heart rate line
136. if (pageWidth > pageHeight){
137. drawViewsOnPaper(Canvas canvas, Paint paint);
138. }
139. }
140.
141. //draw views
142. private void drawViewsOnPaper(Canvas canvas, Paint paint){
143. //这里绘制要在打印的纸上的内容,如果精确一点的话,根据pageHeight,pageWidth计算就行,这里的内容和自定义View的内容一样,
144. //把自定义View绘制的东西拉过来直接就可以用
145. Canvas canvas = page.getCanvas();
146.
147. // units are in points (1/72 ofan inch)
148. int titleBaseLine =72;
149. int leftMargin =54;
150.
151. Paint paint =newPaint();
152. paint.setColor(Color.BLACK);
153. paint.setTextSize(36);
154. canvas.drawText("Test Title", leftMargin, titleBaseLine, paint);
155.
156. paint.setTextSize(11);
157. canvas.drawText("Test paragraph", leftMargin, titleBaseLine +25, paint);
158.
159. paint.setColor(Color.BLUE);
160. canvas.drawRect(100,100,172,172, paint);
注:TextPrint可以换行
Canvas canvas = page.getCanvas();
TextPaint paint = new TextPaint();
//这里绘制要在打印的纸上的内容,如果精确一点的话,根据pageHeight,pageWidth计算就行,这里的内容和自定义View的内容一样,
//把自定义View绘制的东西拉过来直接就可以用
int titleBaseLine= 50;
int leftMargin = 60;
if (flag== 1){
// 会议
paint.setColor(Color.BLACK);
paint.setTextSize(20);
StaticLayout myStaticLayout = new StaticLayout(result.get(i).post_title, paint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
canvas.translate(0,titleBaseLine);
myStaticLayout.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.BLACK);
StaticLayout myStaticLayout1 = new StaticLayout(result.get(i).post_excerpt, paint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
canvas.translate(0,35);
myStaticLayout1.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.BLACK);
StaticLayout myStaticLayout6 = new StaticLayout("时间:"+result.get(i).meeting_date_gmt+"\u3000\u3000"+"地址:"+result.get(i).meeting_address+"\n"+"主持人:"+result.get(i).meeting_author+"\u3000"+"记录人:"+result.get(i).meeting_recorder+"\u3000"+"应到人数:"+result.get(i).meeting_memberYD+"\u3000"+"实到人数:"+result.get(i).meeting_memberSD, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(40,30);
myStaticLayout6.draw(canvas);
paint.setTextSize(13);
paint.setColor(Color.BLACK);
Spanned ss = Html.fromHtml(result.get(i).post_content);
StaticLayout myStaticLayout2 = new StaticLayout(ss, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(0,50);
myStaticLayout2.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.GRAY);
StaticLayout myStaticLayout3 = new StaticLayout("笔记内容:", paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(0,titleBaseLine+myStaticLayout2.getLineCount()*11);
myStaticLayout3.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.BLACK);
StaticLayout myStaticLayout4 = new StaticLayout(result.get(i).content, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(25,30);
myStaticLayout4.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.BLACK);
StaticLayout myStaticLayout7 = new StaticLayout(result.get(i).name, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(canvas.getWidth()-180,30);
myStaticLayout7.draw(canvas);
paint.setTextSize(14);
paint.setColor(Color.BLACK);
StaticLayout myStaticLayout5 = new StaticLayout(result.get(i).addtime, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
canvas.translate(-80,30);
myStaticLayout5.draw(canvas);
}
else if (flag == 2){ // 单个会议 if (i == 0){ paint.setColor(Color.BLACK); paint.setTextSize(20); StaticLayout myStaticLayout = new StaticLayout(result1.get(i).post_title, paint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); canvas.translate(0,titleBaseLine); myStaticLayout.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout1 = new StaticLayout(result1.get(i).post_excerpt, paint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); canvas.translate(0,35); myStaticLayout1.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout6 = new StaticLayout("时间:"+result1.get(i).meeting_date_gmt+"\u3000\u3000"+"地址:"+result1.get(i).meeting_address+"\n"+"主持人:"+result1.get(i).meeting_author+"\u3000"+"记录人:"+result1.get(i).meeting_recorder+"\u3000"+"应到人数:"+result1.get(i).meeting_memberYD+"\u3000"+"实到人数:"+result1.get(i).meeting_memberSD, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(40,30); myStaticLayout6.draw(canvas); paint.setTextSize(13); paint.setColor(Color.BLACK); Spanned ss = Html.fromHtml(result1.get(i).post_content); StaticLayout myStaticLayout2 = new StaticLayout(ss, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(0,50); myStaticLayout2.draw(canvas); for(int a = 0;a< 3;a++){ paint.setTextSize(14); paint.setColor(Color.GRAY); StaticLayout myStaticLayout3 = new StaticLayout("笔记内容:", paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (a == 0){ canvas.translate(0,titleBaseLine+myStaticLayout2.getLineCount()*10); }else{ int length = result1.get(a-1).content.length()/30+1; canvas.translate(0,titleBaseLine+myStaticLayout2.getLineCount()*10+length*20+50); } myStaticLayout3.draw(canvas); canvas.save(); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout4 = new StaticLayout(result1.get(a).content, paint, canvas.getWidth()-leftMargin-25, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(25,30); myStaticLayout4.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout7 = new StaticLayout(result1.get(a).name, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(canvas.getWidth()-180,40+myStaticLayout4.getLineCount()*10); myStaticLayout7.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout5 = new StaticLayout(result1.get(a).addtime, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(-80,30); myStaticLayout5.draw(canvas); canvas.restore(); } }else{ for(int a = i*3;a< 3+i*3;a++){ paint.setTextSize(14); paint.setColor(Color.GRAY); StaticLayout myStaticLayout3 = new StaticLayout("笔记内容:", paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (a == i*3){ canvas.translate(40,titleBaseLine); }else{ int length = result1.get(a-1).content.length()/30+1; canvas.translate(0,titleBaseLine+length*20+50); } myStaticLayout3.draw(canvas); canvas.save(); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout4 = new StaticLayout(result1.get(a).content, paint, canvas.getWidth()-leftMargin-25, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(25,30); myStaticLayout4.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout7 = new StaticLayout(result1.get(a).name, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(canvas.getWidth()-180,40+myStaticLayout4.getLineCount()*10); myStaticLayout7.draw(canvas); paint.setTextSize(14); paint.setColor(Color.BLACK); StaticLayout myStaticLayout5 = new StaticLayout(result1.get(a).addtime, paint, canvas.getWidth()-leftMargin, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); canvas.translate(-80,30); myStaticLayout5.draw(canvas); canvas.restore(); } } }
161. }
162. }
大概解释下,这个MyPrintAdapter继承自PrintDocumentAdapter,PrintDocumentAdapter有自己的生命周期,这个生命周期是和打印时的操作对应上的,如果有需要的参数变量可以通过构造方法传进去,比如我就传了个Context,虽然没怎么用,他的生命周期依次为onStart,onLayout,onWrite,onFinish,从名字上就能看出来大概什么时候调用,start用在刚开始的时候,layout的回调是在生成打印预览的时候布局时候的回调,代码在写的过程就需要把所需要的东西绘制上去,这时就走了write的回调,在write的回调里面用自定义view的方式绘制需要的内容就行了,finish就是完事了。这个生命周期比较简单,可以自行参照源码看看就知道大致流程了。WriteResultCallBack这个回调就是绘制东西的流程,也有自己的周期,可以通过回调的方式通知PrintDocumentAdapter绘制的相关结果失败或者成功。其余部分代码上都有解释。
这里面有个比较麻烦的地方就是:android在绘制的时候是按照dpi,或者px来绘制内容的,但是在纸上的话就是按照cm来绘制内容的,这中间有一个比例转化关系,getHeightMiles获取到mile值,这个值是比英寸还小的单位,转化为英寸后,比如转化为英寸后*72就是72dots per inch,就是72dpi,当然你可以设置的更高,根据打印机的配置试试看吧。
另外需要注意的是,用手机打印比不上电脑,没有想象的那么快,需要等一小会儿。