PrintFileDocumentAdapter.java revision 19fba5d34a444ce145ab0d3a12c578d9d5d3f38c
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.
444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
459abf735387329758ca310acad3baa70eee1dba42Svetoslavpublic class PrintFileDocumentAdapter extends PrintDocumentAdapter {
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
47798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final String LOG_TAG = "PrintedFileDocumentAdapter";
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav    private final Context mContext;
5017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final File mFile;
524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private final PrintDocumentInfo mDocumentInfo;
54798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private WriteFileAsyncTask mWriteFileAsyncTask;
564b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
57798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
58798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Constructor.
59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
60798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @param context Context for accessing resources.
6119fba5d34a444ce145ab0d3a12c578d9d5d3f38cSvetoslav Ganov     * @param file The PDF file to print.
62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @param documentInfo The information about the printed file.
63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrintFileDocumentAdapter(Context context, File file,
65798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            PrintDocumentInfo documentInfo) {
664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (file == null) {
674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            throw new IllegalArgumentException("File cannot be null!");
684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (documentInfo == null) {
70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            throw new IllegalArgumentException("documentInfo cannot be null!");
71798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
7217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        mContext = context;
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mFile = file;
74798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mDocumentInfo = documentInfo;
754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
78a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
796283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav            CancellationSignal cancellationSignal, LayoutResultCallback callback,
806283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav            Bundle metadata) {
81798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        callback.onLayoutFinished(mDocumentInfo, false);
82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    @Override
85d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov    public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
86a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            CancellationSignal cancellationSignal, WriteResultCallback callback) {
8717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                (Void[]) null);
904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
9217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav    private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
94d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        private final ParcelFileDescriptor mDestination;
954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
96a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final WriteResultCallback mResultCallback;
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final CancellationSignal mCancellationSignal;
994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
100d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        public WriteFileAsyncTask(ParcelFileDescriptor destination,
101a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                CancellationSignal cancellationSignal, WriteResultCallback callback) {
1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mDestination = destination;
103fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav            mResultCallback = callback;
10417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav            mCancellationSignal = cancellationSignal;
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mCancellationSignal.setOnCancelListener(new OnCancelListener() {
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                @Override
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                public void onCancel() {
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    cancel(true);
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            });
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        protected Void doInBackground(Void... params) {
1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            InputStream in = null;
116d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov            OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final byte[] buffer = new byte[8192];
1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            try {
11917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                in = new FileInputStream(mFile);
1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                while (true) {
12117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    if (isCancelled()) {
12217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                        break;
12317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    }
1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    final int readByteCount = in.read(buffer);
1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    if (readByteCount < 0) {
1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        break;
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    out.write(buffer, 0, readByteCount);
1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } catch (IOException ioe) {
13117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                 Log.e(LOG_TAG, "Error writing data!", ioe);
13217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                 mResultCallback.onWriteFailed(mContext.getString(
13317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                         R.string.write_fail_reason_cannot_write));
1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } finally {
1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(in);
1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(out);
1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return null;
1394b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
14017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
14117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        @Override
14217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        protected void onPostExecute(Void result) {
14385b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES});
14417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        }
14517b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
14617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        @Override
14717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        protected void onCancelled(Void result) {
14817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav            mResultCallback.onWriteFailed(mContext.getString(
14917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    R.string.write_fail_reason_cancelled));
15017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        }
1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
1534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
154