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; 24d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganovimport android.os.ParcelFileDescriptor; 254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log; 264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 2717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslavimport com.android.internal.R; 2817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils; 304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.File; 324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileInputStream; 334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileOutputStream; 344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.IOException; 354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.InputStream; 364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.OutputStream; 374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/** 3919fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * Adapter for printing PDF files. This class could be useful if you 40798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * want to print a file and intercept when the system is ready 4119fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * spooling the data, so you can delete the file if it is a 4219fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * temporary one. To achieve this one must override {@link #onFinish()} 4319fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * and delete the file yourself. 44b450d0d4d7fca16674fea02f15e21dc737352c40Svetoslav * 45b450d0d4d7fca16674fea02f15e21dc737352c40Svetoslav * @hide 464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */ 479abf735387329758ca310acad3baa70eee1dba42Svetoslavpublic class PrintFileDocumentAdapter extends PrintDocumentAdapter { 484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 491c8f1e06a609507533609b4e04161c1c4fcb2849Philip P. Moltmann private static final String LOG_TAG = "PrintedFileDocAdapter"; 504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 5117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav private final Context mContext; 5217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final File mFile; 544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 55798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov private final PrintDocumentInfo mDocumentInfo; 56798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov 574b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private WriteFileAsyncTask mWriteFileAsyncTask; 584b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov /** 60798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Constructor. 61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * 62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param context Context for accessing resources. 6319fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov * @param file The PDF file to print. 64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * @param documentInfo The information about the printed file. 65798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov */ 66798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov public PrintFileDocumentAdapter(Context context, File file, 67798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov PrintDocumentInfo documentInfo) { 684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (file == null) { 694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov throw new IllegalArgumentException("File cannot be null!"); 704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov if (documentInfo == null) { 72798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov throw new IllegalArgumentException("documentInfo cannot be null!"); 73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov } 7417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mContext = context; 754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mFile = file; 76798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov mDocumentInfo = documentInfo; 774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 794b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 80a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, 816283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav CancellationSignal cancellationSignal, LayoutResultCallback callback, 826283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav Bundle metadata) { 83798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov callback.onLayoutFinished(mDocumentInfo, false); 84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov } 85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov 86a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov @Override 87d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, 88a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal cancellationSignal, WriteResultCallback callback) { 8917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback); 904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov (Void[]) null); 924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 9417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> { 954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 96d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov private final ParcelFileDescriptor mDestination; 974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 98a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov private final WriteResultCallback mResultCallback; 994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov private final CancellationSignal mCancellationSignal; 1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 102d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov public WriteFileAsyncTask(ParcelFileDescriptor destination, 103a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov CancellationSignal cancellationSignal, WriteResultCallback callback) { 1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mDestination = destination; 105fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav mResultCallback = callback; 10617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mCancellationSignal = cancellationSignal; 1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov mCancellationSignal.setOnCancelListener(new OnCancelListener() { 1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov public void onCancel() { 1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov cancel(true); 1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov }); 1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov @Override 1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov protected Void doInBackground(Void... params) { 1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov InputStream in = null; 118d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov OutputStream out = new FileOutputStream(mDestination.getFileDescriptor()); 1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final byte[] buffer = new byte[8192]; 1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov try { 12117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav in = new FileInputStream(mFile); 1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov while (true) { 12317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav if (isCancelled()) { 12417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav break; 12517b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav } 1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov final int readByteCount = in.read(buffer); 1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov if (readByteCount < 0) { 1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov break; 1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov out.write(buffer, 0, readByteCount); 1314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } catch (IOException ioe) { 13317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav Log.e(LOG_TAG, "Error writing data!", ioe); 13417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mResultCallback.onWriteFailed(mContext.getString( 13517b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav R.string.write_fail_reason_cannot_write)); 1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } finally { 1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IoUtils.closeQuietly(in); 1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov IoUtils.closeQuietly(out); 1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov return null; 1414b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 14217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 14317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav @Override 14417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav protected void onPostExecute(Void result) { 14585b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov mResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES}); 14617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav } 14717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav 14817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav @Override 14917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav protected void onCancelled(Void result) { 15017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav mResultCallback.onWriteFailed(mContext.getString( 15117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav R.string.write_fail_reason_cancelled)); 15217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav } 1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov } 1544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov} 1554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov 156