| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.android.pdfrendererbasic; |
| |
| import android.app.Activity; |
| import android.app.Fragment; |
| import android.content.Context; |
| import android.graphics.Bitmap; |
| import android.graphics.pdf.PdfRenderer; |
| import android.os.Bundle; |
| import android.os.ParcelFileDescriptor; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.Button; |
| import android.widget.ImageView; |
| import android.widget.Toast; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| |
| /** |
| * This fragment has a big {@ImageView} that shows PDF pages, and 2 {@link android.widget.Button}s to move between |
| * pages. We use a {@link android.graphics.pdf.PdfRenderer} to render PDF pages as {@link android.graphics.Bitmap}s. |
| */ |
| public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener { |
| |
| /** |
| * Key string for saving the state of current page index. |
| */ |
| private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index"; |
| |
| /** |
| * The filename of the PDF. |
| */ |
| private static final String FILENAME = "sample.pdf"; |
| |
| /** |
| * File descriptor of the PDF. |
| */ |
| private ParcelFileDescriptor mFileDescriptor; |
| |
| /** |
| * {@link android.graphics.pdf.PdfRenderer} to render the PDF. |
| */ |
| private PdfRenderer mPdfRenderer; |
| |
| /** |
| * Page that is currently shown on the screen. |
| */ |
| private PdfRenderer.Page mCurrentPage; |
| |
| /** |
| * {@link android.widget.ImageView} that shows a PDF page as a {@link android.graphics.Bitmap} |
| */ |
| private ImageView mImageView; |
| |
| /** |
| * {@link android.widget.Button} to move to the previous page. |
| */ |
| private Button mButtonPrevious; |
| |
| /** |
| * {@link android.widget.Button} to move to the next page. |
| */ |
| private Button mButtonNext; |
| |
| public PdfRendererBasicFragment() { |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false); |
| } |
| |
| @Override |
| public void onViewCreated(View view, Bundle savedInstanceState) { |
| super.onViewCreated(view, savedInstanceState); |
| // Retain view references. |
| mImageView = (ImageView) view.findViewById(R.id.image); |
| mButtonPrevious = (Button) view.findViewById(R.id.previous); |
| mButtonNext = (Button) view.findViewById(R.id.next); |
| // Bind events. |
| mButtonPrevious.setOnClickListener(this); |
| mButtonNext.setOnClickListener(this); |
| // Show the first page by default. |
| int index = 0; |
| // If there is a savedInstanceState (screen orientations, etc.), we restore the page index. |
| if (null != savedInstanceState) { |
| index = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0); |
| } |
| showPage(index); |
| } |
| |
| @Override |
| public void onAttach(Activity activity) { |
| super.onAttach(activity); |
| try { |
| openRenderer(activity); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| Toast.makeText(activity, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show(); |
| activity.finish(); |
| } |
| } |
| |
| @Override |
| public void onDetach() { |
| try { |
| closeRenderer(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| super.onDetach(); |
| } |
| |
| @Override |
| public void onSaveInstanceState(Bundle outState) { |
| super.onSaveInstanceState(outState); |
| if (null != mCurrentPage) { |
| outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex()); |
| } |
| } |
| |
| /** |
| * Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources. |
| */ |
| private void openRenderer(Context context) throws IOException { |
| // In this sample, we read a PDF from the assets directory. |
| File file = new File(context.getCacheDir(), FILENAME); |
| if (!file.exists()) { |
| // Since PdfRenderer cannot handle the compressed asset file directly, we copy it into |
| // the cache directory. |
| InputStream asset = context.getAssets().open(FILENAME); |
| FileOutputStream output = new FileOutputStream(file); |
| final byte[] buffer = new byte[1024]; |
| int size; |
| while ((size = asset.read(buffer)) != -1) { |
| output.write(buffer, 0, size); |
| } |
| asset.close(); |
| output.close(); |
| } |
| mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); |
| // This is the PdfRenderer we use to render the PDF. |
| mPdfRenderer = new PdfRenderer(mFileDescriptor); |
| } |
| |
| /** |
| * Closes the {@link android.graphics.pdf.PdfRenderer} and related resources. |
| * |
| * @throws java.io.IOException When the PDF file cannot be closed. |
| */ |
| private void closeRenderer() throws IOException { |
| if (null != mCurrentPage) { |
| mCurrentPage.close(); |
| } |
| mPdfRenderer.close(); |
| mFileDescriptor.close(); |
| } |
| |
| /** |
| * Shows the specified page of PDF to the screen. |
| * |
| * @param index The page index. |
| */ |
| private void showPage(int index) { |
| if (mPdfRenderer.getPageCount() <= index) { |
| return; |
| } |
| // Make sure to close the current page before opening another one. |
| if (null != mCurrentPage) { |
| mCurrentPage.close(); |
| } |
| // Use `openPage` to open a specific page in PDF. |
| mCurrentPage = mPdfRenderer.openPage(index); |
| // Important: the destination bitmap must be ARGB (not RGB). |
| Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(), |
| Bitmap.Config.ARGB_8888); |
| // Here, we render the page onto the Bitmap. |
| // To render a portion of the page, use the second and third parameter. Pass nulls to get |
| // the default result. |
| // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter. |
| mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); |
| // We are ready to show the Bitmap to user. |
| mImageView.setImageBitmap(bitmap); |
| updateUi(); |
| } |
| |
| /** |
| * Updates the state of 2 control buttons in response to the current page index. |
| */ |
| private void updateUi() { |
| int index = mCurrentPage.getIndex(); |
| int pageCount = mPdfRenderer.getPageCount(); |
| mButtonPrevious.setEnabled(0 != index); |
| mButtonNext.setEnabled(index + 1 < pageCount); |
| getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount)); |
| } |
| |
| /** |
| * Gets the number of pages in the PDF. This method is marked as public for testing. |
| * |
| * @return The number of pages. |
| */ |
| public int getPageCount() { |
| return mPdfRenderer.getPageCount(); |
| } |
| |
| @Override |
| public void onClick(View view) { |
| switch (view.getId()) { |
| case R.id.previous: { |
| // Move to the previous page |
| showPage(mCurrentPage.getIndex() - 1); |
| break; |
| } |
| case R.id.next: { |
| // Move to the next page |
| showPage(mCurrentPage.getIndex() + 1); |
| break; |
| } |
| } |
| } |
| |
| } |