Home | History | Annotate | Download | only in print
      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.annotation.UnsupportedAppUsage;
     20 import android.os.Bundle;
     21 import android.os.CancellationSignal;
     22 import android.os.ParcelFileDescriptor;
     23 
     24 /**
     25  * Base class that provides the content of a document to be printed.
     26  *
     27  * <h3>Lifecycle</h3>
     28  * <p>
     29  * <ul>
     30  * <li>
     31  * Initially, you will receive a call to {@link #onStart()}. This callback
     32  * can be used to allocate resources.
     33  * </li>
     34  * <li>
     35  * Next, you will get one or more calls to {@link #onLayout(PrintAttributes,
     36  * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} to
     37  * inform you that the print attributes (page size, density, etc) changed
     38  * giving you an opportunity to layout the content to match the new constraints.
     39  * </li>
     40  * <li>
     41  * After every call to {@link #onLayout(PrintAttributes, PrintAttributes,
     42  * CancellationSignal, LayoutResultCallback, Bundle)}, you <strong>may</strong> get
     43  * a call to {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
     44  * WriteResultCallback)} asking you to write a PDF file with the content for
     45  * 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  * The {@link #onStart()} callback is always the first call you will receive and
     54  * is useful for doing one time setup or resource allocation before printing. You
     55  * will not receive a subsequent call here.
     56  * </p>
     57  * <p>
     58  * The {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
     59  * LayoutResultCallback, Bundle)} callback requires that you layout the content
     60  * based on the current {@link PrintAttributes}. The execution of this method is
     61  * not considered completed until you invoke one of the methods on the passed in
     62  * callback instance. Hence, you will not receive a subsequent call to any other
     63  * method of this class until the execution of this method is complete by invoking
     64  * one of the callback methods.
     65  * </p>
     66  * <p>
     67  * The {@link #onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
     68  * WriteResultCallback)} requires that you render and write the content of some
     69  * pages to the provided destination. The execution of this method is not
     70  * considered complete until you invoke one of the methods on the passed in
     71  * callback instance. Hence, you will not receive a subsequent call to any other
     72  * method of this class until the execution of this method is complete by invoking
     73  * one of the callback methods. You will never receive a sequence of one or more
     74  * calls to this method without a previous call to {@link #onLayout(PrintAttributes,
     75  * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)}.
     76  * </p>
     77  * <p>
     78  * The {@link #onFinish()} callback is always the last call you will receive and
     79  * is useful for doing one time cleanup or resource deallocation after printing.
     80  * You will not receive a subsequent call here.
     81  * </p>
     82  * </p>
     83  * <h3>Implementation</h3>
     84  * <p>
     85  * The APIs defined in this class are designed to enable doing part or all
     86  * of the work on an arbitrary thread. For example, if the printed content
     87  * does not depend on the UI state, i.e. on what is shown on the screen, then
     88  * you can offload the entire work on a dedicated thread, thus making your
     89  * application interactive while the print work is being performed. Note that
     90  * while your activity is covered by the system print UI and a user cannot
     91  * interact with it, doing the printing work on the main application thread
     92  * may affect the performance of your other application components as they
     93  * are also executed on that thread.
     94  * </p>
     95  * <p>
     96  * You can also do work on different threads, for example if you print UI
     97  * content, you can handle {@link #onStart()} and {@link #onLayout(PrintAttributes,
     98  * PrintAttributes, CancellationSignal, LayoutResultCallback, Bundle)} on
     99  * the UI thread (assuming onStart initializes resources needed for layout).
    100  * This will ensure that the UI does not change while you are laying out the
    101  * printed content. Then you can handle {@link #onWrite(PageRange[], ParcelFileDescriptor,
    102  * CancellationSignal, WriteResultCallback)} and {@link #onFinish()} on another
    103  * thread. This will ensure that the main thread is busy for a minimal amount of
    104  * time. Also this assumes that you will generate the printed content in
    105  * {@link #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
    106  * LayoutResultCallback, Bundle)} which is not mandatory. If you use multiple
    107  * threads, you are responsible for proper synchronization.
    108  * </p>
    109  */
    110 public abstract class PrintDocumentAdapter {
    111 
    112     /**
    113      * Extra: mapped to a boolean value that is <code>true</code> if
    114      * the current layout is for a print preview, <code>false</code> otherwise.
    115      * This extra is provided in the {@link Bundle} argument of the {@link
    116      * #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
    117      * LayoutResultCallback, Bundle)} callback.
    118      *
    119      * @see #onLayout(PrintAttributes, PrintAttributes, CancellationSignal,
    120      * LayoutResultCallback, Bundle)
    121      */
    122     public static final String EXTRA_PRINT_PREVIEW = "EXTRA_PRINT_PREVIEW";
    123 
    124     /**
    125      * Called when printing starts. You can use this callback to allocate
    126      * resources. This method is invoked on the main thread.
    127      */
    128     public void onStart() {
    129         /* do nothing - stub */
    130     }
    131 
    132     /**
    133      * Called when the print attributes (page size, density, etc) changed
    134      * giving you a chance to layout the content such that it matches the
    135      * new constraints. This method is invoked on the main thread.
    136      * <p>
    137      * After you are done laying out, you <strong>must</strong> invoke: {@link
    138      * LayoutResultCallback#onLayoutFinished(PrintDocumentInfo, boolean)} with
    139      * the last argument <code>true</code> or <code>false</code> depending on
    140      * whether the layout changed the content or not, respectively; or {@link
    141      * LayoutResultCallback#onLayoutFailed(CharSequence)}, if an error occurred;
    142      * or {@link LayoutResultCallback#onLayoutCancelled()} if layout was
    143      * cancelled in a response to a cancellation request via the passed in
    144      * {@link CancellationSignal}. Note that you <strong>must</strong> call one of
    145      * the methods of the given callback for this method to be considered complete
    146      * which is you will not receive any calls to this adapter until the current
    147      * layout operation is complete by invoking a method on the callback instance.
    148      * The callback methods can be invoked from an arbitrary thread.
    149      * </p>
    150      * <p>
    151      * One of the arguments passed to this method is a {@link CancellationSignal}
    152      * which is used to propagate requests from the system to your application for
    153      * canceling the current layout operation. For example, a cancellation may be
    154      * requested if the user changes a print option that may affect layout while
    155      * you are performing a layout operation. In such a case the system will make
    156      * an attempt to cancel the current layout as another one will have to be performed.
    157      * Typically, you should register a cancellation callback in the cancellation
    158      * signal. The cancellation callback <strong>will not</strong> be made on the
    159      * main thread and can be registered as follows:
    160      * </p>
    161      * <pre>
    162      * cancellationSignal.setOnCancelListener(new OnCancelListener() {
    163      *     &#064;Override
    164      *     public void onCancel() {
    165      *         // Cancel layout
    166      *     }
    167      * });
    168      * </pre>
    169      * <p>
    170      * <strong>Note:</strong> If the content is large and a layout will be
    171      * performed, it is a good practice to schedule the work on a dedicated
    172      * thread and register an observer in the provided {@link
    173      * CancellationSignal} upon invocation of which you should stop the
    174      * layout.
    175      * </p>
    176      *
    177      * @param oldAttributes The old print attributes.
    178      * @param newAttributes The new print attributes.
    179      * @param cancellationSignal Signal for observing cancel layout requests.
    180      * @param callback Callback to inform the system for the layout result.
    181      * @param extras Additional information about how to layout the content.
    182      *
    183      * @see LayoutResultCallback
    184      * @see CancellationSignal
    185      * @see #EXTRA_PRINT_PREVIEW
    186      */
    187     public abstract void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
    188             CancellationSignal cancellationSignal, LayoutResultCallback callback,
    189             Bundle extras);
    190 
    191     /**
    192      * Called when specific pages of the content should be written in the
    193      * form of a PDF file to the given file descriptor. This method is invoked
    194      * on the main thread.
    195      *<p>
    196      * After you are done writing, you should close the file descriptor and
    197      * invoke {@link WriteResultCallback#onWriteFinished(PageRange[])}, if writing
    198      * completed successfully; or {@link WriteResultCallback#onWriteFailed(
    199      * CharSequence)}, if an error occurred; or {@link WriteResultCallback#onWriteCancelled()},
    200      * if writing was cancelled in a response to a cancellation request via the passed
    201      * in {@link CancellationSignal}. Note that you <strong>must</strong> call one of
    202      * the methods of the given callback for this method to be considered complete which
    203      * is you will not receive any calls to this adapter until the current write
    204      * operation is complete by invoking a method on the callback instance. The callback
    205      * methods can be invoked from an arbitrary thread.
    206      * </p>
    207      * <p>
    208      * One of the arguments passed to this method is a {@link CancellationSignal}
    209      * which is used to propagate requests from the system to your application for
    210      * canceling the current write operation. For example, a cancellation may be
    211      * requested if the user changes a print option that may affect layout while
    212      * you are performing a write operation. In such a case the system will make
    213      * an attempt to cancel the current write as a layout will have to be performed
    214      * which then may be followed by a write. Typically, you should register a
    215      * cancellation callback in the cancellation signal. The cancellation callback
    216      * <strong>will not</strong> be made on the main thread and can be registered
    217      * as follows:
    218      * </p>
    219      * <pre>
    220      * cancellationSignal.setOnCancelListener(new OnCancelListener() {
    221      *     &#064;Override
    222      *     public void onCancel() {
    223      *         // Cancel write
    224      *     }
    225      * });
    226      * </pre>
    227      * <p>
    228      * <strong>Note:</strong> If the printed content is large, it is a good
    229      * practice to schedule writing it on a dedicated thread and register an
    230      * observer in the provided {@link CancellationSignal} upon invocation of
    231      * which you should stop writing.
    232      * </p>
    233      *
    234      * @param pages The pages whose content to print - non-overlapping in ascending order.
    235      * @param destination The destination file descriptor to which to write.
    236      * @param cancellationSignal Signal for observing cancel writing requests.
    237      * @param callback Callback to inform the system for the write result.
    238      *
    239      * @see WriteResultCallback
    240      * @see CancellationSignal
    241      */
    242     public abstract void onWrite(PageRange[] pages, ParcelFileDescriptor destination,
    243             CancellationSignal cancellationSignal, WriteResultCallback callback);
    244 
    245     /**
    246      * Called when printing finishes. You can use this callback to release
    247      * resources acquired in {@link #onStart()}. This method is invoked on
    248      * the main thread.
    249      */
    250     public void onFinish() {
    251         /* do nothing - stub */
    252     }
    253 
    254     /**
    255      * Base class for implementing a callback for the result of {@link
    256      * PrintDocumentAdapter#onWrite(PageRange[], ParcelFileDescriptor, CancellationSignal,
    257      * WriteResultCallback)}.
    258      */
    259     public static abstract class WriteResultCallback {
    260 
    261         /**
    262          * @hide
    263          */
    264         @UnsupportedAppUsage
    265         public WriteResultCallback() {
    266             /* do nothing - hide constructor */
    267         }
    268 
    269         /**
    270          * Notifies that all the data was written.
    271          *
    272          * @param pages The pages that were written. Cannot be <code>null</code>
    273          *        or empty. <br />
    274          *        Returning {@link PageRange#ALL_PAGES} indicates that all pages that were
    275          *        requested as the {@code pages} parameter in {@link #onWrite} were written.
    276          */
    277         public void onWriteFinished(PageRange[] pages) {
    278             /* do nothing - stub */
    279         }
    280 
    281         /**
    282          * Notifies that an error occurred while writing the data.
    283          *
    284          * @param error The <strong>localized</strong> error message.
    285          * shown to the user. May be <code>null</code> if error is unknown.
    286          */
    287         public void onWriteFailed(CharSequence error) {
    288             /* do nothing - stub */
    289         }
    290 
    291         /**
    292          * Notifies that write was cancelled as a result of a cancellation request.
    293          */
    294         public void onWriteCancelled() {
    295             /* do nothing - stub */
    296         }
    297     }
    298 
    299     /**
    300      * Base class for implementing a callback for the result of {@link
    301      * PrintDocumentAdapter#onLayout(PrintAttributes, PrintAttributes,
    302      * CancellationSignal, LayoutResultCallback, Bundle)}.
    303      */
    304     public static abstract class LayoutResultCallback {
    305 
    306         /**
    307          * @hide
    308          */
    309         @UnsupportedAppUsage
    310         public LayoutResultCallback() {
    311             /* do nothing - hide constructor */
    312         }
    313 
    314         /**
    315          * Notifies that the layout finished and whether the content changed.
    316          *
    317          * @param info An info object describing the document. Cannot be <code>null</code>.
    318          * @param changed Whether the layout changed.
    319          *
    320          * @see PrintDocumentInfo
    321          */
    322         public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
    323             /* do nothing - stub */
    324         }
    325 
    326         /**
    327          * Notifies that an error occurred while laying out the document.
    328          *
    329          * @param error The <strong>localized</strong> error message.
    330          * shown to the user. May be <code>null</code> if error is unknown.
    331          */
    332         public void onLayoutFailed(CharSequence error) {
    333             /* do nothing - stub */
    334         }
    335 
    336         /**
    337          * Notifies that layout was cancelled as a result of a cancellation request.
    338          */
    339         public void onLayoutCancelled() {
    340             /* do nothing - stub */
    341         }
    342     }
    343 }
    344