PrintDocumentAdapter.java revision 19fba5d34a444ce145ab0d3a12c578d9d5d3f38c
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
17package android.print;
18
19import android.os.Bundle;
20import android.os.CancellationSignal;
21import android.os.ParcelFileDescriptor;
22
23import java.util.List;
24
25/**
26 * Base class that provides the content of a document to be printed.
27 *
28 * <h3>Lifecycle</h3>
29 * <p>
30 * <ul>
31 * <li>
32 * Initially, you will receive a call to {@link #onStart()}. This callback
33 * can be used to allocate resources.
34 * </li>
35 * <li>
36 * Next, you will get one or more calls to {@link #onLayout(PrintAttributes,
37 * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} to
38 * inform you that the print attributes (page size, density, etc) changed
39 * giving you an opportunity to layout the content to match the new constraints.
40 * </li>
41 * <li>
42 * After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
43 * CancellationSignal, LayoutResultCallback, Bundle)}, you may get a call to
44 * {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal, WriteResultCallback)}
45 * asking you to write a PDF file with the content for specific pages.
46 * </li>
47 * <li>
48 * Finally, you will receive a call to {@link #onFinish()}. You can use this
49 * callback to release resources allocated in {@link #onStart()}.
50 * </li>
51 * </ul>
52 * </p>
53 * <h3>Implementation</h3>
54 * <p>
55 * The APIs defined in this class are designed to enable doing part or all
56 * of the work on an arbitrary thread. For example, if the printed content
57 * does not depend on the UI state, i.e. on what is shown on the screen, then
58 * you can offload the entire work on a dedicated thread, thus making your
59 * application interactive while the print work is being performed.
60 * </p>
61 * <p>
62 * You can also do work on different threads, for example if you print UI
63 * content, you can handle {@link #onStart()} and {@link #onLayout(PrintAttributes,
64 * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on
65 * the UI thread (assuming onStart initializes resources needed for layout).
66 * This will ensure that the UI does not change while you are laying out the
67 * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
68 * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
69 * thread. This will ensure that the UI is frozen for the minimal amount of
70 * time. Also this assumes that you will generate the printed content in
71 * {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
72 * LayoutResultCallback, Bundle)} which is not mandatory. If you use multiple
73 * threads, you are responsible for proper synchronization.
74 * </p>
75 */
76public abstract class PrintDocumentAdapter {
77
78    /**
79     * Meta-data key: mapped to a boolean value that is <code>true</code> if
80     * the current layout is for a print preview, <code>false</code> otherwise.
81     */
82    public static final String METADATA_KEY_PRINT_PREVIEW = "KEY_METADATA_PRINT_PREVIEW";
83
84    /**
85     * Called when printing starts. You can use this callback to allocate
86     * resources. This method is invoked on the main thread.
87     */
88    public void onStart() {
89        /* do nothing - stub */
90    }
91
92    /**
93     * Called when the print attributes (page size, density, etc) changed
94     * giving you a chance to layout the content such that it matches the
95     * new constraints. This method is invoked on the main thread.
96     * <p>
97     * After you are done laying out, you <strong>must</strong> invoke: {@link
98     * LayoutResultCallback#onLayoutFinished(PrintDocumentInfo, boolean)} with
99     * the last argument <code>true</code> or <code>false</code> depending on
100     * whether the layout changed the content or not, respectively; and {@link
101     * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred.
102     * Note that you must call one of the methods of the given callback.
103     * </p>
104     * <p>
105     * When doing a layout you may satisfy some of the constraints in the print
106     * attributes such as applying the appropriate fitting, emitting content in the
107     * requested orientation, using the specified margins, generating content with
108     * the desired color mode, producing output with the given media size. Ideally,
109     * you will satisfy all of these constraints. It is important that if you
110     * satisfy a given constraint, you update the {@link PrintDocumentInfo} that
111     * is returned in the given {@link LayoutResultCallback}. This way the printer
112     * will have more accurate information about the content, thus producing a
113     * better output. For example, assume that your application is printing
114     * an image and the print attributes request landscape and fitting mode scale
115     * to fill. The result of this operation should be the entire media is filled
116     * and the content is rotated ninety degrees. In this case it is beneficial
117     * you do the rotation and select a higher resolution image to utilize
118     * the wider media (the height is now the width), rather to use a lower
119     * resolution image that is later stretched by the printer. If you applied
120     * the rotation you have to update the returned print document info to
121     * reflect that the content is already in landscape by calling
122     * {@link PrintDocumentInfo.Builder#setOrientation(int)} with {@link
123     * PrintAttributes#ORIENTATION_LANDSCAPE}. In this case the printer does not
124     * have to rotate the content.
125     * </p>
126     * <p>
127     * <strong>Note:</strong> If the content is large and a layout will be
128     * performed, it is a good practice to schedule the work on a dedicated
129     * thread and register an observer in the provided {@link
130     * CancellationSignal} upon invocation of which you should stop the
131     * layout. The cancellation callback will not be made on the main
132     * thread.
133     * </p>
134     *
135     * @param oldAttributes The old print attributes.
136     * @param newAttributes The new print attributes.
137     * @param cancellationSignal Signal for observing cancel layout requests.
138     * @param callback Callback to inform the system for the layout result.
139     * @param metadata Additional information about how layout the content.
140     *
141     * @see LayoutResultCallback
142     * @see CancellationSignal
143     * @see #METADATA_KEY_PRINT_PREVIEW
144     */
145    public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
146            CancellationSignal cancellationSignal, LayoutResultCallback callback,
147            Bundle metadata);
148
149    /**
150     * Called when specific pages of the content should be written in the
151     * form of a PDF file to the given file descriptor. This method is invoked
152     * on the main thread.
153     *<p>
154     * After you are done writing, you should close the file descriptor and
155     * invoke {@link WriteResultCallback #onWriteFinished(PageRange[]), if writing
156     * completed successfully; or {@link WriteResultCallback#onWriteFailed(
157     * CharSequence)}, if an error occurred. Note that you must call one of
158     * the methods of the given callback.
159     * </p>
160     * <p>
161     * <strong>Note:</strong> If the printed content is large, it is a good
162     * practice to schedule writing it on a dedicated thread and register an
163     * observer in the provided {@link CancellationSignal} upon invocation of
164     * which you should stop writing. The cancellation callback will not be
165     * made on the main thread.
166     * </p>
167     *
168     * @param pages The pages whose content to print - non-overlapping in ascending order.
169     * @param destination The destination file descriptor to which to write.
170     * @param cancellationSignal Signal for observing cancel writing requests.
171     * @param callback Callback to inform the system for the write result.
172     *
173     * @see WriteResultCallback
174     * @see CancellationSignal
175     */
176    public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
177            CancellationSignal cancellationSignal, WriteResultCallback callback);
178
179    /**
180     * Called when printing finishes. You can use this callback to release
181     * resources acquired in {@link #onStart()}. This method is invoked on
182     * the main thread.
183     */
184    public void onFinish() {
185        /* do nothing - stub */
186    }
187
188    /**
189     * Base class for implementing a callback for the result of {@link
190     * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
191     * WriteResultCallback)}.
192     */
193    public static abstract class WriteResultCallback {
194
195        /**
196         * @hide
197         */
198        public WriteResultCallback() {
199            /* do nothing - hide constructor */
200        }
201
202        /**
203         * Notifies that all the data was written.
204         *
205         * @param pages The pages that were written. Cannot be null or empty.
206         */
207        public void onWriteFinished(PageRange[] pages) {
208            /* do nothing - stub */
209        }
210
211        /**
212         * Notifies that an error occurred while writing the data.
213         *
214         * @param error Error message. May be null if error is unknown.
215         */
216        public void onWriteFailed(CharSequence error) {
217            /* do nothing - stub */
218        }
219
220        /**
221         * Notifies that write was cancelled as a result of a cancellation request.
222         */
223        public void onWriteCancelled() {
224            /* do nothing - stub */
225        }
226    }
227
228    /**
229     * Base class for implementing a callback for the result of {@link
230     * PrintDocumentAdapter#onLayout(PrintAttributes, PrintAttributes,
231     * CancellationSignal, LayoutResultCallback, Bundle)}.
232     */
233    public static abstract class LayoutResultCallback {
234
235        /**
236         * @hide
237         */
238        public LayoutResultCallback() {
239            /* do nothing - hide constructor */
240        }
241
242        /**
243         * Notifies that the layout finished and whether the content changed.
244         *
245         * @param info An info object describing the document. Cannot be null.
246         * @param changed Whether the layout changed.
247         *
248         * @see PrintDocumentInfo
249         */
250        public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
251            /* do nothing - stub */
252        }
253
254        /**
255         * Notifies that an error occurred while laying out the document.
256         *
257         * @param error Error message. May be null if error is unknown.
258         */
259        public void onLayoutFailed(CharSequence error) {
260            /* do nothing - stub */
261        }
262
263        /**
264         * Notifies that layout was cancelled as a result of a cancellation request.
265         */
266        public void onLayoutCancelled() {
267            /* do nothing - stub */
268        }
269    }
270}
271