1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.print;
18 
19 import android.content.Context;
20 import android.os.AsyncTask;
21 import android.os.Bundle;
22 import android.os.CancellationSignal;
23 import android.os.CancellationSignal.OnCancelListener;
24 import android.os.ParcelFileDescriptor;
25 import android.util.Log;
26 
27 import com.android.internal.R;
28 
29 import libcore.io.IoUtils;
30 
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.OutputStream;
37 
38 /**
39  * Adapter for printing PDF files. This class could be useful if you
40  * want to print a file and intercept when the system is ready
41  * spooling the data, so you can delete the file if it is a
42  * temporary one. To achieve this one must override {@link #onFinish()}
43  * and delete the file yourself.
44  *
45  * @hide
46  */
47 public class PrintFileDocumentAdapter extends PrintDocumentAdapter {
48 
49     private static final String LOG_TAG = "PrintedFileDocumentAdapter";
50 
51     private final Context mContext;
52 
53     private final File mFile;
54 
55     private final PrintDocumentInfo mDocumentInfo;
56 
57     private WriteFileAsyncTask mWriteFileAsyncTask;
58 
59     /**
60      * Constructor.
61      *
62      * @param context Context for accessing resources.
63      * @param file The PDF file to print.
64      * @param documentInfo The information about the printed file.
65      */
PrintFileDocumentAdapter(Context context, File file, PrintDocumentInfo documentInfo)66     public PrintFileDocumentAdapter(Context context, File file,
67             PrintDocumentInfo documentInfo) {
68         if (file == null) {
69             throw new IllegalArgumentException("File cannot be null!");
70         }
71         if (documentInfo == null) {
72             throw new IllegalArgumentException("documentInfo cannot be null!");
73         }
74         mContext = context;
75         mFile = file;
76         mDocumentInfo = documentInfo;
77     }
78 
79     @Override
onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle metadata)80     public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
81             CancellationSignal cancellationSignal, LayoutResultCallback callback,
82             Bundle metadata) {
83         callback.onLayoutFinished(mDocumentInfo, false);
84     }
85 
86     @Override
onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)87     public void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
88             CancellationSignal cancellationSignal, WriteResultCallback callback) {
89         mWriteFileAsyncTask = new WriteFileAsyncTask(destination, cancellationSignal, callback);
90         mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
91                 (Void[]) null);
92     }
93 
94     private final class WriteFileAsyncTask extends AsyncTask<Void, Void, Void> {
95 
96         private final ParcelFileDescriptor mDestination;
97 
98         private final WriteResultCallback mResultCallback;
99 
100         private final CancellationSignal mCancellationSignal;
101 
WriteFileAsyncTask(ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)102         public WriteFileAsyncTask(ParcelFileDescriptor destination,
103                 CancellationSignal cancellationSignal, WriteResultCallback callback) {
104             mDestination = destination;
105             mResultCallback = callback;
106             mCancellationSignal = cancellationSignal;
107             mCancellationSignal.setOnCancelListener(new OnCancelListener() {
108                 @Override
109                 public void onCancel() {
110                     cancel(true);
111                 }
112             });
113         }
114 
115         @Override
doInBackground(Void... params)116         protected Void doInBackground(Void... params) {
117             InputStream in = null;
118             OutputStream out = new FileOutputStream(mDestination.getFileDescriptor());
119             final byte[] buffer = new byte[8192];
120             try {
121                 in = new FileInputStream(mFile);
122                 while (true) {
123                     if (isCancelled()) {
124                         break;
125                     }
126                     final int readByteCount = in.read(buffer);
127                     if (readByteCount < 0) {
128                         break;
129                     }
130                     out.write(buffer, 0, readByteCount);
131                 }
132              } catch (IOException ioe) {
133                  Log.e(LOG_TAG, "Error writing data!", ioe);
134                  mResultCallback.onWriteFailed(mContext.getString(
135                          R.string.write_fail_reason_cannot_write));
136              } finally {
137                 IoUtils.closeQuietly(in);
138                 IoUtils.closeQuietly(out);
139             }
140             return null;
141         }
142 
143         @Override
onPostExecute(Void result)144         protected void onPostExecute(Void result) {
145             mResultCallback.onWriteFinished(new PageRange[] {PageRange.ALL_PAGES});
146         }
147 
148         @Override
onCancelled(Void result)149         protected void onCancelled(Void result) {
150             mResultCallback.onWriteFailed(mContext.getString(
151                     R.string.write_fail_reason_cancelled));
152         }
153     }
154 }
155 
156