MJHD

エモさ駆動開発

AirPrintをXamarin Androidに載っけてみた

 

mjhd.hatenablog.com

 

の記事にて、BMPからUNIRASTへの変換が完了した。

あとは、BonjourとIPPを実装すれば理論上はXamarin AndroidからAirPrintができるはず。

ということで実装してみた。

 

Bonjour

Bonjourは、ネットワーク上のデバイスを探すためのプロトコルのよう。

NuGetにPCLでも使えるBonjourライブラリがあったため、今回はこれを使用する。

www.nuget.org

例えば、ネットワーク上にあるプリンタを列挙したい場合、以下のようなコードを書くことで可能になる。

 

 


    var printer_search = ZeroconfResolver.ResolveAsync("_printer._tcp.local.");
    printer_search.Wait();
    var printers = printer_search.Result;
    foreach(var printer in printers)
      Console.WriteLine(printer);

IPP

AirPrintは実際はIPPを使用して印刷している。

IPPはHTTP上に実装された印刷を制御するためのプロトコル。HTTP上でやりとりが行われているため、プロクシやらSSLやら何やら、HTTPで使用できる技術の恩恵が受けられる点が強みらしい。

遠隔地からの印刷なども、HTTPさえ繋がれば可能になる。

 

今回は、以下のプロジェクトを参考に、IPPをある程度実装した。

github.com

IPPは以下のような書式になっている。(全てビッグエンディアン)

 

Major Version                                 1byte

Minor Version                                 1byte

Operation ID または Status Code  2byte (送信はOperationID、受信はStatusCode)

Request ID                                     4byte (1以上、リクエスト毎の連番)

-- Group

Group ID                                        1byte

-- Attribute

Tag ID                                             1byte

Name Length                                  2byte

Name                                              (Name Length)byte

Value Length                                   2byte

Value                                              (Value Length)byte

Tag ID

-- Attributeの繰り返し

-- Groupの繰り返し

0x03(EndOfAttribute Group ID)      1byte

Groupは、Attributeの集合。操作に関するIDや、ジョブに関するIDなど、Attributeの種類に応じてグループが存在する。

 

Attributeは、実際の値の集合となっている。この辺からかなり複雑になってくるので、割愛。

 

実際のやりとりは、プリンタに対して行いたい操作をOperation IDとしてセットし、詳しい設定をAttributeとしてセット、そして送信する。

その後、帰ってきたIPPデータを読み取り、Status CodeがSuccessなどだったら、Attributeを読み込み、結果を取得する。

という流れになる。

 

今回は、プリンタの情報を取得するGet-Printer-Attributes操作と、ジョブの有効性を判定するValidate-Job操作、実際に印刷をするPrint-Job操作、印刷の状況を取得するGet-Job-Attribute操作を実装した。

 

## ソースコード

https://github.com/mj-hd/AirPrint.NET

 

結果

以上、すべてのソースコードがPCL上で完結しているため、Xamarin上で使用することができる。

そして、無事、Xamarin AndroidからAirPrint対応プリンタを通して印刷が行えた。

 

これにより何が嬉しいかというと、Android標準の印刷ダイアログを表示せずに印刷を行うことができる。

Android標準の印刷機能を使うと、どうしてもユーザに印刷ボタンを押す操作をしてもらう必要が出てしまうため、回避するためにはこう言った工夫が必要なのだと思う。

 

今後の課題

今現在は多くの印刷に関する設定を、プリンタのデフォルト値にしているため、プリンタによって印刷結果が変わってしまうことがある。

この辺どうにかしたい。けど、テストできるプリンタがない…。

 

追記:

実は、AirPrintはBonjourを使うとも限らないようで、自分が探した中にも、Bonjour以外の方法でしか探すことのできないプリンタがあった。どういった方法で探索しているかは、ベンダしか知らないようなので、今回の方法ではすべてのプリンタを探索できるわけではないということが分かった。

探索できない場合は、手動でIPアドレスを指定するようにした。