Android 5.0(Lollipop) で追加されたPdfRendererを使ってPDF表示を試してみた

Android 5.0(Lollipop)にて、ようやくPDF読み込みがサポートされたので、早速エミュレータで試してみました。

今回使用したのは以下のクラスです。
android.graphics.pdf.PdfRenderer
android.graphics.pdf.PdfRenderer.Page

実装例

  • activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
  • MainActivity
package com.example.test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Rect;
import android.graphics.pdf.PdfRenderer;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.widget.ImageView;

public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        File sdcard = Environment.getExternalStorageDirectory();
        ParcelFileDescriptor fd = null;
        PdfRenderer renderer = null;
        PdfRenderer.Page page = null;
        try {
            // SDカード直下からtest.pdfを読み込み、1ページ目を取得
            fd = ParcelFileDescriptor.open(new File(sdcard, "test.pdf"), ParcelFileDescriptor.MODE_READ_ONLY);
            renderer = new PdfRenderer(fd);
            page = renderer.openPage(0);

            ImageView view = (ImageView) findViewById(R.id.image);
            int viewWidth = view.getWidth();
            int viewHeight = view.getHeight();
            float pdfWidth = page.getWidth();
            float pdfHeight = page.getHeight();
            Log.i("test", "viewWidth=" + viewWidth + ", viewHeight=" + viewHeight
                    + ", pdfWidth=" + pdfWidth + ", pdfHeight=" + pdfHeight);

            // 縦横比合うように計算
            float wRatio = viewWidth / pdfWidth;
            float hRatio = viewHeight / pdfHeight;
            if (wRatio <= hRatio) {
                viewHeight = (int) Math.ceil(pdfHeight * wRatio);
            } else {
                viewWidth = (int) Math.ceil(pdfWidth * hRatio);
            }
            Log.i("test", "drawWidth=" + viewWidth + ", drawHeight=" + viewHeight);

            // Bitmap生成して描画
            Bitmap bitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.ARGB_8888);
            page.render(bitmap, new Rect(0, 0, viewWidth, viewHeight), null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

            view.setImageBitmap(bitmap);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fd != null) {
                    fd.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (page != null) {
                page.close();
            }
            if (renderer != null) {
                renderer.close();
            }
        }
    }
}

実行結果

device-2014-10-20-175322

無事、こんな感じで出力されました。

注意点としては、RGB_565だと「Unsupported pixel format」とエラーが出力されてしまう点ですかね。
renderのAPI仕様に記載の通り、ARGBでないといけないようです。

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ