PDFBoxを使ってPDFを作成する(その2)

PDFBoxを使ってPDFを作成しようとしたところ・・・という話でした。

5.改行、改ページができない

できない、と書きましたができるんです。
改行は
cos.newLine();
改ページは
page = new PDPage();
document.addPage(page);

でできます。でもそうじゃないんです!
長い文やページを超える文を出力するときに、自動で改行や改ページしてほしいんです!
結論。できません。
そういうものかもしれませんが、なんとなく自動でできるような気がしていました。
ということで、文字数/行数を自分でカウントして、よきところで改行/改ページを入れる方法で解決しました。
コードは汚いので割愛します。。

6.ファイル保存でOutOfMemoryError発生

今回、1000ページ(数百MB)以上のPDFを作成することもあったのですが、
document.save("sample.pdf")
のところでOutOfMemoryが発生することがありました。
調べたところ、ページ数が多いと発生することがあるという記事を見つけました。
(ちなみにJDK1.6限定で、1.7だと発生しないとのことです。今回の環境は1.6でした。)
この記事なんですが、リンク切れで表示できません。一応、URLはこちらです。
http://www.gcgate.jp/engineerblog/2013/12/06/223/
記事によると
・ある一定ページ数になったらPDFをファイルに書き込む
・その書き込んだPDFファイルを読み込みページを追加する
・繰り返す
で解決したということだったので、これを試したのですが解決せず。
いろいろ試して、PDFファイルを分割して保存する方法で解決できました。
これもコードは割愛しますが、ページ数を自分でカウントして、決まった件数のときにファイルを保存する、という流れです。
今回のケースは、ページ数が多いというより、ファイルサイズの大きさによるような気がします。
分割する際ファイルサイズでできればいいのですが、それは厳しいのでページ数で区切りました。

7.作成したファイルで検索ができない

すみません。これはまだ解決できていません。
1つ前の記事で書いた通り、今回日本語を表示するためにIPAゴシックを使いました。
すると、作成したPDFをAdobeのPDFリーダー等で開いて、検索しようとすると
検索できるファイルと検索できないファイルがありました。何か特定の文字が含まれると検索できないようなのですが、原因となる文字は特定できていません。
また、PDFBoxで何かしら対策ができるのか、も今のところ不明です。

他のライブラリは使っていないので比較ができないのですが、PDFBox、便利は便利だけどすごく使いやすくはない、というふわっとした感想で終わりたいと思います。
あ、公式サイトのFAQは結構役立ちました。

PDFBoxを使ってPDFを作成する(その1)

JavaでPDFファイルを作成することになり、いろいろライブラリを見た結果、一番よさげだったApache PDFBoxを使うことにしました。
一応やりたいことはできたものの、困ったことやわからないことがポロポロとあったので、そのあたり書き残しておこうと思います。
ごくごく基本的な使い方(HelloWorld的な)について説明しているページはいくつか見つけたものの、そこから先の細かい使い方を書いてくれているページがあまりなかったので、どこかの誰かの役に立てばいいなと思いつつ。。。

1.ダウンロード

公式サイトのダウンロードページからダウンロードします。

2.HelloWorld

特に難しいことはありません。以下のコードでHelloWorldと出力されます。正確には出力されたPDFファイルが作成されます。ですね。
細かい説明は省きます。
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream cos= new PDPageContentStream(document, page);
cos.beginText();
cos.newLineAtOffset(0f, 0f);
cos.setFont(font, 12);
cos.setLeading(12);
cos.showText("Hello World");
cos.endText();
cos.close();
document.save("helloworld.pdf");
document.close();

※PDPageContentStreamは、1ページにつき1回生成します。
1ページの中に異なるフォントや異なる文字サイズで出力する場合は、
cos.beginText();
から
cos.endText();
までを繰り返します。

3.日本語

必要に応じてフォントをダウンロードしてください。ちなみに今回はIPAフォントを使いました。
そして、
PDFont font = PDType1Font.HELVETICA_BOLD;
の部分を
PDFont font = PDType0Font.load(document, new File("/usr/share/fonts/ipa-gothic/ipag.ttf"));
とすることで、日本語も表示することができます。

4.画像

PDImageXObject ximage = PDImageXObject.createFromFile("photo.jpg", document);
cos.drawImage(ximage, 100, 100, ximage.getWidth(), ximage.getHeight());

で画像が表示できます。

文字の表示にしろ画像の表示にしろ、それぞれ表示位置を指定できるので、1つのページに文章と画像を表示することももちろん可能です。
表示位置は、実際に出力してみて、微調整した方がいいと思います。
また、画像の表示は文字の表示に比べてかなり時間がかかります。(画像のサイズが大きいと特に)

ここまでが基本的な使い方になります。日本語も表示できる、画像も表示できる、よしよし・・・と思ったのも束の間、ちょこちょこと問題が発生するのでした。

続く

「Android」端末で「ビーコン」を受信

小さいエリアでの通信や端末同士の位置情報を利用したサービスに興味がある。
Androidの開発環境を用意したのでAndroid端末のBLEを利用した「ビーコン」について調べた。

BLEを利用した「ビーコン」は、Bluetooth機器のペアリング時使用していた、アドバタイジングパケットを利用した発信機なイメージ。
その信号をひろって「ビーコン」のIDや信号の強さなどの情報から位置情報サービスに利用するのだろうと思っている。

BLEを利用した「ビーコン」には、Appleの「iBeacon」とGoogleの「Eddystone」があるらしい。
今回は情報が多そうな「iBeacon」を対象とする。

1.テスト用のアプリのインストール

自分で書いたコードが正しく「iBeacon」の受発信を行えているかをテストするためアプリとして以下のものを使用させてもらった。

2.ビーコンライブラリの登録

サンプルコードが豊富なビーコンライブラリの「AltBeacon」を使用する。
ライブラリの登録は「プロジェクトの構造」画面で行う。

「Android Studio」を起動し、プロジェクト、「プロジェクトの構造」>「app」>「依存関係」タブの「+」ボタンを押下するとプロジェクトへライブラリの登録する画面が表示される。
「altbeacon」と入力して検索ボタンを押下すると「org.altbeacon:android-beacon-library」がヒットするので選択し登録する。

「プロジェクトの構造」
ライブラリの登録

build.gradleファイルのdependenciesに次の行が追加されていることを確認。

3.BLE関連のPermissionの追加

BLEデバイスにアクセスできるように「app/src/main/AndroidManifest.xml」に次のような設定を追記。

4.「Android」端末側の設定

Bluetoothにアプリケーションがアクセスできるようにするため「Android」端末側の設定が要るようだ。まず、Bluetoothを有効にする。

一度アプリケーションをデプロイした後に、
「設定」>「端末管理」>「アプリケーション」>[デプロイしたアプリケーション]をタップする。「アプリ情報」の「許可」をタップすると「位置情報」の許可設定ができるようになっているので有効にする。(※)

※この許可をしていないと下のようなメッセージが出力されBluetoothにアクセスできない。

5.ビーコン受信のJavaコード

6.実行

上記のコード実行しiOS版の「Beacon入門」から「ビーコンの発信」を行うと以下のようなログが出力された。
動作しているようだ。

次は発信(送信)を試そう。

Unity3DでDebugする

CUDLRによるデバッグ

CUDLR

CUDLR(Console for Unity Debugging and Loggin Remotely)
Unityアセットストアより無料で入手可能なアセット
ターゲットのデバイスに、簡易なWebサーバ(のような物)を稼働させ、Log等をブラウザから確認可能したり
幾つかの簡単なコマンドを実行可能にするツール

使用方法

デバッグオブジェクトの追加

CUDLRの機能を使用するには、GameObjectとして配置する必要があります。
プロジェクトを開き、HierachyウィンドよりEmptyObjectをシーンへ追加し
追加したGameObjectへ、コンポーネントとしてCUDLRのServerを追加します。


Assets/CUDLR/Script/Serverをコンポーネントとして、GameObjectへ登録する

確認の為に、下記のようなコンポーネントを登録します

ビルドし、Deviceにインストールし、アプリケーションを起動します
起動後、ブラウザでhttp://[DviceのIP]:55055/へアクセスすると、実行中のアプリログが確認できます。
DeviceのIPは事前に確認しておいてください。

サンプルで設定したコンポーネントのログが出力されていますね

コマンドを幾つか実行する事もできます。

オブジェクトリストを表示してみます

注意点

リリースモジュールに含まれると、セキュリティー上のリスクとなります。
リリース時にはCUDLRオブジェクトの削除を忘れずに行いましょう

VSCodeによるデバッグ

次にVSCode上にブレークポイントを設定し、ステップ実行を行ってみます

テスト用のコードを少し改変し、ビルド、インストールを行います

アプリの起動後、CUDLRで確認します。

一定時間毎にログが出ていることが確認できます。

VSCodeにブレークポイントを設定します

左のメニューより虫のようなアイコンを選択します

デバッグ対象をAndroidPlayerに変更し、再生(▶ボタン)を選択する


DeviceにAttacheできました。

しばらく待つと、ブレークポイントで止まる事が確認できます。
変数の中も確認できました。

これで開発が進められそうです。

最後に

執筆時点で、2018.2.0b5がリリースされていたのですが、これはBetaリリースです。
こちらのバージョンはVSCodeからDeviceniにAttacheできませんでした。
xxxx.x.0fxと行ったバージョンが正式バージョンのようですので、利用する際は注意しましょう

「Android」端末で「Hello World」2

androidアプリを作りたい。
まずはお約束の「Hello World」を出力するまでのメモのその2。
実機の実行とデバッグについて触れる。

5.実機「Android」端末(Fujitsu Arrows M03)で実行する

まず、IDEを使ったデプロイ・デバッグができるように「Android」端末を開発者モードに切り替える。

「Android」端末の「アプリ一覧」画面から、「設定」>「端末管理」>「端末情報」と選び、「ビルド番号」を数回タップ。「これでデベロッパーになりました!」とメッセージが出力されたら「端末管理」に「開発者向けオプション」が表示されるようになる。

「アプリ一覧」画面
「設定」画面
「端末情報」画面
※「開発者向けオプション」は当初表示されない
「端末情報」画面
ビルド番号を数回タップ後に表示されるメッセージ

「開発者向けオプション」画面で「OFF」から「ON」に切り替え、「USBデバッグ」にチェックを入れる。

「開発者向けオプション」画面

PCとAndroid端末をUSBでつなげるとUSBデバッグの許可を求めてくるので「OK」を押下する。

IDE(Android Studio)に戻り、再び「ツールバー」から「実行」ボタンを押すと「デプロイ対象の選択」画面に実機(FUJITSU ArrowsM03)が選択可能になった。

「デプロイ対象の選択」画面
「FUJITSU ArrowsM03」で実行
6.デバッグモードで起動しブレーク(停止)させる

ブレークポイントの置き方は他のIDEなどと同じ。ソースコードエディタの行番号の右隣をクリックすれば赤丸が表示され、その行でブレークできるようになる。

デバッグモードでデプロイ・起動するボタンはツールバーの「デバッグ」ボタン。

「デバッグ」ボタン
デバッグブレーク

起動中のプロセスにアタッチしてデバッグしたい場合は、「Andoroidプロセスへデバッガー接続」ボタンを押下する。
「プロセスの選択」画面でアタッチするプロセスを選択する。

「Andoroid
プロセスへデバッガー接続」
ボタン
「プロセスの選択」画面

これで開発する準備ができた。