PrintFileDocumentAdapter.java revision a00271533f639c8ed36429c663889ac9f654bc72
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
194b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.AsyncTask;
204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal;
214b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.os.CancellationSignal.OnCancelListener;
224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport android.util.Log;
234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport libcore.io.IoUtils;
254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.File;
274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileDescriptor;
284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileInputStream;
294b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.FileOutputStream;
304b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.IOException;
314b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.InputStream;
324b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.io.OutputStream;
334b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.ArrayList;
344b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganovimport java.util.List;
354b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
364b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov/**
374b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov * Adapter for printing files.
384b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov */
39a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganovfinal class FileDocumentAdapter extends PrintDocumentAdapter {
404b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
41a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    private static final String LOG_TAG = "FileDocumentAdapter";
424b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
434b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private final File mFile;
444b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
454b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private WriteFileAsyncTask mWriteFileAsyncTask;
464b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
47a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public FileDocumentAdapter(File file) {
484b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        if (file == null) {
494b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            throw new IllegalArgumentException("File cannot be null!");
504b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
514b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mFile = file;
524b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
534b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
544b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    @Override
55a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
56a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            CancellationSignal cancellationSignal, LayoutResultCallback callback) {
57a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        // TODO: When we have a PDF rendering library we should query the page count.
58a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        PrintDocumentInfo info =  new PrintDocumentInfo.Builder()
59a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN).create();
60a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        callback.onLayoutFinished(info, false);
61a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    }
62a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov
63a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    @Override
64a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void onWrite(List<PageRange> pages, FileDescriptor destination,
65a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov            CancellationSignal cancellationSignal, WriteResultCallback callback) {
664b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mWriteFileAsyncTask = new WriteFileAsyncTask(mFile, destination, cancellationSignal,
67fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav                callback);
684b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
694b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                (Void[]) null);
704b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
714b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
724b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
734b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    private static final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
744b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
754b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final File mSource;
764b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
774b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final FileDescriptor mDestination;
784b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
79a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov        private final WriteResultCallback mResultCallback;
804b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
814b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        private final CancellationSignal mCancellationSignal;
824b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
834b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        public WriteFileAsyncTask(File source, FileDescriptor destination,
84a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                CancellationSignal cancellationSignal, WriteResultCallback callback) {
854b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mSource = source;
864b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mDestination = destination;
87fd90651cfcc7e2b75254666fd6861038b72fb4acSvetoslav            mResultCallback = callback;
884b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mCancellationSignal = cancellationSignal;
894b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            mCancellationSignal.setOnCancelListener(new OnCancelListener() {
904b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                @Override
914b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                public void onCancel() {
924b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    cancel(true);
934b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
944b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            });
954b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
964b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
974b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        @Override
984b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        protected Void doInBackground(Void... params) {
994b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            InputStream in = null;
1004b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            OutputStream out = new FileOutputStream(mDestination);
1014b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            final byte[] buffer = new byte[8192];
1024b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            try {
1034b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                in = new FileInputStream(mSource);
1044b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                while (true) {
1054b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    final int readByteCount = in.read(buffer);
1064b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    if (readByteCount < 0) {
1074b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                        break;
1084b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    }
1094b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    out.write(buffer, 0, readByteCount);
1104b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1114b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } catch (IOException ioe) {
1124b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                Log.e(LOG_TAG, "Error writing data!", ioe);
1134b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov             } finally {
1144b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(in);
1154b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                IoUtils.closeQuietly(out);
1164b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                if (!isCancelled()) {
1174b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    List<PageRange> pages = new ArrayList<PageRange>();
1184b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                    pages.add(PageRange.ALL_PAGES);
119a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    mResultCallback.onWriteFinished(pages);
1204b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                } else {
121a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov                    mResultCallback.onWriteFailed("Cancelled");
1224b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov                }
1234b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            }
1244b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov            return null;
1254b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov        }
1264b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov    }
1274b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov}
1284b9a4d16872bbb50712e007b419ac0b35ff1582dSvetoslav Ganov
129