1 /* 2 * Copyright (C) 2014 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 com.example.android.pdfrendererbasic; 18 19 import android.app.Activity; 20 import android.app.Fragment; 21 import android.content.Context; 22 import android.graphics.Bitmap; 23 import android.graphics.pdf.PdfRenderer; 24 import android.os.Bundle; 25 import android.os.ParcelFileDescriptor; 26 import android.view.LayoutInflater; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.widget.Button; 30 import android.widget.ImageView; 31 import android.widget.Toast; 32 33 import java.io.IOException; 34 35 /** 36 * This fragment has a big {@ImageView} that shows PDF pages, and 2 {@link android.widget.Button}s to move between 37 * pages. We use a {@link android.graphics.pdf.PdfRenderer} to render PDF pages as {@link android.graphics.Bitmap}s. 38 */ 39 public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener { 40 41 /** 42 * Key string for saving the state of current page index. 43 */ 44 private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index"; 45 46 /** 47 * File descriptor of the PDF. 48 */ 49 private ParcelFileDescriptor mFileDescriptor; 50 51 /** 52 * {@link android.graphics.pdf.PdfRenderer} to render the PDF. 53 */ 54 private PdfRenderer mPdfRenderer; 55 56 /** 57 * Page that is currently shown on the screen. 58 */ 59 private PdfRenderer.Page mCurrentPage; 60 61 /** 62 * {@link android.widget.ImageView} that shows a PDF page as a {@link android.graphics.Bitmap} 63 */ 64 private ImageView mImageView; 65 66 /** 67 * {@link android.widget.Button} to move to the previous page. 68 */ 69 private Button mButtonPrevious; 70 71 /** 72 * {@link android.widget.Button} to move to the next page. 73 */ 74 private Button mButtonNext; 75 PdfRendererBasicFragment()76 public PdfRendererBasicFragment() { 77 } 78 79 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)80 public View onCreateView(LayoutInflater inflater, ViewGroup container, 81 Bundle savedInstanceState) { 82 return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false); 83 } 84 85 @Override onViewCreated(View view, Bundle savedInstanceState)86 public void onViewCreated(View view, Bundle savedInstanceState) { 87 super.onViewCreated(view, savedInstanceState); 88 // Retain view references. 89 mImageView = (ImageView) view.findViewById(R.id.image); 90 mButtonPrevious = (Button) view.findViewById(R.id.previous); 91 mButtonNext = (Button) view.findViewById(R.id.next); 92 // Bind events. 93 mButtonPrevious.setOnClickListener(this); 94 mButtonNext.setOnClickListener(this); 95 // Show the first page by default. 96 int index = 0; 97 // If there is a savedInstanceState (screen orientations, etc.), we restore the page index. 98 if (null != savedInstanceState) { 99 index = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0); 100 } 101 showPage(index); 102 } 103 104 @Override onAttach(Activity activity)105 public void onAttach(Activity activity) { 106 super.onAttach(activity); 107 try { 108 openRenderer(activity); 109 } catch (IOException e) { 110 e.printStackTrace(); 111 Toast.makeText(activity, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show(); 112 activity.finish(); 113 } 114 } 115 116 @Override onDetach()117 public void onDetach() { 118 try { 119 closeRenderer(); 120 } catch (IOException e) { 121 e.printStackTrace(); 122 } 123 super.onDetach(); 124 } 125 126 @Override onSaveInstanceState(Bundle outState)127 public void onSaveInstanceState(Bundle outState) { 128 super.onSaveInstanceState(outState); 129 if (null != mCurrentPage) { 130 outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex()); 131 } 132 } 133 134 /** 135 * Sets up a {@link android.graphics.pdf.PdfRenderer} and related resources. 136 */ openRenderer(Context context)137 private void openRenderer(Context context) throws IOException { 138 // In this sample, we read a PDF from the assets directory. 139 mFileDescriptor = context.getAssets().openFd("sample.pdf").getParcelFileDescriptor(); 140 // This is the PdfRenderer we use to render the PDF. 141 mPdfRenderer = new PdfRenderer(mFileDescriptor); 142 } 143 144 /** 145 * Closes the {@link android.graphics.pdf.PdfRenderer} and related resources. 146 * 147 * @throws java.io.IOException When the PDF file cannot be closed. 148 */ closeRenderer()149 private void closeRenderer() throws IOException { 150 if (null != mCurrentPage) { 151 mCurrentPage.close(); 152 } 153 mPdfRenderer.close(); 154 mFileDescriptor.close(); 155 } 156 157 /** 158 * Shows the specified page of PDF to the screen. 159 * 160 * @param index The page index. 161 */ showPage(int index)162 private void showPage(int index) { 163 if (mPdfRenderer.getPageCount() <= index) { 164 return; 165 } 166 // Make sure to close the current page before opening another one. 167 if (null != mCurrentPage) { 168 mCurrentPage.close(); 169 } 170 // Use `openPage` to open a specific page in PDF. 171 mCurrentPage = mPdfRenderer.openPage(index); 172 // Important: the destination bitmap must be ARGB (not RGB). 173 Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(), 174 Bitmap.Config.ARGB_8888); 175 // Here, we render the page onto the Bitmap. 176 // To render a portion of the page, use the second and third parameter. Pass nulls to get 177 // the default result. 178 // Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter. 179 mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); 180 // We are ready to show the Bitmap to user. 181 mImageView.setImageBitmap(bitmap); 182 updateUi(); 183 } 184 185 /** 186 * Updates the state of 2 control buttons in response to the current page index. 187 */ updateUi()188 private void updateUi() { 189 int index = mCurrentPage.getIndex(); 190 int pageCount = mPdfRenderer.getPageCount(); 191 mButtonPrevious.setEnabled(0 != index); 192 mButtonNext.setEnabled(index + 1 < pageCount); 193 getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount)); 194 } 195 196 /** 197 * Gets the number of pages in the PDF. This method is marked as public for testing. 198 * 199 * @return The number of pages. 200 */ getPageCount()201 public int getPageCount() { 202 return mPdfRenderer.getPageCount(); 203 } 204 205 @Override onClick(View view)206 public void onClick(View view) { 207 switch (view.getId()) { 208 case R.id.previous: { 209 // Move to the previous page 210 showPage(mCurrentPage.getIndex() - 1); 211 break; 212 } 213 case R.id.next: { 214 // Move to the next page 215 showPage(mCurrentPage.getIndex() + 1); 216 break; 217 } 218 } 219 } 220 221 } 222