Xamarin.Forms でバーコードスキャンライブラリ ZXing.Net.Mobile を使う

こんにちは。エクセルソフトの田淵です。

ZXing（Zebra Crossing の略みたいです）を使って簡単にバーコードスキャナが作れるよ！というエントリーを Xamarin エバンジェリストの James Montemagno さんがアップされていたので、試してみました。ネイティブでも有名なライブラリですよね。

[GitHub サンプル](https://github.com/ytabuchi/Study/tree/master/XFP_ZXingSample)

Windows Phone 8.1 に対応していない（Sliverlight のみ）ので、 Profile 7、49、78 のどれかを使用する必要があります（多分）。私は Profile 7 にして NuGet からインストールできました。各 Profile の対応プラットフォームは [私のブログエントリー](http://ytabuchi.hatenablog.com/entry/2014/12/10/174116) を参照してください。

### インストール

PCL の Profile が 7、49、78 以外の場合は Profile を変更します。Xamarin.Forms PCL プロジェクトで Profile を変更するには、一度 Xamarin.Forms ライブラリをアンインストールして、PCL プロジェクトのプロパティで Windows Phone 8.1 を外すなどして、保存し、再度 Xamarin.Forms ライブラリをインストールする必要があります。

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310201721.png" width="300">

NuGet から `ZXing.Net.Mobile.Forms` をインストールすると、一緒に `ZXing.Net.Mobile` もインストールされます。

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310201925.png" width="450">

インストール後の各プラットフォームの参照一覧は次のようになっていました。

PCL
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310202342.png" width="300">


Android
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310202518.png" width="300">

iOS
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310202554.png" width="300">

UWP
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310202621.png" width="300">


Windows Store
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310202655.png" width="300">

### 使い方

サンプルなので簡単に。
`NavigationPage` 経由でページを表示し、コードビハインドに次のイベントハンドラを記述します。

```csharp
using ZXing.Net.Mobile.Forms;

async void ScanButtonClicked(object sender, EventArgs s)
{
    // スキャナページの設定
    var scanPage = new ZXingScannerPage()
    {
        DefaultOverlayTopText = "バーコードを読み取ります",
        DefaultOverlayBottomText = "",
    };
    // スキャナページを表示
    await Navigation.PushAsync(scanPage);

    // データが取れると発火
    scanPage.OnScanResult += (result) =>
    {
        // スキャン停止
        scanPage.IsScanning = false;

        // PopAsyncで元のページに戻り、結果をダイアログで表示
        Device.BeginInvokeOnMainThread(async () =>
        {
            await Navigation.PopAsync();
            await DisplayAlert("スキャン完了", result.Text, "OK");
        });
    };
}
```

XAML はボタンを追加しただけです。

では、各プロジェクトでビルドしてみます。

#### iOS

iOS は初回起動時の許可を求める必要がありますので、iOS プロジェクトの `AppDelegate.cs` の `global::Xamarin.Forms.Forms.Init();` の後に ZXing の初期化コードが必要です。

```csharp
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    global::ZXing.Net.Mobile.Forms.iOS.Platform.Init(); // <- これ
    LoadApplication(new App());

    return base.FinishedLaunching(app, options);
}
```

また、ダイアログのメッセージを `Info.plist` に追加します。

```xml
<key>NSCameraUsageDescription</key>
<string>カメラを利用してスキャンします。</string>
```

初回起動時に確認ダイアログが表示されました \:clap:\:clap:

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160315/20160315112020.png" width="300">


#### Android 

ビルド前に色々設定を。

Manifest

GUI の設定から、または `Manifest.xml` を直接編集し、CAMERA と FLASHLIGHT の権限を取っておきます。

```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
```

Runtime Permission

Android 6.0 Marshmallow を対象にする場合は、ランタイムパーミッションの設定が必要なので 、Android プロジェクトの `MainActivity.cs` に以下を追加します。

```csharp
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    global::ZXing.Net.Mobile.Forms.Android.PermissionsHandler.OnRequestPermissionsResult (requestCode, permissions, grantResults);           
}
```

ビルドすると \:scream:\:scream:
<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310201519.png" width="450">

むむむ。。。ライブラリで参照しちゃってるんですね。仕方ないので `values/Strings.xml` のフォルダ、ファイルを作成し、

```xml
<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <string name="Hello">Hello World, Click Me!</string>
  <string name="ApplicationName">アプリ名</string>
</resources>
```

を追加しておきます。

OK です。無事ビルドが通りました。ボタンをクリックしてカメラを初回起動した時の Marshmallow の Runtime Permission も動作しています。\:clap:\:clap:

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310204453.png" width="300">


#### UWP

UWP は一応 `Package.appxmanifest` の［機能］タブで［Webカメラ］にチェックを入れました。不要かも。

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160315/20160315113151.png" width="300">



### 動作イメージ

笑えるくらい素早く認識してくれます。\:+1:\:+1:

#### iOS

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160315/20160315104543.gif" width="300">

#### Android

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160310/20160310211746.gif" width="300">

#### UWP

やっぱり QR コードしか対応していないようでした。

<img src="http://cdn-ak.f.st-hatena.com/images/fotolife/y/ytabuchi/20160315/20160315104632.gif" width="300">

### この後は

例えば `ObservableCollection<string>` に `scanPage.OnScanResult` の `Result.Text` をガンガン突っ込んでいけば連続でスキャンできますよね。ただ、画面を「スキャンしたよ」と一瞬ホワイトアウトさせるような処理を入れないとスキャンしたのかしてないのか分からないですよね。どうやるのか気になります。是非チャレンジしてみてください。


### Xamarin 気になった方は

是非 <a href="http://xamarin.com/download/">ダウンロード(直接)</a> / <a href="https://www.xlsoft.com/jp/products/download/index.html?option=Xamarin&r=ythb">ダウンロード(弊社経由)</a> して触ってみてください。
<a href="http://ytabuchi.hatenablog.com/entry/2014/08/26/191759">学習用リソース</a> や <a href="http://jxug.org/links.html">JXUG リンクページ</a> に参考資料を纏めてますので併せてどうぞ。

Xamarin の情報が欲しい方は <a href="http://blog.hatena.ne.jp/ytabuchi/ytabuchi.hatenablog.com/subscribe">田淵ブログも購読</a>いただいたり、私の<a href="https://twitter.com/ytabuchi">Twitterアカウントをフォロー</a>いただいたりすると嬉しいです。

以上です。