1package foo.bar.printservice2;
2
3import android.content.Intent;
4import android.net.Uri;
5import android.os.AsyncTask;
6import android.os.Handler;
7import android.os.Looper;
8import android.os.Message;
9import android.print.PrintAttributes;
10import android.print.PrintAttributes.Margins;
11import android.print.PrintAttributes.Resolution;
12import android.print.PrintAttributes.Tray;
13import android.print.PrintJobInfo;
14import android.print.PrinterId;
15import android.print.PrinterInfo;
16import android.printservice.PrintJob;
17import android.printservice.PrintService;
18import android.util.Log;
19import android.widget.Toast;
20
21import java.io.BufferedInputStream;
22import java.io.BufferedOutputStream;
23import java.io.File;
24import java.io.FileInputStream;
25import java.io.FileOutputStream;
26import java.io.IOException;
27import java.io.InputStream;
28import java.io.OutputStream;
29import java.util.ArrayList;
30import java.util.List;
31
32public class MyPrintService extends PrintService {
33
34    private static final String LOG_TAG = MyPrintService.class.getSimpleName();
35
36    private Handler mHandler;
37
38    @Override
39    protected void onConnected() {
40        mHandler = new MyHandler(getMainLooper());
41        Log.i(LOG_TAG, "#onConnected()");
42    }
43
44    @Override
45    protected void onDisconnected() {
46        Log.i(LOG_TAG, "#onDisconnected()");
47    }
48
49    @Override
50    protected void onStartPrinterDiscovery() {
51        Log.i(LOG_TAG, "#onStartDiscoverPrinters()");
52        Message message1 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_FIRST_FAKE_PRINTER);
53        mHandler.sendMessageDelayed(message1, 0);
54
55        Message message2 = mHandler.obtainMessage(MyHandler.MESSAGE_ADD_SECOND_FAKE_PRINTER);
56        mHandler.sendMessageDelayed(message2, 10000);
57    }
58
59    @Override
60    protected void onStopPrinterDiscovery() {
61        Log.i(LOG_TAG, "#onStopDiscoverPrinters()");
62    }
63
64    @Override
65    public void onPrintJobQueued(final PrintJob printJob) {
66        Log.i(LOG_TAG, "#onPrintJobPending()");
67        PrintJobInfo info = printJob.getInfo();
68        final File file = new File(getFilesDir(), info.getLabel() + ".pdf");
69        if (file.exists()) {
70            file.delete();
71        }
72        AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
73            @Override
74            protected Void doInBackground(Void... params) {
75                InputStream in = new BufferedInputStream(
76                        new FileInputStream(printJob.getData()));
77                OutputStream out = null;
78                try {
79                    out = new BufferedOutputStream(new FileOutputStream(file));
80                    final byte[] buffer = new byte[8192];
81                    while (true) {
82                        final int readByteCount = in.read(buffer);
83                        if (readByteCount < 0) {
84                            break;
85                        }
86                        out.write(buffer, 0, readByteCount);
87                    }
88                } catch (IOException ioe) {
89                    /* ignore */
90                } finally {
91                    try {
92                        in.close();
93                    } catch (IOException ioe) {
94                       /* ignore */
95                    }
96                    if (out != null) {
97                        try {
98                            out.close();
99                        } catch (IOException ioe) {
100                           /* ignore */
101                        }
102                    }
103                }
104                return null;
105            }
106
107            @Override
108            protected void onPostExecute(Void result) {
109                file.setExecutable(true, false);
110                file.setWritable(true, false);
111                file.setReadable(true, false);
112
113                Intent intent = new Intent(Intent.ACTION_VIEW);
114                intent.setDataAndType(Uri.fromFile(file), "application/pdf");
115                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
116                startActivity(intent, null);
117
118                if (printJob.isQueued()) {
119                    printJob.start();
120                }
121
122                PrintJobInfo info =  printJob.getInfo();
123                Toast.makeText(MyPrintService.this,
124                        "Printer: " + info.getPrinterId().getName()
125                        + " copies: " + info.getAttributes().getCopies(),
126                        Toast.LENGTH_SHORT).show();
127
128                if (printJob.isStarted()) {
129                    printJob.complete();
130                }
131            }
132        };
133        task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
134    }
135
136    private void addFirstFakePrinter() {
137        PrinterId printerId = generatePrinterId("1");
138        PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 1")
139                .setStatus(PrinterInfo.STATUS_READY)
140                .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
141                .addMediaSize(PrintAttributes.MediaSize.ISO_A2, false)
142                .addMediaSize(PrintAttributes.MediaSize.ISO_A3, false)
143                .addMediaSize(PrintAttributes.MediaSize.ISO_A4, false)
144                .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
145                .addMediaSize(PrintAttributes.MediaSize.ISO_A6, false)
146                .addMediaSize(PrintAttributes.MediaSize.NA_LETTER, true)
147                .addResolution(new Resolution("R1", getPackageName(),
148                        R.string.resolution_600x600, 600, 600), true)
149                .addInputTray(new Tray("FirstInputTray", getPackageName(),
150                        R.string.input_tray_first), false)
151                .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
152                        R.string.output_tray_first), false)
153                .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
154                        | PrintAttributes.DUPLEX_MODE_LONG_EDGE
155                        | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
156                        PrintAttributes.DUPLEX_MODE_NONE)
157                .setColorModes(PrintAttributes.COLOR_MODE_COLOR
158                        | PrintAttributes.COLOR_MODE_MONOCHROME,
159                        PrintAttributes.COLOR_MODE_COLOR)
160                .setFittingModes(PrintAttributes.FITTING_MODE_NONE
161                        | PrintAttributes.FITTING_MODE_FIT_TO_PAGE,
162                        PrintAttributes.FITTING_MODE_NONE)
163                .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
164                        | PrintAttributes.ORIENTATION_LANDSCAPE,
165                        PrintAttributes.ORIENTATION_PORTRAIT)
166                .create();
167        List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
168        printers.add(printer);
169        addPrinters(printers);
170    }
171
172    private void addSecondFakePrinter() {
173        PrinterId printerId = generatePrinterId("2");
174        PrinterInfo printer = new PrinterInfo.Builder(printerId, "Printer 2")
175                .setStatus(PrinterInfo.STATUS_READY)
176                .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0))
177                .addMediaSize(PrintAttributes.MediaSize.ISO_A4, true)
178                .addMediaSize(PrintAttributes.MediaSize.ISO_A5, false)
179                .addResolution(new Resolution("R1", getPackageName(),
180                        R.string.resolution_200x200, 200, 200), true)
181                .addResolution(new Resolution("R2", getPackageName(),
182                        R.string.resolution_300x300, 300, 300), false)
183                .addInputTray(new Tray("FirstInputTray", getPackageName(),
184                        R.string.input_tray_first), false)
185                .addInputTray(new Tray("SecondInputTray", getPackageName(),
186                        R.string.input_tray_second), true)
187                .addOutputTray(new Tray("FirstOutputTray", getPackageName(),
188                        R.string.output_tray_first), false)
189                .addOutputTray(new Tray("SecondOutputTray",  getPackageName(),
190                        R.string.output_tray_second), true)
191                .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE
192                        | PrintAttributes.DUPLEX_MODE_LONG_EDGE
193                        | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
194                        PrintAttributes.DUPLEX_MODE_SHORT_EDGE)
195                .setColorModes(PrintAttributes.COLOR_MODE_COLOR
196                        | PrintAttributes.COLOR_MODE_MONOCHROME,
197                        PrintAttributes.COLOR_MODE_MONOCHROME)
198                .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE
199                        | PrintAttributes.FITTING_MODE_NONE,
200                        PrintAttributes.FITTING_MODE_FIT_TO_PAGE)
201                .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
202                        | PrintAttributes.ORIENTATION_LANDSCAPE,
203                        PrintAttributes.ORIENTATION_LANDSCAPE)
204                .create();
205        List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
206        printers.add(printer);
207        addPrinters(printers);
208    }
209
210    private final class MyHandler extends Handler {
211
212        public static final int MESSAGE_ADD_FIRST_FAKE_PRINTER = 1;
213        public static final int MESSAGE_ADD_SECOND_FAKE_PRINTER = 2;
214
215        public MyHandler(Looper looper) {
216            super(looper, null, true);
217        }
218
219        @Override
220        public void handleMessage(Message message) {
221            switch (message.what) {
222                case MESSAGE_ADD_FIRST_FAKE_PRINTER: {
223                    addFirstFakePrinter();
224                } break;
225                case MESSAGE_ADD_SECOND_FAKE_PRINTER: {
226                    addSecondFakePrinter();
227                } break;
228            }
229        }
230    }
231}
232