PrintFileDocumentAdapter.java revision d26d4898fcc9b78f4b66118895c375384098205e
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/**
39798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * Adapter for printing files. This class could be useful if you
40798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * want to print a file and intercept when the system is ready
41798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * spooling the data, so you can deleted the file if it is a
42798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov * temporary one.
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
449abf735387329758ca310acad3baa70eee1dba42Svetoslavpublic class PrintFileDocumentAdapter extends PrintDocumentAdapter {
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
46798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private static final String LOG_TAG = "PrintedFileDocumentAdapter";
474b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
4817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav    private final Context mContext;
4917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final File mFile;
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
52798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    private final PrintDocumentInfo mDocumentInfo;
53798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov
544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private WriteFileAsyncTask mWriteFileAsyncTask;
554b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
56798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    /**
57798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * Constructor.
58798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     *
59798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @param context Context for accessing resources.
60798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @param file The file to print.
61798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     * @param documentInfo The information about the printed file.
62798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov     */
63798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov    public PrintFileDocumentAdapter(Context context, File file,
64798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            PrintDocumentInfo documentInfo) {
654b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (file == null) {
664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            throw new IllegalArgumentException("File cannot be null!");
674b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
68798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        if (documentInfo == null) {
69798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov            throw new IllegalArgumentException("documentInfo cannot be null!");
70798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        }
7117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        mContext = context;
724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mFile = file;
73798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        mDocumentInfo = documentInfo;
744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
77a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
786283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav            CancellationSignal cancellationSignal, LayoutResultCallback callback,
796283608e0bd40548742839f5a8b02f7e5c9c5c7cSvetoslav            Bundle metadata) {
80798bed6cc7d273e72b0253288605db9cd2b57740Svetoslav Ganov        callback.onLayoutFinished(mDocumentInfo, false);
81a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
82a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
83a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    @Override
84d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov    public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
85a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            CancellationSignal cancellationSignal, WriteResultCallback callback) {
8617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
874b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                (Void[]) null);
894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
9117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav    private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
93d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        private final ParcelFileDescriptor mDestination;
944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
95a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final WriteResultCallback mResultCallback;
964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final CancellationSignal mCancellationSignal;
984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
99d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov        public WriteFileAsyncTask(ParcelFileDescriptor destination,
100a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                CancellationSignal cancellationSignal, WriteResultCallback callback) {
1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mDestination = destination;
102fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav            mResultCallback = callback;
10317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav            mCancellationSignal = cancellationSignal;
1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mCancellationSignal.setOnCancelListener(new OnCancelListener() {
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                @Override
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                public void onCancel() {
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    cancel(true);
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            });
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        protected Void doInBackground(Void... params) {
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            InputStream in = null;
115d26d4898fcc9b78f4b66118895c375384098205eSvetoslav Ganov            OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final byte[] buffer = new byte[8192];
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            try {
11817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                in = new FileInputStream(mFile);
1194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                while (true) {
12017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    if (isCancelled()) {
12117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                        break;
12217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    }
1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    final int readByteCount = in.read(buffer);
1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    if (readByteCount < 0) {
1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        break;
1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    out.write(buffer, 0, readByteCount);
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } catch (IOException ioe) {
13017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                 Log.e(LOG_TAG, "Error writing data!", ioe);
13117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                 mResultCallback.onWriteFailed(mContext.getString(
13217b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                         R.string.write_fail_reason_cannot_write));
1334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } finally {
1344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(in);
1354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(out);
1364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
1374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return null;
1384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
13917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
14017b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        @Override
14117b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        protected void onPostExecute(Void result) {
14285b1f883056a1d74473fd9ce774948878f389ab6Svetoslav Ganov            mResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES});
14317b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        }
14417b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav
14517b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        @Override
14617b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        protected void onCancelled(Void result) {
14717b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav            mResultCallback.onWriteFailed(mContext.getString(
14817b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav                    R.string.write_fail_reason_cancelled));
14917b7f6e6d4ec9f5e9597bfd283f1c017b6c66275Svetoslav        }
1504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
1524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
153