かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

python から Cognitive Services の API をたたいてみよう

Cognitive Services は、ある程度でしたら無料で試せます。

azure.microsoft.com

ここでは、Emotion API を試しにたたいてみようと思います。

API キーの取得

Emotion API の API キーの取得 ボタンを押します。 使用条件が表示されるので、よく読んで国を選択して、同意できる場合は同意して次へ進みます。

f:id:okazuki:20170920111740p:plain

次にサインインを求められます。これは Microsoft Account, Facebook, LinkedIn, Github が使用できます。

f:id:okazuki:20170920111832p:plain

私は Github を選択しました。 Github のサインイン画面が出てくるのでサインインしましょう。 サインインすると以下のように呼び出しに必要なエンドポイントとキーが表示されます。とりあえずキー1があれば問題ありません。

f:id:okazuki:20170920112143p:plain

呼んでみよう

基本こちらにやり方が書いてあります。

docs.microsoft.com

Python 2.7 で試してみてます。 とりあえず Emotion API のサンプルがインターネット上の画像の URL を送って結果を返すものだったので、ここではローカルの画像ファイルを読み込んで POST するものにしました。

import httplib
import urllib
import base64

headers = {
    'Content-Type': 'application/octet-stream',
    'Ocp-Apim-Subscription-Key': 'ポータルから取得したキー'
}

params = urllib.urlencode({

})

try:
    with open("emotionsample.jpeg", "rb") as f:
        conn = httplib.HTTPSConnection('westus.api.cognitive.microsoft.com')
        conn.request('POST', '/emotion/v1.0/recognize?%s' % params, f, headers)
        response = conn.getresponse()
        data = response.read()
        print(data)
        conn.close()
except Exception as e:
    print("[Errno {0}] {1}".format(e.errno, e.strerror))

実行すると以下のように JSON が返ってきます。

[
    {
        "faceRectangle": {
            "height": 162,
            "left": 130,
            "top": 141,
            "width": 162
        },
        "scores": {
            "anger": 9.29041E-06,
            "contempt": 0.000118981574,
            "disgust": 3.15619363E-05,
            "fear": 0.000589638,
            "happiness": 0.06630674,
            "neutral": 0.00555004273,
            "sadness": 7.44669524E-06,
            "surprise": 0.9273863
        }
    }
]

コードは以下の Github リポジトリに格納しています。

github.com

CoreML を Xamarin.Forms で使ってみよう

なんか iOS 11 から CoreML ってのが使えて簡単にいうと機械学習の学習結果を iOS ローカルで動かせるぜ!っていう感じのものらしいですね。強い。

ということで、Apple Developer と Xamarin のドキュメントを見ながら試してみたいと思います。

Core ML | Apple Developer Documentation

developer.xamarin.com

ちなみに、CoreML で使える学習結果のファイルは、Cognitive Services の Custo Vision API で作れるということなので、今回はこれも使ってみたいと思います。

azure.microsoft.com

Custom Vision API でいい感じの画像データを用意するのがめんどくさかったので、Drew さんの作ってくれた、このハンズオンにある画像をそのまま使いたいと思います。

github.com

customvision.ai

ではさくっと Custom Visoin を使えるようにしましょう。本題じゃないので注意点だけを。

Custom Vision のサイトでプロジェクトを作るときに General (compact) を使うことです。これをしないと CoreML で使えるファイルをエクスポートできません。

f:id:okazuki:20170919203915p:plain

あとは、Drew さんのリポジトリにある画像を適当に投げ込んで Fries / Not Fries のカテゴリを作って学習させます。

学習させたら下の青で囲ったエクスポートボタンを押します。

f:id:okazuki:20170919210929p:plain

こんな画面になるので、あとは支持に従うだけです。mlmodel という拡張子のファイルが取得できます。

f:id:okazuki:20170919211037p:plain

次の作業環境は Mac です。以下のコマンドをターミナルでうちます。

xcrun coremlcompiler compile さっきダウンロードしたファイル.mlmodel 出力先フォルダ

出来上がったファイルをどうにかして Windows にもっていきましょう。

Xamarin.iOS で頑張る

とりあえず、Xamarin.Forms でプロジェクトを作って iOS プロジェクトだけで動くように作りたいと思います。先ほどのコマンドでできた一連のファイルを iOS プロジェクトの Resources フォルダに移動させます。

f:id:okazuki:20170919223451p:plain

ClreML を使って認識をしてくれるであろう処理のためのインターフェースを PCL プロジェクトに作ります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoreMLLabApp
{
    public interface IFriesOrNotFriesService
    {
        Task<string> DetectAsync(byte[] image);
    }
}

そして、MainPage.xaml を以下のような感じにします。

<?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:CoreMLLabApp"
             x:Class="CoreMLLabApp.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS">0,20,0,0</On>
        </OnPlatform>
    </ContentPage.Padding>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        
        <Button Text="Take picture"
            Clicked="Button_Clicked" />

        <Image x:Name="image"
               HorizontalOptions="Fill"
               VerticalOptions="Fill"
               Grid.Row="1" />
    </Grid>
</ContentPage>

そして、カメラから画像をとりたいので Xam.Plugin.Media を導入して表示される readme.txt の内容に従って info.plist に設定を追加したら MainPage.xaml.cs を以下のようにします。

using Plugin.Media;
using Plugin.Media.Abstractions;
using System;
using System.IO;
using Xamarin.Forms;

namespace CoreMLLabApp
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private async void Button_Clicked(object sender, EventArgs e)
        {
            await CrossMedia.Current.Initialize();

            var file = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions());
            if (file == null) { return; }

            this.image.Source = ImageSource.FromStream(() => file.GetStream());

            using (var fs = file.GetStream())
            using (var ms = new MemoryStream())
            {
                await fs.CopyToAsync(ms);
                var d = DependencyService.Get<IFriesOrNotFriesService>();
                var result = await d.DetectAsync(ms.ToArray());
                await this.DisplayAlert("Result", result, "OK");
            }
        }
    }
}

ここまでは、ただの Xamarin.Forms ですね。

CoreML を使ってみよう

では、iOS プロジェクトに FriesOrNotFriesService.cs を追加して処理を書いていきます。サンプルプロジェクトとかを参考に以下のように書いてみました。

using System;
using System.Linq;
using System.Threading.Tasks;
using Foundation;
using Vision;
using CoreML;
using CoreImage;
using CoreFoundation;

[assembly: Xamarin.Forms.Dependency(typeof(CoreMLLabApp.iOS.FriesOrNotFriesService))]
namespace CoreMLLabApp.iOS
{
    public class FriesOrNotFriesService : IFriesOrNotFriesService
    {
        private static VNCoreMLModel VModel { get; }

        static FriesOrNotFriesService()
        {
            // Load the ML model
            var assetPath = NSBundle.MainBundle.GetUrlForResource("e3e4e645c0944c6ca84f9a000e501b22", "mlmodelc");
            var friedOrNotFriedModel = MLModel.Create(assetPath, out _);
            VModel = VNCoreMLModel.FromMLModel(friedOrNotFriedModel, out _);
        }

        public Task<string> DetectAsync(byte[] image)
        {
            var taskSource = new TaskCompletionSource<string>();
            void handleClassification(VNRequest request, NSError error)
            {
                var observations = request.GetResults<VNClassificationObservation>();
                if (observations == null)
                {
                    taskSource.SetException(new Exception("Unexpected result type from VNCoreMLRequest"));
                    return;
                }

                if (observations.Length == 0)
                {
                    taskSource.SetResult(null);
                    return;
                }

                var best = observations.First();
                taskSource.SetResult(best.Identifier);
            }

            using (var data = NSData.FromArray(image))
            {
                var ciImage = new CIImage(data);
                var handler = new VNImageRequestHandler(ciImage, new VNImageOptions());
                DispatchQueue.DefaultGlobalQueue.DispatchAsync(() =>
                {
                    handler.Perform(new VNRequest[] { new VNCoreMLRequest(VModel, handleClassification) }, out _);
                });
            }

            return taskSource.Task;
        }

    }
}

byte[] から CoreML の入力として渡すための CIImage に変換して認識処理を呼び出しています。

動かして動作確認

ふむ。とりあえず動くっぽい。

f:id:okazuki:20170919224454p:plain

f:id:okazuki:20170919224507p:plain

あとは、DependencyService で Android や UWP の時には、CustomVision の API をたたくように仕込めば iOS だけ CoreML で他は REST API みたいなことが出来ますね。

ソースコードは以下に置いています。

github.com

Visual Studio Mobile Center の Push を試してみよう Android編

プッシュ通知ってめんどいですよね。 ということで Visual Studio Mobile Center の Push を試してみようと思います。Android, iOS, UWP あたりに対応してるらしいですが、とりあえず私の好きな Xamarin.Forms を使って Android に対して対応してみようと思います。

VSMS にプロジェクトを作成

これがないと始まらないのでさくっと作りましょう。

Android で Xamarin でさくっとね。

f:id:okazuki:20170918164931p:plain

設定とか

Push の項目を見てみると Firebase Console でアプリ作ってねっていう感じの説明があるので Firebase Console に移動します。

https://console.firebase.google.com/?hl=ja

とりあえずプロジェクトがないと始まらないみたいなので Firebase Console でプロジェクトを作成しましょう。

f:id:okazuki:20170918165510p:plain

作成後、左側のメニューから 成長 のところにある Notifications を選びます。そこから Android のアプリを作るボタンがあるのでさくっと作っちゃいましょう。

f:id:okazuki:20170918165727p:plain

Android パッケージ名は、これから作るアプリのパッケージと合わせておきます。ここでは jp.okazuki.pushlab.android にしました。

次の画面で google-services.json をダウンロードするように言われるので、これをダウンロードしておきます。あとで使うので。

f:id:okazuki:20170918170003p:plain

そして、Mobile Center と Firebase の間をつなぐ設定をします。これは、Firebase Console の左のメニューの上の方にある歯車マークを押してプロジェクトの設定を選択します。そして、画面上部のタブにあるクラウドメッセージングを選択して、そこにあるサーバーキーというものを使います。

f:id:okazuki:20170918170352p:plain

サーバーキーをゲットしたら、Mobile Center の画面に戻って Next を選択します。するとサーバーキーを入れる画面になるので、先ほど Firebase Console でゲットしたサーバーキーを入力します。Done を押すと完了です。

プッシュ通知が送れそうな雰囲気の画面になります。

f:id:okazuki:20170918170609p:plain

アプリの作成

では、サーバー側の構成が終わったのでクライアント側を作っていきます。 Xamarin.Forms のアプリケーションをサクッと作りましょう。

ここでは、PushLabApp という名前で作りました。

作ったら、ソリューションのNuGetパッケージの管理で Microsoft.Azure.Mobile.Push パッケージを PCL, Android, iOS, UWP のプロジェクトに追加しましょう。

f:id:okazuki:20170918172514p:plain

次に、先ほどダウンロードした google-services.json を Android プロジェクトに追加します。そしてビルドアクションを GoogleServicesJson にします。

Tips

GoogleServicesJson のビルドアクションが出ない場合は Visual Studio を再起動してみましょう。こういうの多いですよね。

アプリの作成続き

Android プロジェクトのプロパティで Android マニフェストで、パッケージ名に先ほど作成した Firebase Console のアプリで指定したパッケージ名と同じものを設定しましょう。

f:id:okazuki:20170918193737p:plain

f:id:okazuki:20170918185601p:plain

App.xaml.cs の OnStart メソッドに Push を有効化させるコードを書きます。

protected override void OnStart()
{
    MobileCenter.Start("android=a58a4c6f-1093-4bfd-a47b-2b3d877a56c6;" +
        "uwp={Your UWP App secret here};" +
        "ios={Your iOS App secret here}",
        typeof(Push));
}

uwp や ios は今後有効化させるとして置いときましょう。

AndroidManifest.xml の application タグの下に2つほど receiver タグを追加します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-sdk android:minSdkVersion="15" />
    <application android:label="PushLabApp.Android">
    <!-- ここから -->
    <receiver
      android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver"
      android:exported="false" />
    <receiver
        android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
        android:exported="true"
        android:permission="com.google.android.c2dm.permission.SEND">
      <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
      </intent-filter>
    </receiver>
    <!-- ここまで -->
  </application>
</manifest>

${applicationId} あたりは何か固定値入れるのかなと思わせつつそのままでいいみたいですね。

ビルドして動作確認

では、ビルドしましょう!ちなみにビルドエラー(java.exeが2を返すみたいな雰囲気のメッセージ)が出たら Android プロジェクトのプロパティの Android オプションにある Multi-Dex を有効にするをチェック入れましょう。

んで、実行してホームボタンを押してアプリをバックグラウンドに回します。

Send notification を押します。

f:id:okazuki:20170918192130p:plain

あとは、適当に項目を埋めて

f:id:okazuki:20170918192337p:plain

送信対象者を選びます。

f:id:okazuki:20170918192458p:plain

最後にプレビューが出るので Send notification を押しましょう。

f:id:okazuki:20170918192709p:plain

送信するとこんな感じでリスト形式で表示されます。

f:id:okazuki:20170918194118p:plain

アプリ側には、このような感じで通知がきます。(フォアグランドにアプリがあると来ないので気を付けてね)

f:id:okazuki:20170918194433p:plain

フォアグランドにあるときはどうするの?

Push きても通知が出るのがバックグラウンドだけだったらフォアグランドにあるときはどうしよう?って感じですよね。 その時は、Push.PushNotificationReceived イベントが発火します。ということなので、こんな感じにすればいいじゃん?ってことになりますよね。

protected override void OnStart()
{
    Debug.WriteLine("App.OnStart() called");
    MobileCenter.Start("android=a58a4c6f-1093-4bfd-a47b-2b3d877a56c6;" +
        "uwp={Your UWP App secret here};" +
        "ios={Your iOS App secret here}",
        typeof(Push));
    Push.PushNotificationReceived += this.Push_PushNotificationReceived;
}

private async void Push_PushNotificationReceived(object sender, PushNotificationReceivedEventArgs e)
{
    Debug.WriteLine(
        string.Join("\n", e.CustomData?.Select(x => $"{x.Key}, {x.Value}") ?? new[] { "" }));
    if (string.IsNullOrEmpty(e.Message))
    {
        return;
    }

    await this.MainPage.DisplayAlert(e.Title,
        e.Message,
        "OK");
}

protected override void OnSleep()
{
    Push.PushNotificationReceived -= this.Push_PushNotificationReceived;
}

ちなみに、Send notification の時に Custom data が設定できる画面がありましたが、これはイベント引数の CustomData プロパティにディクショナリで格納されています。とりあえずあったら適当にデバッグコンソールに出しておきましょう。

f:id:okazuki:20170918223413p:plain

あと、これは個人的に解せぬ動きなんですが、この PushNotificationReceived イベントはバックグラウンドにアプリがあるときに通知がきて、それをタップしたときにも呼ばれるんですよね。その時は、何故か CustomData は値が入っていて Title, Message が null みたいになってます。ちょっとびっくりした。

よくわからないんだけどこれも必要みたい

なんか、Android アプリ開発にそんなに明るくないせいか不勉強のせいかはじめて OnNewIntent なるメソッドを見ました。 なんだか Activity の launchMode が singleTop, singleInstance, singleTask の時は OnNewIntent メソッドを以下のようにしないといけないみたいです。ふーん。

protected override void OnNewIntent(Android.Content.Intent intent)
{
    base.OnNewIntent(intent);
    Push.CheckLaunchedFromNotification(this, intent);
}

あとは試してないんだけど

有効無効を切り替えれるらしい。

Push.SetEnabledAsync(false); // 無効
Push.SetEnabledAsync(true); // 有効

配信先の制御

今まで無差別に全員に対して Push 通知を送り込んできました。 ここらへんは、ある程度絞ることができるようになっています。まずは、MobileCenter.getInstallId(); でとってこれるインストールID指定で送る方法です。20人まで一気に遅れるみたいですね。当選者発表みたいなのとかに使うんだろうか?

f:id:okazuki:20170918224841p:plain

あとは Push の下にある Audiences でオーディエンスというものを作っておくとユーザーを条件つけて絞り込めるという機能もあります。

f:id:okazuki:20170918225815p:plain

ドキュメント上は Custom Properties を使ってきめ細やかな設定ができるということも書いてありますが UI 上設定の仕方がわかりませんでした。REST API を使ってやってる人がいたので、もしかしたらまだ UI が出来てないんですかね?

blog.cellenza.com

まとめ

ということで、割と簡単にプッシュ通知できるみたいですね。 そして興味を持った人はドキュメントを見てみましょう!

docs.microsoft.com

あと、Mobile Center 自体に興味を持った人で、がんがん使いこなしてみたいって人は、私はまだ見てないけど REST API も公開されてるようなので、それを使うと楽しいことが出来そうな気がしてます。

https://docs.mobile.azure.com/api/

ちなみに、こういう便利系サービス割と好きです。今回 Push をやるにあたって Firebase Console を見たけどこいつも色々出来そうですね。というか Push だけに限ると Firebase そのまま使ってもいいんじゃ?って思ったんですがどうでしょう。Firebase についてはこの資料好きです。

speakerdeck.com

Visual Studio Emulator for Android でネットワークにつなぐ

まぁ普通は標準のエミュレータ使いますよね。

でも世の中には Hyper-V が必須な人もいるでしょう。 そんな人は Visual Studio Emulator for Android を使うことになると思います。

ただ Visual Studio Emulator for Android では Marshmallow までしかエミュレータが用意されてないので悲しい気持ちになります。 N が来てないので O は個人的に絶望的なのではと思ってます。なので Hyper-V を常時 ON にしないといけないという制約がない人以外は標準の Android SDK についてくるエミュレータを使う方が幸せになれると思います。

Visual Studio 2017 のインストール時に個別のコンポーネントからチェックを入れることでインストールできます。

f:id:okazuki:20170917132423p:plain

さて、このままインストールして Visual Studio Emulator fro Android を立ち上げて Mashmallow の仮想マシンを適当に入れて起動したのですが、これだとインターネットにつながってませんでした。

ネットにつなごう

Hyper-Vマネージャー を起動します。仮想スイッチマネージャーをぽちっとします。 新しい仮想ネットワークスイッチを選んで外部で適当に作ります。

f:id:okazuki:20170917133736p:plain

で、VS Emulator 5-inch Marshmallow (6.0.0) XXHDPI Phone kaota みたいな感じの仮想マシンを右クリックして設定を押します。ハードウェアの追加で ネットワーク アダプター を選んで先ほど追加したネットワークスイッチを選択します。

これでエミュレータがネットワークにつながってくれるはずです。

f:id:okazuki:20170917134359p:plain

Xamarin.Forms のプロジェクトでフォルダパスが長すぎてエラーになってしまうときの対処法 その2

ちょっと前にこんな記事を書きました。

blog.okazuki.jp

コメントでジャンクション使ってみたらどうですか?と言われたので調べてみたら mklink コマンドってので作れるみたいですね。今回は、mklink コマンドを使って適当にシンボリックリンクを張る方法で試してみたいと思います。

ということで以下のようなコマンドをうってみました。

c:\>mklink /J Projects "c:\Users\kaota\Documents\Visual Studio 2017\Projects"
Projects <<===>> c:\Users\kaota\Documents\Visual Studio 2017\Projects のジャンクションが作成されました

c:\>mklink /J Repos c"\Users\kaota\Documents\Repos"
Repos <<===>> c\Users\kaota\Documents\Repos のジャンクションが作成されました

私は、上記2か所でリポジトリに突っ込まないコードとリポジトリに突っ込んでるコードを分けて管理してるのでこんな感じのコマンドになります。

プロジェクトを作ると無事作ってビルドできました。めでたしめでたし。

f:id:okazuki:20170917130542p:plain

ちなみに前に紹介した方法で作ったドライブは再起動したら消えてしまって悲しい気持ちになったのと UWP アプリケーションを起動が出来なかったりというのがあったのですが、こっちだと UWP アプリの起動もできたので、こっちのほうがいい感じかもしれない。

blog の引っ越しを考えてるのだけど何処がいいんだろう?

さて、私が blog を書き始めた頃はどの blog サービスがデファクトだ!!というのは意識していませんでした。

わんくま同盟というコミュニティで blog を作ってもらえるということで申し込んで作ってもらったのが私の blog 人生のはじまりになります。その後、hatena ダイアリーに移動して、hatena blog といった感じで流れて来ました。ということで基本的に世間一般で言われる blog サービスというものは hatena さんが運営するもの以外触ったことのがありません。

Hatena blog(現在の巣)

可もなく不可もなく。触っていて不満を感じることはありません。 最近のアップデートで何故か自分の記事に対して bookmark をはるためのショートカットが blog 記事投稿後に表示されたりと謎の進化を遂げている点と、https 対応がまだいつリリースされるのかわからないという点が気になります。

個人的に以下の点が気に入っています。

  • markdown が使える
  • なんだかんだいって規模はあるよね
  • プログラムのコードのシンタックスハイライトもあるので good
  • pro になると(課金すると)独自ドメインを割り当てたりできる
  • blog 書きに専念できる(プラットフォームのアップデートとか気にしなくてもいい)

気になってる点は以下です

  • 引っ越しって簡単にできないんじゃなかろうか
    • 画像まで含めて綺麗に引っ越しできるの?
  • https …
  • 最近のイケてるプラットフォームだという認識はない
  • 日本に閉じてる
    • あっ、私英語できないので別に困ってはないんですけどね

最近、使用者目線から見てイケイケな雰囲気を感じないのが気になってます。世間的にはそういうことはないのかな?気になる。

Qiita

コンセプトがそもそもプログラマのための技術情報共有サービスという点という時点で心強いです。個人的な印象でしかないですが、最近の若い人は、だいたい Qiita なのでは?と思ってしまうくらい色々なところで見かけます。

Qiita

記事の記述も markdown でいけるのでとてもいい感じだと思います。個人的に今プログラミング関連の blog をはじめるのだったらここなのだろうか?という雰囲気を感じてます。

シンタックスハイライトもあっていい感じですね。

medium

Qiita の他にもう1つ気になってるのが medium です。

medium

最近、ちらほら medium で blog 書いてる人を見かけます。なので気になったから調べて見たら、こういう記事も見つけてしまって「ん?」となっているところではあります。

Mediumがビジネス立て直しのため、日本でのオペレーションを終了

ただ、最近 Windows 10 Mobile を個人的にメイン機として使うのをやめようと思って iOS, Android に引っ越ししつつ iPad Pro(第1世代の小さいほう)を手に入れて何を思ったか開発環境を構築しようとして、色々頑張った(諦めました)ときにテキストエディタを探し回ったのですが Qiita や hatena は対応してるようなエディタは有名どころであまり見ない気がしたのですが medium はチラホラ見かけたような気がします。結局最終的に iA Writer を買ったのですが、こちらは medium への投稿機能があるんですよね。

ワールドワイドというか英語圏のサービスは、こういう世界的に有名なアプリでサポートされてたりするあたりが強いなぁと思いました。

ただ、組み込みでのシンタックスハイライトは対応していないみたいなので、そこらへんちょっとがっかりしました。gist とかの URL 貼ればいい感じにしてくれるみたいですが、餅は餅屋という発想なんですかね。

How to display code blocks in Medium

自前の wordpress

個人的には一番無いなと思ってる選択肢です。 ただ、ガチでセルフブランディングを考えてて他の人と差別化した blog サイトを作ることが目的の人には合致するんだろうなと思います。

私が blog を書く目的は

  • 自分用の備忘録
  • 他の人が同じことで困ってたときの助けになればいいな

というくらいなので、あまり blog のメンテナンス作業に時間を割かれるのは好きじゃ無いとうことなので wordpress を自分で建てたときに発生する wordpress のバージョンアップだとかサーバーのお守りだとか(Microsoft Azure App Serviceに立てればサーバーのお守りはしなくていいけど)そういう類のものに時間を割きたく無い!!

まとめ

結局どこに行くのがいいんだろうか?? という記事を試しに hatena blog, qiita, medium に投稿して使い勝手を試してみようと思ったのですが qiita はポエムを置く場所ではないということを思い出したので hatena blog と medium に書いて置くのでした。

Emotion API でビデオ分析機能を呼ぶ方法

画像を投げ込むパターンはよくあったのですがビデオの情報がなかなか見つからなかったのでメモ。

var emotionClient = new EmotionServiceClient("key");

var result = await emotionClient.RecognizeInVideoAsync(<ここにstreamを渡す>);
// 分析をポーリングする
VideoOperationResult operationResult;
while (true)
{
    operationResult = await emotionClient.GetOperationResultAsync(result);
    if (operationResult.Status == VideoOperationStatus.Succeeded || operationResult.Status == VideoOperationS
    {
        break;
    }

    await Task.Delay(15000);
}

// 成否を確認
if (operationResult.Status == VideoOperationStatus.Failed)
{
    task.Message = $"感情分析に失敗しました: {operationResult.Message}";
    return;
}

// 結果をVideoOperationInfoResult<VideoAggregateRecoginitionResult>にして色々やる
var r = (VideoOperationInfoResult<VideoAggregateRecognitionResult>)operationResult;
// Fragmentsで認識結果を確認できる
r.ProcessingResult.Fragments...

Xamarin.Forms のプロジェクトでフォルダパスが長すぎてエラーになってしまうときの対処法

続編書きました。

blog.okazuki.jp

最近 Xamarin.Forms のプロジェクトを新規作成したあとにビルドエラーになるというかプロジェクト作成すらままならないという状況に出会うことが増えました。

まぁ本質的にはパスの長さの問題なので別にXamarinに限った話ではないのですが辛いところですね。 (Windows 10の最新バージョンではグループポリシーエディターでパス長の制限解除できるけど、それがVS2017で有効になるのかは知らない)

とまぁTwitterで愚痴ったところ、私以外にも起きてるという人がいるということなので共有しておきます。

なんか色々なパターンがあるのですが、例えばちょっと長めのプロジェクト名をつけてデフォルトのC:\Users\<username>\Documents\Visual Studio 2017\Projects以下に作成しようとするとこんな感じのメッセージが出たりします。

---------------------------
Microsoft Visual Studio
---------------------------
サブ プロジェクト 'LongLongPathApplicationSample.Client.UWP' の作成中にエラーが発生しました。ファイル名または拡張子が長すぎます。 (HRESULT からの例外:0x800700CE)
---------------------------
OK   
---------------------------

対処法1

とりあえず短いパスのフォルダに作るようにする。

まぁパスが長いのが問題ですからね…。でもデフォルトのパスを出来れば使いたい。

対処法2

ということなので以下のようなコマンドをうってみました。

subst d: C:\Users\kaota\Documents

これでDドライブがドキュメントフォルダになります。そして、Visual Studio 2017でDドライブの下のVisual Studio 2017\Projectsにプロジェクトを作ると無事成功!!

とはなりませんでした。

重大度レベル   コード   説明  プロジェクト  ファイル    行 抑制状態
エラー       "ResolveLibraryProjectImports" タスクが予期せずに失敗しました。
System.IO.PathTooLongException: 指定されたパス、ファイル名、またはその両方が長すぎます。完全限定型名は 260 文字未満で指定し、ディレクトリ名は 248 未満で指定してください。
   場所 System.IO.Directory.InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, Boolean checkHost)
   場所 System.IO.Directory.InternalCreateDirectoryHelper(String path, Boolean checkHost)
   場所 System.IO.Directory.CreateDirectory(String path)
   場所 Xamarin.Android.Tasks.ResolveLibraryProjectImports.Extract(DirectoryAssemblyResolver res, ICollection`1 jars, ICollection`1 resolvedResourceDirectories, ICollection`1 resolvedAssetDirectories, ICollection`1 resolvedEnvironments)
   場所 Xamarin.Android.Tasks.ResolveLibraryProjectImports.Execute()
   場所 Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   場所 Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()   LongLongPathApplicationSample.Client.Android            

まだ長いのか…。ならばこうだ

subst /D d:
subst d: "C:\Users\kaota\Documents\Visual Studio 2017\Projects"

開きなおして実行すると、やったね!!

f:id:okazuki:20170908175733p:plain

まとめ

緩募。もっといい方法とかあれば。

React Native でプロジェクトを作って実機で画面確認まで

最近ご無沙汰してたReact Nativeですが、久しぶりにインストールしてみました!

node.js を入れる

これがないと始まらないですよね。最近のJavaScript界隈。

Node.js

create-react-native-app を入れる

npm i -g create-react-native-app

これでプロジェクトのひな形作ってくれるコマンドが入ります。

expo を入れる

なんか、気軽にアプリをデバッグ実行するためのものみたいですね。ありがたや。

expo.io

開発母艦にアプリを入れたらデバッグ用端末にもストアから expo のクライアントアプリを入れます。

yarn を入れる(入れなくてもいいかもしれない?)

2017/09/02 時点では npm 5 では create-react-native-app がうまく動きません。なのでかわりにyarnを入れます。

npm i -g yarn

プロジェクトを作る

ではさくっとプロジェクトを作ってみましょう。

create-react-native-app hello-react-native

のようにコマンドのあとにプロジェクト名をつけてうつとサクッと作ってくれます。

yarn start

これで expo 使っていつでもアクセスできるようになります。

Expo XDEを立ち上げるとこんな感じに表示されます。

f:id:okazuki:20170902205111p:plain

Shareを押すとQRコードとか出てくる。これをモバイルのexpoアプリから読み込めば動き始めます。 ただ、注意点としては同じネットワークにいないとダメってことですね。

あと、このQRコードのIPアドレスはどういうルールでとってこられてるのかわからないのですが、ローカルのネットワークにつながってるやつじゃないのが出てくることもあるみたいです。Hyper-Vのインターナルな奴?のネットワークのIP拾ってきてました。

なので ipconfig /all あたりでIPアドレスを確認して直打ちしました。

実行結果

こんな感じに画面が出ればとりあえず開発環境は整いました!あとはやっていくだけや!

f:id:okazuki:20170902210810p:plain

Reactで開発するときに使えるかっこよさそうなコンポーネント ANT DESIGN

知らなかったんですが ANT DESIGN というのがあるんですね。

ant.design

React のコンポーネントも実装されてていい感じかも。

今までは、Material-UIを何かあったら使おうと思ってたけど、今度何かやるときには ANT DESIGN も評価してみてもいいかもというメモでした。

中国の方が作ってるのかな?GitHubを見る限り。