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