Home | History | Annotate | Download | only in permission2
      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 foo.bar.permission2;
     18 
     19 import java.io.FileOutputStream;
     20 import java.io.IOException;
     21 import java.util.ArrayList;
     22 import java.util.Arrays;
     23 import java.util.List;
     24 
     25 import android.app.Activity;
     26 import android.content.Context;
     27 import android.graphics.Color;
     28 import android.graphics.Paint;
     29 import android.graphics.pdf.PdfDocument.Page;
     30 import android.os.AsyncTask;
     31 import android.os.Bundle;
     32 import android.os.CancellationSignal;
     33 import android.os.CancellationSignal.OnCancelListener;
     34 import android.os.ParcelFileDescriptor;
     35 import android.print.PageRange;
     36 import android.print.PrintAttributes;
     37 import android.print.PrintDocumentAdapter;
     38 import android.print.PrintDocumentInfo;
     39 import android.print.PrintManager;
     40 import android.print.pdf.PrintedPdfDocument;
     41 import android.util.Log;
     42 import android.util.SparseIntArray;
     43 import android.view.Menu;
     44 import android.view.MenuItem;
     45 import android.view.View;
     46 
     47 /**
     48  * Simple sample of how to use the print APIs.
     49  */
     50 public class PrintActivity extends Activity {
     51 
     52     public static final String LOG_TAG = "PrintActivity";
     53 
     54     private static final int PAGE_COUNT = 50;
     55 
     56     @Override
     57     protected void onCreate(Bundle savedInstanceState) {
     58         super.onCreate(savedInstanceState);
     59         setContentView(R.layout.activity_main);
     60     }
     61 
     62     @Override
     63     public boolean onCreateOptionsMenu(Menu menu) {
     64         super.onCreateOptionsMenu(menu);
     65         getMenuInflater().inflate(R.menu.activity_main, menu);
     66         return true;
     67     }
     68 
     69     @Override
     70     public boolean onOptionsItemSelected(MenuItem item) {
     71         if (item.getItemId() == R.id.menu_print) {
     72             printView();
     73             return true;
     74         }
     75         return super.onOptionsItemSelected(item);
     76     }
     77 
     78     private void printView() {
     79         PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
     80         final View view = findViewById(R.id.content);
     81 
     82         printManager.print("Print_View",
     83             new PrintDocumentAdapter() {
     84                 private static final int RESULT_LAYOUT_FAILED = 1;
     85                 private static final int RESULT_LAYOUT_FINISHED = 2;
     86 
     87                 private PrintAttributes mPrintAttributes;
     88 
     89                 @Override
     90                 public void onStart() {
     91                     Log.i(LOG_TAG, "onStart");
     92                 }
     93 
     94                 @Override
     95                 public void onFinish() {
     96                     Log.i(LOG_TAG, "onFinish");
     97                 }
     98 
     99                 @Override
    100                 public void onLayout(final PrintAttributes oldAttributes,
    101                         final PrintAttributes newAttributes,
    102                         final CancellationSignal cancellationSignal,
    103                         final LayoutResultCallback callback,
    104                         final Bundle metadata) {
    105 
    106                     Log.i(LOG_TAG, "onLayout() oldAttrs:" + oldAttributes + "\n"
    107                             + "newAttrs:" + newAttributes + "\n"
    108                             + "preview:" + metadata.getBoolean(
    109                             PrintDocumentAdapter.EXTRA_PRINT_PREVIEW) );
    110 
    111                     new AsyncTask<Void, Void, Integer>() {
    112                         @Override
    113                         protected void onPreExecute() {
    114                             // First register for cancellation requests.
    115                             cancellationSignal.setOnCancelListener(new OnCancelListener() {
    116                                 @Override
    117                                 public void onCancel() {
    118                                     cancel(true);
    119                                 }
    120                             });
    121                             mPrintAttributes = newAttributes;
    122                         }
    123 
    124                         @Override
    125                         protected Integer doInBackground(Void... params) {
    126                             try {
    127                                 // Pretend we do some layout work.
    128                                 for (int i = 0; i < PAGE_COUNT; i++) {
    129                                     // Be nice and respond to cancellation.
    130                                     if (isCancelled()) {
    131                                         return null;
    132                                     }
    133                                     pretendDoingLayoutWork();
    134                                 }
    135                                 return RESULT_LAYOUT_FINISHED;
    136                             } catch (Exception e) {
    137                                 return RESULT_LAYOUT_FAILED;
    138                             }
    139                         }
    140 
    141                         @Override
    142                         protected void onPostExecute(Integer result) {
    143                             // The task was not cancelled, so handle the layout result.
    144                             switch (result) {
    145                                 case RESULT_LAYOUT_FINISHED: {
    146                                     PrintDocumentInfo info = new PrintDocumentInfo
    147                                             .Builder("print_view.pdf")
    148                                             .setContentType(PrintDocumentInfo
    149                                                     .CONTENT_TYPE_DOCUMENT)
    150                                             .setPageCount(PAGE_COUNT)
    151                                             .build();
    152                                     callback.onLayoutFinished(info, false);
    153                                 } break;
    154 
    155                                 case RESULT_LAYOUT_FAILED: {
    156                                     callback.onLayoutFailed(null);
    157                                 } break;
    158                             }
    159                         }
    160 
    161                         @Override
    162                         protected void onCancelled(Integer result) {
    163                             // Task was cancelled, report that.
    164                             callback.onLayoutCancelled();
    165                         }
    166 
    167                         private void pretendDoingLayoutWork() throws Exception {
    168 
    169                         }
    170                     }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
    171                 }
    172 
    173                 @Override
    174                 public void onWrite(final PageRange[] pages,
    175                         final ParcelFileDescriptor destination,
    176                         final CancellationSignal cancellationSignal,
    177                         final WriteResultCallback callback) {
    178 
    179                     Log.i(LOG_TAG, "onWrite() pages:" + Arrays.toString(pages));
    180 
    181                     new AsyncTask<Void, Void, Integer>() {
    182                         private static final int RESULT_WRITE_FAILED = 1;
    183                         private static final int RESULT_WRITE_FINISHED = 2;
    184 
    185                         private final SparseIntArray mWrittenPages = new SparseIntArray();
    186                         private final PrintedPdfDocument mPdfDocument = new PrintedPdfDocument(
    187                                 PrintActivity.this, mPrintAttributes);
    188 
    189                         @Override
    190                         protected void onPreExecute() {
    191                             // First register for cancellation requests.
    192                             cancellationSignal.setOnCancelListener(new OnCancelListener() {
    193                                 @Override
    194                                 public void onCancel() {
    195                                     cancel(true);
    196                                 }
    197                             });
    198 
    199                             for (int i = 0; i < PAGE_COUNT; i++) {
    200                                 // Be nice and respond to cancellation.
    201                                 if (isCancelled()) {
    202                                     return;
    203                                 }
    204 
    205                                 // Write the page only if it was requested.
    206                                 if (containsPage(pages, i)) {
    207                                     mWrittenPages.append(mWrittenPages.size(), i);
    208                                     Page page = mPdfDocument.startPage(i);
    209                                     // The page of the PDF backed canvas size is in pixels (1/72") and
    210                                     // smaller that the view. We scale down the drawn content and to
    211                                     // fit. This does not lead to losing data as PDF is a vector format.
    212                                     final float scale = (float) Math.min(mPdfDocument.getPageWidth(),
    213                                             mPdfDocument.getPageHeight()) / Math.max(view.getWidth(), view.getHeight());
    214                                     page.getCanvas().scale(scale, scale);
    215                                     view.draw(page.getCanvas());
    216 
    217 
    218                                     Paint paint = new Paint();
    219                                     paint.setTextSize(100);
    220                                     paint.setColor(Color.RED);
    221                                     final int x = page.getCanvas().getWidth() / 2;
    222                                     final int y = page.getCanvas().getHeight() / 2;
    223                                     page.getCanvas().drawText(String.valueOf(i), x, y, paint);
    224 
    225                                     mPdfDocument.finishPage(page);
    226                                 }
    227                             }
    228                         }
    229 
    230                         @Override
    231                         protected Integer doInBackground(Void... params) {
    232                             // Write the data and return success or failure.
    233                             try {
    234                                 mPdfDocument.writeTo(new FileOutputStream(
    235                                         destination.getFileDescriptor()));
    236                                 return RESULT_WRITE_FINISHED;
    237                             } catch (IOException ioe) {
    238                                 return RESULT_WRITE_FAILED;
    239                             }
    240                         }
    241 
    242                         @Override
    243                         protected void onPostExecute(Integer result) {
    244                             // The task was not cancelled, so handle the write result.
    245                             switch (result) {
    246                                 case RESULT_WRITE_FINISHED: {
    247                                     PageRange[] pageRanges = computePageRanges(mWrittenPages);
    248                                     callback.onWriteFinished(pageRanges);
    249                                 } break;
    250 
    251                                 case RESULT_WRITE_FAILED: {
    252                                     callback.onWriteFailed(null);
    253                                 } break;
    254                             }
    255 
    256                             mPdfDocument.close();
    257                         }
    258 
    259                         @Override
    260                         protected void onCancelled(Integer result) {
    261                             // Task was cancelled, report that.
    262                             callback.onWriteCancelled();
    263                             mPdfDocument.close();
    264                         }
    265                     }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
    266                 }
    267 
    268                 private PageRange[] computePageRanges(SparseIntArray writtenPages) {
    269                     List<PageRange> pageRanges = new ArrayList<PageRange>();
    270 
    271                     int start = -1;
    272                     int end = -1;
    273                     final int writtenPageCount = writtenPages.size();
    274                     for (int i = 0; i < writtenPageCount; i++) {
    275                         if (start < 0) {
    276                             start = writtenPages.valueAt(i);
    277                         }
    278                         int oldEnd = end = start;
    279                         while (i < writtenPageCount && (end - oldEnd) <= 1) {
    280                             oldEnd = end;
    281                             end = writtenPages.valueAt(i);
    282                             i++;
    283                         }
    284                         PageRange pageRange = new PageRange(start, end);
    285                         pageRanges.add(pageRange);
    286                         start = end = -1;
    287                     }
    288 
    289                     PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
    290                     pageRanges.toArray(pageRangesArray);
    291                     return pageRangesArray;
    292                 }
    293 
    294                 private boolean containsPage(PageRange[] pageRanges, int page) {
    295                     final int pageRangeCount = pageRanges.length;
    296                     for (int i = 0; i < pageRangeCount; i++) {
    297                         if (pageRanges[i].getStart() <= page
    298                                 && pageRanges[i].getEnd() >= page) {
    299                             return true;
    300                         }
    301                     }
    302                     return false;
    303                 }
    304         }, null);
    305     }
    306 }
    307