MyPrintService.java revision e8c204dc3956cdcffd88cdcf96b5a644a9b7d2ad
1package foo.bar.printservice; 2 3import android.content.Context; 4import android.content.Intent; 5import android.net.Uri; 6import android.os.AsyncTask; 7import android.os.Handler; 8import android.os.Looper; 9import android.os.Message; 10import android.print.PrintAttributes; 11import android.print.PrintAttributes.Margins; 12import android.print.PrintAttributes.MediaSize; 13import android.print.PrintAttributes.Resolution; 14import android.print.PrintAttributes.Tray; 15import android.print.PrintJobInfo; 16import android.print.PrinterCapabilitiesInfo; 17import android.print.PrinterId; 18import android.print.PrinterInfo; 19import android.printservice.PrintJob; 20import android.printservice.PrintService; 21import android.printservice.PrinterDiscoverySession; 22import android.util.Log; 23import android.widget.Toast; 24 25import libcore.io.IoUtils; 26 27import java.io.BufferedInputStream; 28import java.io.BufferedOutputStream; 29import java.io.File; 30import java.io.FileInputStream; 31import java.io.FileOutputStream; 32import java.io.IOException; 33import java.io.InputStream; 34import java.io.OutputStream; 35import java.util.ArrayList; 36import java.util.List; 37 38public class MyPrintService extends PrintService { 39 40 private static final String LOG_TAG = "MyPrintService"; 41 42 private Handler mHandler; 43 44 private PrinterInfo mFirstFakePrinter; 45 46 private PrinterInfo mSecondFakePrinter; 47 48 private AsyncTask<Void, Void, Void> mFakePrintTask; 49 50 private FakePrinterDiscoverySession mSession; 51 52 @Override 53 public void onCreate() { 54 mFirstFakePrinter = new PrinterInfo.Builder(generatePrinterId("Printer 1"), 55 "SHGH-21344", PrinterInfo.STATUS_READY).create(); 56 mSecondFakePrinter = new PrinterInfo.Builder(generatePrinterId("Printer 2"), 57 "OPPPP-09434", PrinterInfo.STATUS_READY).create(); 58 } 59 60 @Override 61 protected void onConnected() { 62 Log.i(LOG_TAG, "#onConnected()"); 63 mHandler = new MyHandler(getMainLooper()); 64 } 65 66 @Override 67 protected void onDisconnected() { 68 Log.i(LOG_TAG, "#onDisconnected()"); 69 if (mSession != null) { 70 mSession.cancellAddingFakePrinters(); 71 } 72 } 73 74 @Override 75 protected PrinterDiscoverySession onCreatePrinterDiscoverySession() { 76 return new FakePrinterDiscoverySession(this); 77 } 78 79 @Override 80 protected void onRequestCancelPrintJob(PrintJob printJob) { 81 Log.i(LOG_TAG, "#onRequestCancelPrintJob() printJobId: " + printJob.getId()); 82 if (mHandler.hasMessages(MyHandler.MSG_HANDLE_PRINT_JOB)) { 83 mHandler.removeMessages(MyHandler.MSG_HANDLE_PRINT_JOB); 84 if (printJob.isQueued() || printJob.isStarted()) { 85 printJob.cancel(); 86 } 87 } else if (mFakePrintTask != null) { 88 mFakePrintTask.cancel(true); 89 } else { 90 if (printJob.isQueued() || printJob.isStarted()) { 91 printJob.cancel(); 92 } 93 } 94 } 95 96 @Override 97 public void onPrintJobQueued(final PrintJob printJob) { 98 Log.i(LOG_TAG, "#onPrintJobQueued()"); 99// printJob.fail("I am lazy today!"); 100 Message message = mHandler.obtainMessage(MyHandler.MSG_HANDLE_PRINT_JOB, printJob); 101// mHandler.sendMessageDelayed(message, 20000); 102 mHandler.sendMessageDelayed(message, 0); 103 } 104 105 private void handleHandleQueuedPrintJob(final PrintJob printJob) { 106 if (printJob.isQueued()) { 107 printJob.start(); 108 } 109 110 final PrintJobInfo info = printJob.getInfo(); 111 final File file = new File(getFilesDir(), info.getLabel() + ".pdf"); 112 113 Toast.makeText(MyPrintService.this, 114 "[STARTED] Printer: " + info.getPrinterId().getLocalId(), 115 Toast.LENGTH_SHORT).show(); 116 117 mFakePrintTask = new AsyncTask<Void, Void, Void>() { 118 @Override 119 protected Void doInBackground(Void... params) { 120 // Simulate slow print service 121// SystemClock.sleep(20000); 122 123 InputStream in = new BufferedInputStream( 124 new FileInputStream(printJob.getDocument().getData())); 125 OutputStream out = null; 126 try { 127 out = new BufferedOutputStream(new FileOutputStream(file)); 128 final byte[] buffer = new byte[8192]; 129 while (true) { 130 if (isCancelled()) { 131 if (printJob.isStarted()) { 132 printJob.cancel(); 133 } 134 break; 135 } 136 final int readByteCount = in.read(buffer); 137 if (readByteCount < 0) { 138 break; 139 } 140 out.write(buffer, 0, readByteCount); 141 } 142 } catch (IOException ioe) { 143 /* ignore */ 144 } finally { 145 IoUtils.closeQuietly(in); 146 IoUtils.closeQuietly(out); 147 if (isCancelled()) { 148 file.delete(); 149 } 150 } 151 return null; 152 } 153 154 @Override 155 protected void onPostExecute(Void result) { 156 if (printJob.isStarted()) { 157 printJob.complete(); 158 } 159 160 Toast.makeText(MyPrintService.this, 161 "[COMPLETED] Printer: " + info.getPrinterId().getLocalId(), 162 Toast.LENGTH_SHORT).show(); 163 164 file.setReadable(true, false); 165 166 Intent intent = new Intent(Intent.ACTION_VIEW); 167 intent.setDataAndType(Uri.fromFile(file), "application/pdf"); 168 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 169 startActivity(intent, null); 170 171 mFakePrintTask = null; 172 } 173 }; 174 mFakePrintTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null); 175 } 176 177 private final class MyHandler extends Handler { 178 public static final int MSG_HANDLE_PRINT_JOB = 3; 179 180 public MyHandler(Looper looper) { 181 super(looper, null, true); 182 } 183 184 @Override 185 public void handleMessage(Message message) { 186 switch (message.what) { 187 case MSG_HANDLE_PRINT_JOB: { 188 PrintJob printJob = (PrintJob) message.obj; 189 handleHandleQueuedPrintJob(printJob); 190 } break; 191 } 192 } 193 } 194 195 private final class FakePrinterDiscoverySession extends PrinterDiscoverySession { 196 private final Handler mSesionHandler = new SessionHandler(getMainLooper()); 197 198 public FakePrinterDiscoverySession(Context context) { 199 super(context); 200 } 201 202 @Override 203 public void onOpen(List<PrinterId> priorityList) { 204 Log.i(LOG_TAG, "#onStartDiscoverPrinters()"); 205 Message message1 = mSesionHandler.obtainMessage( 206 SessionHandler.MSG_ADD_FIRST_FAKE_PRINTER, this); 207 mSesionHandler.sendMessageDelayed(message1, 0); 208 209 Message message2 = mSesionHandler.obtainMessage( 210 SessionHandler.MSG_ADD_SECOND_FAKE_PRINTER, this); 211 mSesionHandler.sendMessageDelayed(message2, 10000); 212 } 213 214 @Override 215 public void onClose() { 216 cancellAddingFakePrinters(); 217 Log.i(LOG_TAG, "#onStopDiscoverPrinters()"); 218 } 219 220 @Override 221 public void onRequestPrinterUpdate(PrinterId printerId) { 222 if (printerId.equals(mFirstFakePrinter.getId())) { 223 PrinterCapabilitiesInfo capabilities = 224 new PrinterCapabilitiesInfo.Builder(printerId) 225 .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) 226 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 227 MediaSize.ISO_A2), true) 228 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 229 MediaSize.ISO_A3), false) 230 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 231 MediaSize.ISO_A4), false) 232 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 233 MediaSize.NA_LETTER), false) 234 .addResolution(new Resolution("R1", getString( 235 R.string.resolution_600x600), 600, 600), true) 236 .addInputTray(new Tray("FirstInputTray", getString( 237 R.string.input_tray_first)), false) 238 .addOutputTray(new Tray("FirstOutputTray", getString( 239 R.string.output_tray_first)), false) 240 .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE 241 | PrintAttributes.DUPLEX_MODE_LONG_EDGE 242 | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, 243 PrintAttributes.DUPLEX_MODE_NONE) 244 .setColorModes(PrintAttributes.COLOR_MODE_COLOR 245 | PrintAttributes.COLOR_MODE_MONOCHROME, 246 PrintAttributes.COLOR_MODE_COLOR) 247 .setFittingModes(PrintAttributes.FITTING_MODE_NONE 248 | PrintAttributes.FITTING_MODE_FIT_TO_PAGE, 249 PrintAttributes.FITTING_MODE_NONE) 250 .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT 251 | PrintAttributes.ORIENTATION_LANDSCAPE, 252 PrintAttributes.ORIENTATION_PORTRAIT) 253 .create(); 254 255 PrinterInfo printer = new PrinterInfo.Builder(mFirstFakePrinter) 256 .setCapabilities(capabilities) 257 .create(); 258 259 List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); 260 printers.add(printer); 261 updatePrinters(printers); 262 263 } else if (printerId.equals(mSecondFakePrinter.getId())) { 264 PrinterCapabilitiesInfo capabilities = 265 new PrinterCapabilitiesInfo.Builder(printerId) 266 .setMinMargins(new Margins(0, 0, 0, 0), new Margins(0, 0, 0, 0)) 267 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 268 MediaSize.ISO_A4), true) 269 .addMediaSize(MediaSize.createMediaSize(getPackageManager(), 270 MediaSize.ISO_A5), false) 271 .addResolution(new Resolution("R1", getString( 272 R.string.resolution_200x200), 200, 200), true) 273 .addResolution(new Resolution("R2", getString( 274 R.string.resolution_300x300), 300, 300), false) 275 .addInputTray(new Tray("FirstInputTray", getString( 276 R.string.input_tray_first)), false) 277 .addInputTray(new Tray("SecondInputTray", getString( 278 R.string.input_tray_second)), true) 279 .addOutputTray(new Tray("FirstOutputTray", getString( 280 R.string.output_tray_first)), false) 281 .addOutputTray(new Tray("SecondOutputTray", getString( 282 R.string.output_tray_second)), true) 283 .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE 284 | PrintAttributes.DUPLEX_MODE_LONG_EDGE 285 | PrintAttributes.DUPLEX_MODE_SHORT_EDGE, 286 PrintAttributes.DUPLEX_MODE_SHORT_EDGE) 287 .setColorModes(PrintAttributes.COLOR_MODE_COLOR 288 | PrintAttributes.COLOR_MODE_MONOCHROME, 289 PrintAttributes.COLOR_MODE_MONOCHROME) 290 .setFittingModes(PrintAttributes.FITTING_MODE_FIT_TO_PAGE 291 | PrintAttributes.FITTING_MODE_NONE, 292 PrintAttributes.FITTING_MODE_FIT_TO_PAGE) 293 .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT 294 | PrintAttributes.ORIENTATION_LANDSCAPE, 295 PrintAttributes.ORIENTATION_LANDSCAPE) 296 .create(); 297 298 PrinterInfo printer = new PrinterInfo.Builder(mSecondFakePrinter) 299 .setCapabilities(capabilities) 300 .create(); 301 302 List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); 303 printers.add(printer); 304 updatePrinters(printers); 305 } 306 } 307 308 private void addFirstFakePrinter(PrinterDiscoverySession session) { 309 List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); 310 printers.add(mFirstFakePrinter); 311 session.addPrinters(printers); 312 } 313 314 private void addSecondFakePrinter(PrinterDiscoverySession session) { 315 List<PrinterInfo> printers = new ArrayList<PrinterInfo>(); 316 printers.add(mSecondFakePrinter); 317 session.addPrinters(printers); 318 } 319 320 private void cancellAddingFakePrinters() { 321 mSesionHandler.removeMessages(SessionHandler.MSG_ADD_FIRST_FAKE_PRINTER); 322 mSesionHandler.removeMessages(SessionHandler.MSG_ADD_SECOND_FAKE_PRINTER); 323 } 324 325 final class SessionHandler extends Handler { 326 public static final int MSG_ADD_FIRST_FAKE_PRINTER = 1; 327 public static final int MSG_ADD_SECOND_FAKE_PRINTER = 2; 328 329 public SessionHandler(Looper looper) { 330 super(looper, null, true); 331 } 332 333 @Override 334 public void handleMessage(Message message) { 335 switch (message.what) { 336 case MSG_ADD_FIRST_FAKE_PRINTER: { 337 PrinterDiscoverySession session = 338 (PrinterDiscoverySession) message.obj; 339 addFirstFakePrinter(session); 340 } break; 341 342 case MSG_ADD_SECOND_FAKE_PRINTER: { 343 PrinterDiscoverySession session = 344 (PrinterDiscoverySession) message.obj; 345 addSecondFakePrinter(session); 346 } break; 347 } 348 } 349 } 350 } 351} 352