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