VisualStudio Code の ターミナル に MSYS2 の zsh を使う

settings.jsonに以下のように記述

{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\zsh.exe",
    "terminal.integrated.env.windows": {
        "MSYSTEM": "MINGW64",
        "CHERE_INVOKING": "1",
        "MSYS2_PATH_TYPE": "inherit"
    },
    "terminal.integrated.shellArgs.windows": [
        "--login"
    ],
    "terminal.integrated.cursorStyle": "line"
}

MSYS2でインストールしたGitは挙動不審なのでGit for Windowsを使用する。 したがって「"MSYS2_PATH_TYPE": "inherit"」は必須。

画像認識やってみたい(Xamarinで既存のjarやsoを使う)

画像認識やってみたい!!
というわけで調べてみると、こんなのを発見。

www.gaprot.jp

なんか簡単そう。 とりあえずお得意のVisualStudioで作ってみよう。 →失敗しました。以下失敗の記録。

もらってくる

上記のページから

  • 画像認識ライブラリv2 for Android
  • 画像辞書作成ツールv2 for Windows

をダウンロード

画像辞書をつくる

「画像辞書作成ツールv2 for Windows」をダウンロード・展開して、DatasetCreater.exeを実行。
使い方は上記ページの通り。同梱の Tutorial にも書いてあるが、とても簡単。

プロジェクトの作成

VisualStudioで新規プロジェクトを作成。テンプレートは「Androidアプリ(Xamarin)」の「単一ビューアプリ」を選択。
今回はXamarin.Formsはパス。

jarを参照できるようにする

「画像認識ライブラリv2 for Android」は、jarファイルといくつかのsoファイル(共有ライブラリ)、aファイル(静的ライブラリ)で構成されている。
jarファイルをXamarinで参照できるようにするには、「Androidバインドライブラリ(Xamarin)」を作成するらしい。

docs.microsoft.com

少々日本語が不自由だが、jarファイルを追加することはできた。
soファイルは??

soファイルを埋め込む

以下の手順でOK

  1. Androidバインドライブラリ(Xamarin)」プロジェクトの下に、libフォルダを作成する。
  2. libフォルダに、「画像認識ライブラリv2 for Android」のarmeabiフォルダを中身ごとコピーする。
  3. VisualStudioで、armeabiフォルダ下の全ファイルについてビルドアクションを「EmbeddedNativeLibrary」に変更する。
    ここで、.DS_Store は .thumbnail 的なファイルであるため無視してよい。
    .aファイルは通常.soファイルに含まれるためこれも無視してよい。。。はず。

Xamarinからバインドライブラリを使う

Androidアプリ(Xamarin)」プロジェクトから「Androidバインドライブラリ(Xamarin)」プロジェクトを参照すればOK。
あとは、「画像認識ライブラリVer.2.0 | ギャップロ」のサンプルのように実装すればよい。
バインドライブラリでインターフェイスが自動変換されているためコピペでは動かないが、オブジェクトブラウザでカバーできる。
getXXX が XXX というプロパティになっていたり、someFunc 関数が SomeFunc 関数に変換されている程度の相違しかない。
これは素敵な機能!

ABIを変更する

「画像認識ライブラリv2 for Android」に含まれていたsoファイルは、armeabiにしか対応していない(と思う)。
アーキテクチャがarm64のスマホで実行するとファイルがないエラーが発生する。ちょっとハマった。
CPUアーキテクチャは一般的に下位互換性があるので、対応アーキテクチャをarmeabiに限定しても動くはず。
下図のように「Androidアプリ(Xamarin)」プロジェクトのプロパティから「サポートされているアーキテクチャ」をarmeabiのみに変更する。
x86エミュレータが使えないのは痛いが、仕方ない。

f:id:foohogehoge:20180901144256p:plain

いざ実行! しかし……

f:id:foohogehoge:20180901145012p:plain

oh....

  • .aファイルもEmbeddedNativeLibraryにしてみる
  • GPFineRecognizerではなくGPFastRecognizerにしてみる
  • 古いNexsus5でデバッグしてみる

等々試してみたが解決せず。 AndroidStudioを立ち上げる元気もないのでとりあえず投げる。

WindowsのJenkinsSlaveから git fetch ができない

前提

  • Jenkinsサーバー・Slave共にWindows
  • gitサーバーもWindowsSSHではなくフォルダ共有でセットアップ。
  • gitリポジトリがある共有フォルダにアクセスするためのユーザー・パスワードが設定されている

Slaveを単純に追加すると認証エラー

下記ページあたりを参考にSlaveを追加する。 https://blog.engineer-memo.com/2015/06/08/windows-に-jenkins-をインストールして-windows-スレーブを追加/

git リポジトリ からソースを取得してビルドするようなジョブを追加すると、

fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists. とエラーが発生する。

サービスのログオンユーザーを変更するとOK

[管理ツール]-[サービス]からJenkinsSlaveのサービスを探す。 右クリック-[プロパティ]を選択。 「ログオン」タブをクリックして、”ローカル システム アカウント”を”アカウント”に変更。 適当なユーザーを選択してパスワードを入力する。 ここで選択するユーザーは、共有フォルダへのアクセス権が必要。 ドメイン管理していなければ Windows資格情報マネージャー で設定しておく。

Visual Studio 2017 で Xamarin する(4)イベント処理

Aboutボタンの処理を書く

Activityの定義は完全にテンプレートのままで問題なかった。 AndoridプロジェクトのMainActivity → 共通のApp.xaml → 共通のMainPage.xaml のように呼び出しているようだ。 次は、イベント処理を書いてみる。

<Button
    Text="{x:Static properties:Resources.About}" 
    Clicked="About_Clicked"/>

Clicked= でイベントハンドラを追加する。適当に名前を付けて、F12キー(定義へ移動)で空の関数が作成されてナイス。

ダイアログの表示は、DisplayAlertメソッドを使うのだがこれはPageオブジェクトのメソッドだ。 FragmentMainはPageではないので、無理やり実装するとこんな感じか。

  • FragmentMain.xaml.cs
private void About_Clicked(object sender, EventArgs e)
{
    ((Page)this.Parent.Parent).DisplayAlert("About Ultimate Tic Tac Toe", "This game is...", "OK");
}

さすがにひどい。 MainPage側でコントロールのイベントをハンドルしてやればよさそう。

まず、ボタンを識別するために名前を設定する。

<Button
    x:Name="About_Button"
    Text="{x:Static properties:Resources.About}" />

親から子を識別できるように FragmentMain にも名前を設定する。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:TicTacToe"
             x:Class="TicTacToe.MainPage">

    <Frame VerticalOptions="Center"
           HorizontalOptions="Center">
        <local:FragmentMain
            x:Name="fragment_main"/>
    </Frame>
</ContentPage>

MainPageでハンドルする

public MainPage()
{
    InitializeComponent();
    this.fragment_main.About_Button.Clicked += AboutButton_Clicked;
}

しかし、About_Buttonが見えない。「アクセスできない保護レベルになっています」と怒られる。

名前のほかに何かないかと探すと、FieldModifier といういかにもな属性がある。

<Button
    x:Name="About_Button"
    x:FieldModifier="internal"
    Text="{x:Static properties:Resources.About}" />

のように書き換えてみたが、やはりAbout_Buttonが見えない。この属性は無効っぽいのでプロパティでボタンを公開してやる

  • FragmentMain.xaml.cs
internal Button AboutButton { get { return About_Button; } }
public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        fragment_main.AboutButton.Clicked += AboutButton_Clicked;
    }

    private void AboutButton_Clicked(object sender, EventArgs e)
    {
        DisplayAlert("About Ultimate Tic Tac Toe", "This game is...", "OK");
    }
}

実行してみる

Android

f:id:foohogehoge:20170408233036p:plain:h600

UWP

f:id:foohogehoge:20170408233200p:plain:w600

タイトルが二重に表示されるのがちょっとダサい。

なんとかモノになりそうな気がしてきましたよ。

参考

Xamarin.Formsでダイアログボックス(とBusyインジケーター)を表示するには? - Build Insider

[Xamarin.Forms] x:FieldModifier が使えない? | rksoftware

x:FieldModifier — Xamarin Forums

Visual Studio 2017 で Xamarin する(3)文字列リソース

リソースファイルを作成する

初めてのAndroid 第4版を一通り読んだ後なので、先にリソースファイルを整備しておいた方が楽なのを知っている。 VisualStudioでリソースファイルを追加するのは慣れたもの。 TicTacToe(移植可能)プロジェクトのプロパティページを開いて、リソースファイルを追加する。 f:id:foohogehoge:20170408200754p:plain:w600

f:id:foohogehoge:20170408201115p:plain:w600

こんな感じになるのだが、多言語対応のために Resources.ja-JP.resx も追加しておく。 Resources.resx と Resources.ja-JP.resx の中身は以下のようにした。

f:id:foohogehoge:20170408214235p:plain:w600

f:id:foohogehoge:20170408214243p:plain:w600

アクセス修飾子をPublicにするのを忘れずに。

Xamlから使うときはこんな感じ。

<?xml version="1.0" encoding="UTF-8"?>
<StackLayout 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:properties="clr-namespace:TicTacToe.Properties"
    x:Class="TicTacToe.FragmentMain">
    <Label
       Text="{x:Static properties:Resources.Title}"
       VerticalOptions="Start"
       HorizontalOptions="Center" />
    <Button
        Text="{x:Static properties:Resources.Continue}" />
    <Button
        Text="{x:Static properties:Resources.NewGame}" />
    <Button
        Text="{x:Static properties:Resources.About}"/>
</StackLayout>

5行目の

xmlns:properties="clr-namespace:TicTacToe.Properties"

がポイント。

実行してみる

Android

f:id:foohogehoge:20170408221552p:plain:h600

良さそうだが、エミュレーターロケールをja-JPに指定する必要があった。 エミュレーターで日本語表示する際のロケールは単に ja であるが、 ja ではアプリの日本語表示ができなかった。 Resouces.ja.resxを作成しても解決できない。 面倒くさい予感がするので後回しにする。とりあえず色や座標がリソースから指定できていればローカライズは後から何とかなる。

UWP

f:id:foohogehoge:20170408221611p:plain:w600

こちらは何の問題もない。