【Androidでデータやファイルと戯れる】android.graphics.pdfパッケージを使ってPDFを操作しよう!

このエントリーを Google ブックマーク に追加
Pocket
[`yahoo` not found]

AndroidでPDFを作成しよう!

API19以降からandroid.graphics.pdfが追加され、Android端末でPDFを作成できるようになりました。
そんなわけで今更ながらPDFの作り方を説明します。
また、今回紹介するandroid.graphics.pdfはCanvasを使ってPDFを作成するのでAndroidのCanvasに向き合うを参考にしてください。

android.graphics.pdfの紹介

まずはパッケージに含まれているクラス群の紹介からいきます。

クラス名 概要
PdfDocument PDFドキュメントの新規作成、ページの管理、ファイルへの書き込み等を行います。
PdfDocument.PageInfo ページ情報を管理するクラス、コンストラクタはプライベートになっているのでPdfDocument.PageInfo.Builderを使用してインスタンスを作成する。
PdfDocument.PageInfo.Builder PdfDocument.PageInfoを作成するためのビルダークラス
PdfDocument.Page PDFの一ページに相当し、ページに書き込むためのCanvasを管理する。
PdfRenderer Bitmapに書き出すためにPDFの全ページを読み込みます。
PdfRenderer.Page Bitmapに書き出すためにPDFの1ページを読み込みます。

PDFを作成するためのクラス群

PdfDocument

シグネチャ 説明
PdfDocument.Page startPage(PdfDocument.PageInfo pageInfo) PageInfoインスタンスを渡して編集可能な Pageを取得する。
closeメソッドを使用した後に使用してはいけません。
void finishPage(PdfDocument.Page page) Pageの編集を終了します。
closeメソッドを使用した後に使用してはいけません。
void writeTo(OutputStream out) PdfDocumentの内容を指定した出力ストリームに書き出します。
closeメソッドを使用した後に使用してはいけません。
また、startPageで編集を開始し、finishPageで編集を終了していないPageがある場合も使用してはいけません。
void close() PdfDocumentに対する操作を終了します。
startPageで編集を開始し、finishPageで編集を終了していないPageがある場合も使用してはいけません。
List getPages() PdfDocumentに含まれるPageInfoのリストを返却します。
PageInfoが存在しない場合は空のリストが返却されます。

PdfDocument.PageInfo

シグネチャ 説明
Rect getContentRect() PDFページの高さと幅をRectクラスのインスタンスで返却する。
縦横のPoint値は1point = 1/72inchとなっています。
int getPageHeight() PDFページの高さのPoint値を返却する。
Point値は1point = 1/72inchとなっています。
int getPageWidth() PDFページの幅のPoint値を返却する。
Point値は1point = 1/72inchとなっています。
int getPageNumber() PDFページのページ番号を返却する。

PdfDocument.PageInfo.Builder

コンストラクタ 説明
PdfDocument.PageInfo.Builder (int pageWidth, int pageHeight, int pageNumber)
  • int pageWidth:PDFページの幅のPoint値を設定する。
    Point値は1point = 1/72inchとなっています。
  • int pageHeight:PDFページの高さのPoint値を設定する。
    Point値は1point = 1/72inchとなっています。
  • int pageNumber:PDFページのページ番号を設定する。

 

シグネチャ 説明
PdfDocument.PageInfo create() 設定した値でPdfDocument.PageInfoを作成する。
PdfDocument.PageInfo.Builder setContentRect(Rect contentRect) PDFページの高さと幅をRectクラスのインスタンスで設定する。
高さと幅のPoint値は1point = 1/72inchとなっています。

PdfDocument.Page

シグネチャ 説明
PdfDocument.PageInfo getInfo() Pageに設定されているPdfDocument.PageInfoを返却する。
Canvas getCanvas() Pageに書き込むためのCanvasを返却する。

PDFを表示するためのクラス群

PdfRenderer

コンストラクタ 説明
PdfRenderer(ParcelFileDescriptor input) ParcelFileDescriptor input:表示するためのFileを指定する。

 

シグネチャ 説明
int getPageCount() PDFのページ数を返却する。
PdfRenderer.Page openPage(int index) PDFの指定したページのPdfRenderer.Pageを返却する。
void close() PdfRendererを閉じます。
boolean shouldScaleForPrinting() 印刷のために拡大縮小を必要とするかを返却します。

PdfRenderer.Page

シグネチャ 説明
int getIndex() ページ番号を返却します。
int getHeight() PDFページの高さのPoint値を返却する。
Point値は1point = 1/72inchとなっています。
int getWidth() PDFページの幅のPoint値を返却する。
Point値は1point = 1/72inchとなっています。
void render(Bitmap destination, Rect destClip, Matrix transform, int renderMode) 渡したBitmapにPDFの内容を描画します。
  • Bitmap destination:PDFの内容を描画するBitmap
  • Rect destClip:Bitmapをクリッピングする領域を指定する。
    クリッピングを行わない場合はnullを指定する。
  • Matrix transform:描画時の変形をMatrixで指定する。
    変形しない場合はnullを指定する。
  • int renderMode:モードを指定する。
    PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY:ディスプレイモード
    PdfRenderer.Page.RENDER_MODE_FOR_PRINT:印刷モード
void close()   PdfRenderer.Pageを閉じます。

まとめ

今回は簡単なPDFの作成とPDFの表示を作成しました。
また、作成処理はとても遅いため、実際は非同期処理で実装した方がよさそうです。

サンプルプログラム

public class MainActivity extends AppCompatActivity {
	private String path;
	private PdfDocument pdfDocument;
	private Paint paint;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		path = Environment.getExternalStorageDirectory().getPath() + "/" + Environment.DIRECTORY_DOWNLOADS + "/file.pdf";
		//PDFを作成する。
		createPdf();
		//PDFの内容を画面に表示する。
		showPdf();
	}

	public void createPdf(){
		//PDFに書き込む時に使用するPaintを作成する。
		paint = new Paint();
		paint.setColor(Color.RED);
		paint.setTextSize(30);
		//PdfDocumentをインスタンス化
		pdfDocument  = new PdfDocument();
		long start = SystemClock.currentThreadTimeMillis();
		FileOutputStream fos = null;
		try {
			//PDFに5ページ追加する。
			for (int i = 0; i < 5 ; i++){
			//ページを追加する。
			addPage(i);
			}
			//PDFの書き込みストリームを生成する。
			fos = new FileOutputStream(path);
			//ストリームにPdfDocumentの内容を書き込む
			pdfDocument.writeTo(fos);
			//PdfDocumentを閉じる
			pdfDocument.close();
		} catch (FileNotFoundException e) {

		} catch (IOException e) {

		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		Toast.makeText(this, "Time:"+(SystemClock.currentThreadTimeMillis() - start) + "ms", Toast.LENGTH_SHORT).show();
	}

	public void addPage(int pageNum){
		/**
		* PageInfoインスタンスを作成するためのビルダーをインスタンス化する。
		* 幅:720point(10inch)
		* 高さ:720point(10inch)
		* ページ番号:pageNum
		*/
		PdfDocument.PageInfo.Builder builder = new PdfDocument.PageInfo.Builder(720, 720, pageNum);
		//PageInfoをインスタンス化する。
		PdfDocument.PageInfo pageInfo = builder.create();
		//PageInfoから編集可能なPageインスタンスを取得する。
		PdfDocument.Page page = pdfDocument.startPage(pageInfo);
		//Pageにテキストを描画する。
		page.getCanvas().drawText("PdfDocumentで作成した文書の " + pageNum + " ページ目" ,0 ,30, paint);
		//Pageの編集を終了する。
		pdfDocument.finishPage(page);
	}

	public void showPdf(){
		//PDF表示用のViewを用意する。
		ScrollView scrollView = new ScrollView(this);
		LinearLayout linearLayout = new LinearLayout(this);
		linearLayout.setOrientation(LinearLayout.VERTICAL);
		scrollView.addView(linearLayout);
		setContentView(scrollView);
		try {
			//表示するPDFファイルを指定し、ParcelFileDescriptorインスタンスを作成する。
			ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(new File(path) , ParcelFileDescriptor.MODE_READ_ONLY);
			//ParcelFileDescriptorインスタンスを使用しPdfRendererをインスタンス化する。
			PdfRenderer pdfRenderer = new PdfRenderer(parcelFileDescriptor);
			//印刷するために拡大縮小が必要かを調べる(今回はトースト表示するだけ)
			Toast.makeText(this, "PdfRenderer#shouldScaleForPrinting():" + pdfRenderer.shouldScaleForPrinting(), Toast.LENGTH_SHORT).show();
			//PDFにページが存在するときだけ表示処理を行う。
			if (pdfRenderer.getPageCount() > 0) {
				for (int i = 0 ; i < pdfRenderer.getPageCount() ; i++){
					//ページ番号を指定してPdfRenderer.Pageインスタンスを取得する。
					PdfRenderer.Page page = pdfRenderer.openPage(i);
					//PdfRenderer.Pageの情報を使って空の描画用Bitmapインスタンスを作成する。
					Bitmap bitmap = Bitmap.createBitmap(page.getWidth() , page.getHeight() , Bitmap.Config.ARGB_8888);
					//空のBitmapにPDFの内容を描画する。
					page.render(bitmap , null,null , PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
					//PdfRenderer.Pageを閉じる、この処理を忘れると次回読み込む時に例外が発生する。
					page.close();
					//画面に表示する
					ImageView imageView = new ImageView(this);
					imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT ,ViewGroup.LayoutParams.WRAP_CONTENT ));
					imageView.setImageBitmap(bitmap);
					linearLayout.addView(imageView);
				}
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Androidゲームプログラミング A to Z

新品価格
¥4,968から
(2017/2/27 22:58時点)


AndroidエンジニアのためのモダンJava

新品価格
¥3,456から
(2017/2/27 23:01時点)


AndroidNDKネイティブプログラミング第2版

中古価格
¥1,893から
(2017/2/28 00:04時点)


Androidアプリ開発逆引きレシピ (PROGRAMMER’S RECiPE)

新品価格
¥3,024から
(2017/2/28 00:06時点)


Android Studio ではじめる Android プログラミング入門 第3版 Android Studio 2対応

新品価格
¥3,240から
(2017/2/28 00:11時点)


アプリを作ろう! Android入門 Android Studio版 Android5対応

新品価格
¥2,160から
(2017/2/28 00:31時点)


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)