14b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/* 24b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Copyright (C) 2013 The Android Open Source Project 34b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 44b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 54b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * you may not use this file except in compliance with the License. 64b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * You may obtain a copy of the License at 74b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 84b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * http://www.apache.org/licenses/LICENSE-2.0 94b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * 104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Unless required by applicable law or agreed to in writing, software 114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * distributed under the License is distributed on an "AS IS" BASIS, 124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * See the License for the specific language governing permissions and 144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * limitations under the License. 154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovpackage android.print; 184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslavimport android.content.Context; 204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.AsyncTask; 216283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslavimport android.os.Bundle; 224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal; 234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal.OnCancelListener; 2445c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkeyimport android.os.FileUtils; 2545c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkeyimport android.os.OperationCanceledException; 26d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganovimport android.os.ParcelFileDescriptor; 274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslavimport com.android.internal.R; 3017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.File; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileInputStream; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileOutputStream; 364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.IOException; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.InputStream; 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.OutputStream; 394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 4119fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * Adapter for printing PDF files. This class could be useful if you 42798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * want to print a file and intercept when the system is ready 4319fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * spooling the data, so you can delete the file if it is a 4419fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * temporary one. To achieve this one must override {@link #onFinish()} 4519fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * and delete the file yourself. 46b450d0d4d7fca16674fea02f15e21dc737352c40Svetoslav * 47b450d0d4d7fca16674fea02f15e21dc737352c40Svetoslav * @hide 484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 499abf735387329758ca310acad3baa70eee1dba42Svetoslavpublic class PrintFileDocumentAdapter extends PrintDocumentAdapter { 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 511c8f1e06a609507533609b4e04161c1c4fcb2849Philip P. Moltmann private static final String LOG_TAG = "PrintedFileDocAdapter"; 524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav private final Context mContext; 5417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final File mFile; 564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 57798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private final PrintDocumentInfo mDocumentInfo; 58798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov 594b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private WriteFileAsyncTask mWriteFileAsyncTask; 604b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov /** 62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Constructor. 63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param context Context for accessing resources. 6519fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * @param file The PDF file to print. 66798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param documentInfo The information about the printed file. 67798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov */ 68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public PrintFileDocumentAdapter(Context context, File file, 69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov PrintDocumentInfo documentInfo) { 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (file == null) { 714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("File cannot be null!"); 724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov if (documentInfo == null) { 74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov throw new IllegalArgumentException("documentInfo cannot be null!"); 75798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov } 7617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mContext = context; 774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mFile = file; 78798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mDocumentInfo = documentInfo; 794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 836283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav CancellationSignal cancellationSignal, LayoutResultCallback callback, 846283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav Bundle metadata) { 85798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov callback.onLayoutFinished(mDocumentInfo, false); 86a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 87a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 88a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 89d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, 90a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal cancellationSignal, WriteResultCallback callback) { 9117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback); 924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov (Void[]) null); 944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 9617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> { 974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 98d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private final ParcelFileDescriptor mDestination; 994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 100a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final WriteResultCallback mResultCallback; 1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final CancellationSignal mCancellationSignal; 1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 104d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public WriteFileAsyncTask(ParcelFileDescriptor destination, 105a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal cancellationSignal, WriteResultCallback callback) { 1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mDestination = destination; 107fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav mResultCallback = callback; 10817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mCancellationSignal = cancellationSignal; 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mCancellationSignal.setOnCancelListener(new OnCancelListener() { 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onCancel() { 1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov cancel(true); 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }); 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected Void doInBackground(Void... params) { 11945c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey try (InputStream in = new FileInputStream(mFile); 12045c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey OutputStream out = new FileOutputStream(mDestination.getFileDescriptor())) { 12145c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey FileUtils.copy(in, out, null, mCancellationSignal); 12245c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey } catch (OperationCanceledException e) { 12345c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey // Ignored; already handled below 12445c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey } catch (IOException e) { 12545c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey Log.e(LOG_TAG, "Error writing data!", e); 12645c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey mResultCallback.onWriteFailed(mContext.getString( 12745c97df89d6c9d8b5252ba9fc27c41e75c81254dJeff Sharkey R.string.write_fail_reason_cannot_write)); 1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 13117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 13217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav @Override 13317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav protected void onPostExecute(Void result) { 13485b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES}); 13517b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav } 13617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 13717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav @Override 13817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav protected void onCancelled(Void result) { 13917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mResultCallback.onWriteFailed(mContext.getString( 14017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav R.string.write_fail_reason_cancelled)); 14117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav } 1424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 145