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