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.compat.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 */ onStart()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 * @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 */ onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)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 * @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 */ onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback)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 */ onFinish()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 WriteResultCallback()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 */ onWriteFinished(PageRange[] pages)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 */ onWriteFailed(CharSequence error)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 */ onWriteCancelled()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 LayoutResultCallback()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 */ onLayoutFinished(PrintDocumentInfo info, boolean changed)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 */ onLayoutFailed(CharSequence error)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 */ onLayoutCancelled()339 public void onLayoutCancelled() { 340 /* do nothing - stub */ 341 } 342 } 343 } 344