実現方法としては・・・
僕自身、全て試したわけではありませんが、手っ取り早いのは(1)既存のライブラリを活用する事だと思います。実装が一筋縄ではありませんが・・・
(2)に関しては、PDFの仕様を理解していないとイバラの道になると思います。
でも仕様を理解することは勉強にもなるし、時間に余裕のある人はこちらをオススメします。(日本語訳の公式リファレンスが5、6千円で売ってます。英語のリファレンスはWebで無料でダウンロードできます)
(3)に関しては2chで仕入れた情報ですが、面倒臭そうなので調べていません…
(4)調べたんですが、今のところ無さそうです。。。(もしあれば教えてください)
既存のライブラリを利用してみる
これより先はライブラリの利用方法について説明しますが、フリーのライブラリを利用する際、
いくつか注意する事があります。
これらすべての条件を満たすライブラリとなると、かなり数が限られてきそうです。
特にライセンスは重要です。調べれば分かることですが、GPL関連のライセンスだと利用するのが難しいでしょう。
うろ覚えですが、「GPLライセンスのライブラリを利用する際の条約の一つとして、アプリに組み込まれたライブラリが改変された場合はソースコードを開示しなければいけない。Androidではこの条約を満たすことが出来ないから、結局ソースコードを開示する必要がある」どこかのブログに書いてあった気がします。。。回避策としては、PDFに関連する処理だけを抜き出し、別アプリで公開後、インテント経由で利用するということが考えられます。でもユーザーにアプリのインストール促す必要もあり、いろいろ面倒ですね。。。
なんとなく使えそうなライブラリ
「java PDF ライブラリ」でググルと結構ヒットしますが、どれもコレも一筋縄ではいきません。
java用のPDFライブラリ | ||||
---|---|---|---|---|
ライブラリ名 | packageのサポート | JDKバージョン | 日本語出力 | ライセンス |
iText | × | △ | ◎ | × |
iText for Android | ○ | ? | ○ | × |
PDF Box | × | ? | ? | ○ |
Android PDF Write | ○ | ○ | × | ○ |
iTextはドキュメントも豊富で、ブログ等で使い方も紹介されているぐらいメジャー?なライブラリのようですが、
awt等のAndroidではサポートされないパッケージを使ってます。
実際にiTextを実装する際、この事に気づくまで1週間ぐらいハマってしまいました。
iTextをAndroidで使えるようにしてるらしいですが、どうやらまだ未完成のようです。
実際試しましたが、結局ビルドが通りませんでした。
PDF Box
こちらは試してませんが、やっぱりパッケージ関連の問題で無理なようです。
http://www.kaede-software.com/2011/04/pdfbox.html
恐らくつい最近に公開されたAndroid用のライブラリですが、外国の方が作られたライブラリなので日本語等の出力が無理なようです。英語のドキュメントのみ生成するのであれば、十分利用出来ます。
色々なライブラリを調べた結果、「androidで利用出来るjavaのPDFライブラリ」は今のところ無さそうです・・・
NDKを利用する
それからかなり悩んだのですが、javaが無理ならCのライブラリはどうだ?と色々探してみたところ、
「libHaru free PDF library」を見つけました。
ドキュメント等は全て英語のなのですが、製作者は日本の方なので、日本語の出力も可能です。
ライセンスは zlib/libpngライセンスなので、商用・非商用を問わずアプリに組み込めそうです。
ダウンロード・ドキュメントはこちら
http://libharu.org/wiki/Main_Page
これよりNDKの環境構築とビルドに関して説明していきます。環境を整えるのが結構面倒ですが、それに見合った価値はあると思います。
(とりあえず動きを確認したい場合は、ページ最下部にプロジェクトをダウンロードできるURLを貼りつけています)
NDKの開発環境を整える
環境構築に関しては、分かりやすく解説されているサイトが多数存在しますので、頑張って調べてください。
僕はこちらのサイトを参考にさせていただきました。
http://www.usefullcode.net/2010/12/android_sdk_inst05.html
http://d.hatena.ne.jp/bs-android/20090324/1237864333
ネィティブモジュールを呼び出す準備
クラスファイルにネィティブを使うことを宣言します。
static { System.loadLibrary("CreatePDF"); } private native int createPDF(String fpath);
exportボタンを押すと、SyncTaskが起動してPDFを作成するようにします。
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button b = (Button)this.findViewById(R.id.Button01); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.Button01: export(); break; default: break; } } }); }
private void export() { final ProgressDialog mProgress = new ProgressDialog(this); mProgress.setProgressStyle(ProgressDialog.STYLE_SPINNER); mProgress.setMessage(getResources().getString(R.string.wait)); mProgress.setCancelable(false); Runnable successRun = new Runnable() { public void run() { Toast.makeText(getApplicationContext(), getResources().getString(R.string.success), Toast.LENGTH_SHORT).show(); mProgress.dismiss(); setResult(RESULT_OK); }; }; Runnable errorRun = new Runnable() { public void run() { Toast.makeText(getApplicationContext(), getResources().getString(R.string.error), Toast.LENGTH_SHORT).show(); mProgress.dismiss(); }; }; mProgress.show(); ExportSyncTask task = new ExportSyncTask( this.getApplicationContext(), successRun, errorRun); task.execute(); } private String getSavePath(String catStr) throws IOException { String pathSd = new StringBuilder() .append(Environment.getExternalStorageDirectory().getPath()) .append("/") .append(this.getPackageName()) .toString(); File filePathToSaved = new File(pathSd); if (!filePathToSaved.exists() && !filePathToSaved.mkdirs()) { throw new IOException("FAILED_TO_CREATE_PATH_ON_SD"); } return pathSd + "/" + catStr; } public int exportPDF () throws FileNotFoundException, IOException { String savePath; savePath = getSavePath("helloPDF.pdf"); createPDF(savePath); return 0; } private class ExportSyncTask extends AsyncTask<Void, Void, Integer> { private Handler mHandler; private Handler mHandler2; private Thread mSuccessT; private Thread mErrorT; public ExportSyncTask(Context context, final Runnable r1, final Runnable r2) { mHandler = new Handler(); mHandler2 = new Handler(); mSuccessT = new Thread(new Runnable() { public void run() { mHandler.post(r1); } }); mErrorT = new Thread(new Runnable() { public void run() { mHandler2.post(r2); } }); } @Override protected Integer doInBackground(Void... arg0) { try { exportPDF(); } catch (FileNotFoundException e) { Log.e("PDF_sampleActivity", e.toString()); return -1; } catch (IOException e) { Log.e("PDF_sampleActivity", e.toString()); return -1; } return 0; } @Override protected void onPostExecute(Integer result) { if (result == null || result < 0) { mErrorT.start(); } else { mSuccessT.start(); } } }
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
「CreatePDF」はこれから作成するライブラリの名前になります。
javad側の処理はこれで完了です。
ここで一旦ビルドしてください。
ソースコードをダウンロードする
AndroidでlibHaruPDFを使うには、ソースコードをコンパイルしてAndroid用の共有ライブラリを作成する必要があります。
libHaruPDFはlibpngライブラリーを使用しておりますので、libHaruPDFとlibpngのソースコードをダウンロードしましょう。
libHaruPDF
http://libharu.org/wiki/Downloads
(Latest Versionをダウンロードして下さい)
libpng
http://www.libpng.org/pub/png/libpng.html
(バージョン1.2.46のsource codeよりダウンロードして下さい)
ではeclipseにフォルダを作って、ファイルを移動しましょう。
jniフォルダを作り、その中にlibharu,libpng,pdftestの3フォルダを作ります。
フォルダ構成は次のようになってると思います。(*.c,*.hのみ移動させます。その他のmakeとか必要ないです)
top src gen assets libs res jni --libharu --include --hpdf_annotation.h --hpdf_catalog.h --hpdf_conf.h --... --hpdf_annotation.c --hpdf_array.c --hpdf_binary.c --... --libpng --<*.hと*.cを全て> --pdftest
pdftestフォルダにCreatePDFとヘッダファイルを配置します。
こちらのブログを参考にヘッダファイルを作成します。(「JNIヘッダファイルの生成」の項を参照)
http://d.hatena.ne.jp/bs-android/20090324/1237864333
次にCreatePDF.cを作成してください。
下記URLのサンプルコードを試してみます。(コピペでは動きません)
http://libharu.org/wiki/Documentation/Examples
/* * << Haru Free PDF Library 2.0.0 >> -- font_demo.c * * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp> * * Permission to use, copy, modify, distribute and sell this software * and its documentation for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * It is provided "as is" without express or implied warranty. * */ #include <sample_pdf_PDFsampleActivity.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <setjmp.h> #include "hpdf.h" #include <android/log.h> jmp_buf env; static char* jstr2cp(JNIEnv *e, jstring str); static void jstrfree(JNIEnv *e, jstring str, char *cp); static void log_print(char *str); #ifdef HPDF_DLL void __stdcall #else void
0 件のコメント:
コメントを投稿