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