眠いしお腹すいたし(´・ω・`)

C#関連を主に書きます。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

ついぶくテストにご協力いただいている方へ

ごあいさつ

クリスマスイブですね\(^o^)/

本題

仕様変更に関して

ついぶくテストにご協力いただいている皆様、本当にありがとうございます。

この度まとめツイートをツイートする方法を変更いたします。

twitter.com

こちらのアカウントよりユーザ様へメンションツイートにてまとめツイートを行います。

いったんユーザ様へメンションツイートを行い拡散を行うかはユーザ様に判断して頂きRTを行ってください。

この変更はついぶくアカウントをフォローした場合に適用されます。

フォローを行わなかった場合には、これまでと同様にユーザ様のツイートとしてまとめツイートを行います。

変更理由

7時に一斉にまとめツイートを行うという仕様はTLを荒らしがちになってしまうため。

以上、よろしくメリークリスマス('ω')ノ🎁🎄

ついぶくを公開しました。

ごあいさつ

断捨離が全然進みません(´・ω・`)

ついぶく

私事で大変恐縮なのですが

このたび「ついぶく」というサービスを試験リリースいたしました。

どういうサービスかと言いますと

1日のツイートの中からリンクを抽出してまとめページを作成してくれるサービスです。

サービスに参加すると朝7時頃にこのようなツイートが行われます。

でリンクに飛んでみてもらえればわかるのですがツイート中からリンクを抽出し簡単にまとめてあります。

これだけのサービスです。

作成の経緯

理由1

私は結構ツイ廃なので1日に沢山ツイートします。

その中には技術的な調べ物をしていてそのリンクをツイートしたりしたものも含まれてます。

そんな中で1日単位くらいでまとめておけると楽だなぁというのが1つ目の理由です。

理由2

それだけだとはてブを使用すれば良いのですが

例えば

キュレーション活動としてフォローしている方に定期的に公開したいようなケースでははてブは少し使いづらいかな、という面があります。

ということでただツイートしていれば自動でまとめてくれるサービスがあったらなぁと思ったのが2つ目の理由です。

理由3

現在はWebフロントエンド技術の知識更新作業を行っているので勉強用にサービスを作りたかった。

Azure Functionsの勉強をするためにFunctionsを使用するサービスを作りたかった。

クラウド環境でのサービスデプロイに関して勉強するためにサービスを作りたかった。

以上の理由によりサービスの作成を行っています。

試験に協力して頂けるユーザさんを募集しています。

現時点で試験段階です。10人程度ユーザさんが使っていただけれるとうれしいかなぁとか思っています。

ただまだまだプログラム書いただけ~みたいな段階ですので色々と不具合も出てしまうかもしれません。

よく記事等のリンクをツイートされる方で協力して頂ける方がおりましたら、以下のサイトから登録してくれると嬉しいです。

ついぶく登録

https://yukasantestnet.azurewebsites.net/

こちらのサイトに移動するとツイッター認証画面が表示されます。

認証して頂いた後に設定画面に移動して「使います」ボタンを押していただければ登録が完了します。

以上、久々にプログラムがないブログ更新でした('ω')ノ

Azure Mobile Appsの.NETバックエンドでMVCを同居させてみよう🍣=3

ごあいさつ

衣類乾燥機が今すぐ欲しいのです(´・ω・`)

本題

はじめに

Azure Mobile Appsの.NET バックエンドはASP.NET Web APIがベースとなっていてMVCを追加できません。

f:id:tamafuyou:20161216003610p:plain

でもMobileAppでもMVC使えるようにしたいですよねぇ。

ほらアプリの入口はやっぱりブラウザが多いと思いますし私がいま取り組んでいる課題で必要ですし。

ということで、Mobile AppでMVCを使えるようにしてみます。

前提

Mobile Appの.NET バックエンドプロジェクトをVSで作成してAzureにデプロイできている状態まで出来ている事を前提とします。

docs.microsoft.com

この辺を参考にすればすぐにできるかと思います。

コントローラーを追加する

Controllersフォルダに空のMVC5コントローラを追加します。

今回はPageControllerという名前にしてみました。

するとASP.NET MVCを構築するためのファイルが勝手に展開されます。

f:id:tamafuyou:20161216010937p:plain

Viewを追加する

f:id:tamafuyou:20161216011118p:plain

Viewを追加しちゃいます。

ルーティング設定を変更する

デフォルトコントローラ名を指定します。

これを行うとドメイン名のみのURL指定時のコントローラを指定できます。

f:id:tamafuyou:20161216011335p:plain

MobileAppのスタートアップを変更する

今回の肝の部分です。

現在の状態でデバッグをスタートするとこのページが表示されると思います。

f:id:tamafuyou:20161216011640p:plain

これはMobileAppのライブラリが表示しているページです。

このページを表示されないようにしMVC側のルーティング設定が適用されるようにします。

App_Start下にあるStartup.MobileApp.csを開きConfigureMobileApp関数をこのように変更します。

gist.github.com

どういう意味かというと

UseDefaultConfigurationというMobileAppConfigurationに対する拡張メソッドを分解しAddMobileAppHomeControllerという拡張メソッドを呼ばないようにしています。

AddMobileAppHomeContollerによってMobileAppの機能に関係ないルーティングが設定されてしまうためです。

これにより

f:id:tamafuyou:20161216012952p:plain

デバッグ実行すればPageコントローラのIndexがコールされIndexページが表示され、この状態でもMobileAppのAPIは正しく動作しているかと思います。

ではでは('ω')ノ

Prism.FormsでランダムにNavigationが変わるアプリを作ってみた(^^)/

こちらの記事は

qiita.com

8日目の記事になります。

初心者枠ということでお手柔らかにお願い致します。

Xamarin.Formsのナビゲーション

developer.xamarin.com

Xanarin,FormsのNavigationには大きく分けて4種類あります。

  1. NavigationPage
  2. MasterDetailPage
  3. TabbedPage
  4. CarouselPage

NavigationPageは非常にシンプルで1本道なナビゲーションです。

それに対してTabbedPage / CarouselPageはPageを横に並べます。

MasterDetailPageはMasterPageでページを選んでDetailにPageを表示するようなNavigationが可能です、

一般的に標準的なアプリにおいてiOSはTabナビゲーション、AndroidはMasterDetailが採用されていることが多いです。

これは各プラットフォームの推奨デザインによります。

同じアプリでもプラットフォーム毎にナビゲーションを最適化しておく事は大切です。

Xamarin.Formsはクロスプラットフォームで同じアプリを作る仕組み・・・・

ナビゲーションを簡単に変更するなんて出来ないんじゃないの・・・・?

そんなお考えのそこのあなた(; ・`д・´)m9

今回ご紹介する方法ならできるんです\(^o^)/

それでは方法をご紹介してみましょう。

Prism.Formsの利用

今回のサンプルではPrism.Formsを使用します。

Prism.FormsはMVVMライブラリでかなり巨大なライブラリになります。

Prismに関して、なにそれ美味しいの?という方は

www.nuits.jp

こちらをご覧ください、

はじめに

考え方

TabbedPageを右に90度回転させるとMasterDetailっぽくありません?

そういう事です。

二つのアプローチ

  1. TabbedPageを継承してCustomRendererでMasterDetailのような見た目のNavigationを作成する。

  2. MasterDetailPageを継承してTabbedPageに近いインターフェースと仕組みを持ったクラスを作成する。

1番が理想形です。が・・・すいません。完成しませんでした・・・

今回は2番のアプローチで作成を行います。

プログラム

今回のサンプルプログラムはこちらになります。

github.com

MasterDetail拡張

Prism.Forms_NavigationSample/TabbedMasterDetailPage.cs at master · yuka1984/Prism.Forms_NavigationSample · GitHub

gist.github.com

MasterDetailクラスを継承し更に IViewContainer、IPageContainer、IItemsViewを追加します。

この3つはabstractクラスであるMultiPageのインターフェースです。MultiPageはTabbedPageのベースクラスです。

実際には今回の範囲ではこのインターフェースを持つ必要はないのですが形だけでも似せるために実装しています。

MasterPageにはListViewをおいてChildrenと結び付けを行っています。

Childrenが選択された場合にはDetailに該当ページをNavigationPageに包んでセットします。

そのほかChangePageなどを実装しています。

PageNavigationServiceの拡張

Prism.Forms_NavigationSample/CustomPageNavigationService.cs at master · yuka1984/Prism.Forms_NavigationSample · GitHub

本来であればPrism.FormsのPageNavigationServiceを継承してカスタム、という形にしたかったのですが期待する動作をさせるためにはどうしても無理であったためPrism.Formsのコードを持ってきてカスタマイズを行いました。

変更点は先ほど作成したTabbedMasterDetailPage用の処理関数ProcessNavigationForTabbedPageを追加し呼び出されるようにしたことです。

この関数の中身自体はTabbedPage用の関数とほぼ同じです。

先ほど説明した2つのアプローチの1番であればNavigationServiceをカスタマイズする必要はなく、そういういみでもアプローチ1は理想形と言えます。

Appクラス

Prism.Forms_NavigationSample/App.cs at master · yuka1984/Prism.Forms_NavigationSample · GitHub

gist.github.com

Appクラスはこのように実装しています。

あまり良い実装ではないです。

RegisterTypesにてランダムにNavigationPageを登録しています。

この時に名前をRootPageという名前で登録することでawait NavigationService.NavigateAsync("RootPage/Content2");というように指定することができます。

ここまでの実装によりMasterDetailな見た目だけどロジック的にはTabbedPageと共通で実装することができました。

終わりに

Xamarin.FormsはMVVMパターン・・・みたいに言われることがあるのですがなんか違う気がしてきています。

というよりMVVMってなんだろう。MVVMとはいったいなんだろう・・・・なんなんだぁ(/・ω・)/

MVVMを考えるときにNavigationを入れちゃだめだ(;^ω^)

clean architecture Reactive・・・・

:(´◦ω◦`):

Xamarin.FormsのPCLプロジェクトを.NET Standardライブラリプロジェクトにしてみた(*'▽')

はじめに

本記事は

qiita.com

の4日目の記事になります。

あいさつ

今年は既にXamarin最前線から退いてしまっているのでAdventCalendarへの参加は見送ろうと思っていたのですがXamarin Adventalendarの枠が4枚目のカレンダーに余っていたのでコッソリと投稿することにしてみました。

初心者枠という事でお手柔らかにお願いします。

今年は公私共に色々なことに関してある程度目標を達成することができて良かったです。

来年は今年以上に忙しくなるかもしれないので頑張っていかねばと思います。

なお去年に引き続き今年も一人ぼっちのクリスマスです('◇')ゞ

.NET Standardねぇ

未だにいまいち浸透していないように思える.NET Standard・・・

docs.microsoft.com

同時期に.NET Coreというワードが登場し、浸透する前に.NET Standardというワードが出てしまった為に余計にごちゃごちゃしてしまったなぁという印象です(´・ω・`)

各用語に関して

私の中ではこんな感じで考えてます。

PCL・・・クロスプラットフォームなライブラリを実現するために使いたいプラットフォームの公約数APIのみを使用できるライブラリ作成環境。使用できる.NET FrameworkAPIは使いたいプラットフォームによって増減する。

.NET Core・・・.NET FrameworkのサブセットでWindows Linux Mac等のクロスプラットフォーム環境で使えるフレームワーク。Monoベースでない点が重要でMonoは.NET Framework互換であったのに対して.NET Coreは.NET Frameworkのサブセット。.NET Coreをベースに作られたフレームワークASP.NET Coreがある。あと.NET Coreベースのコンソールアプリも作れる。.NET CoreにプラットフォームAPIを足してできているのがUWPかな?

.NET Standard・・・プラットフォーム関係なくAPIセットという形で.NET Foundationが定義したクラスライブラリ環境。概念としてはプラットフォームには非依存。現在1.0~1.6まであるがバージョンが上がるごとに使えるAPIが増えていく。1.3までは下位互換のバージョンであって.NET Standardの本質は1.4以降と思う。1.4以降のバージョンは.NET Framework/.NET Core/Xamarin/UWPの進化に対してAPIを調整したバージョンと考える。要するにこれまでと同じ環境で作る分にはPCLから変更する必要がないけれど、今後.NET基盤の進化に対応していく為には,NET Standardに乗り換えておかないと不便になる。ということだと思う。たぶん(;'∀') 1.4以降であっても最小APIセットは.NET Coreとなるので.NET Core以上に使えるAPIが増えることはない。

nugetの方ではPCL用が用意されいた主要なライブラリは概ね.NET Standardに対応してきたのかなというイメージです。

Xamarin.Formsと.NET Standard

Xamarin.Formsの共有プロジェクトに関してはAndroid/iOSのみであればSharedも考えられるがUWP/Tizenまで入れるとPCLにすることが現状の定石じゃないでしょうか?

PCLを.NET Standardプロジェクトに変更することは現時点でメリットは特にありません。

メリットがあるとすれば共有プロジェクトのcsprojの中身がきれいになってnugetでのライブラリ設定がproject.json記述になることで操作しやすくなる??

ですがこの先.NET StadardのAPIセットが進んでいく中ではメリットが生まれる事もあるかと思います。

直近ではvNextでしょうか。

今回はXamarin.FormsプロジェクトのPCLを.NET Standardに変更する手順を記したいと思います。

手順

今回の環境はVisual Studio 2015 Update3にて行っています。

プロジェクトを作る

まずはXamarin.FormsのPCLプロジェクトを作成します。

f:id:tamafuyou:20161203073306p:plain

こんな感じのソリューションが出来上がるかと思います。

f:id:tamafuyou:20161203073430p:plain

PCLプロジェクトからXamarin.Formsパッケージを一度外す

PCLプロジェクトのnugetマネージャーを開いてXamarin.Formsパッケージをアンインストールしてしまいます。

Xamarin.Formsのバージョンは覚えておいてください。

f:id:tamafuyou:20161203073611p:plain

PCL -> .NET Standard

PCLプロジェクトのプロパティを開いてTarget .NET Platform Standardを選択します。

f:id:tamafuyou:20161203074645p:plain

ダイアログが出てくるので「はい」を選択してください。

こんな感じに画面が変わるかと思います。

f:id:tamafuyou:20161203074858p:plain

Xamarin.Formsを追加する。

プロジェクトにproject.jsonが追加されていますので開きます。

f:id:tamafuyou:20161203075103p:plain

project.jsonをこう書き換えてください。

{
  "supports": {},
  "dependencies": {
    "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
    "NETStandard.Library": "1.6.0",
    "Xamarin.Forms" :  "2.3.3.168" 
  },
  "frameworks": {
    "netstandard1.1": {
      "imports": "portable-net45+win8+wpa81+wp8"
    }
  }
}

Xamarin.Formsのバージョンはアンインストールしたバージョンと同じものにしてください。

これで.NET Standardへの移行が終わりましたので実行できる状態になっていると思います。

この例ではプロジェクトにWindows8.1やWindowsPhoneプロジェクトが入っているので.NET Standard1.1になっています。

これらが必要なくAndroid/iOS/UWPであれば1.4 Android/iOSであれば1.5にあげることができます。Tizenはよくわかりませんが,NET CoreベースということなのでAndroid/iOS/Tizenであれば1.5が可能かと思います。

1.6も本来は可能なはずなのですが、どうもバグっぽい挙動でうまくビルドができません。

github.com

まだVS2017 RCでは.NET Standard 2.0はまだ使えないのですかねぇ。

いまいちVS2017への関心が高くなくて現状調べていません(´・ω・`)

以上、ありがとうございました。

Xamarin.iOSでゆっくりボイスを喋らせてみた(*'▽')

ごあいさつ

今使っているMacBookProが2010年モデルでメモリが4GBしかありません。

ちなみに来月が誕生日です。

・・・・・・・('ω')・・・・・・・・・

tamafuyou.hatenablog.com

前回の記事に引き続き、今回はXamarin.iOSでゆっくりボイスをしゃべらせてみます。

作ってみる。

開発環境

Mac + XCode8.1 + Xamarin Studio 6.1.2

今回の開発はMacが必須です。

もしMacを持っていない・・・という事であれば

www.nuits.jp

MacinCloudを使うことでプログラムはできますが音が出ないのでゆっくりボイスを聞けません(´・ω・`)

サンプルプログラム

github.com

今回作成するプログラムはこちらのリポジトリに保存してあります。

ダウンロード

http://www.a-quest.com/download/index.html

AquesTalk iOS 1.6.2 をダウンロードしてください。

f:id:tamafuyou:20161125174803p:plain

libファイルの中にあるヘッダファイルとライブラリファイルを使用します。

プロジェクト作成

まずはプロジェクトを作成します。

f:id:tamafuyou:20161125180114p:plain

iOSのSingle View Appを使用します。

f:id:tamafuyou:20161125180939p:plain

名前は適当で良いかと思います。

アプリの ソリューションをを作成できましたら次はバインディングライブラリ用のプロジェクトをソリューションに追加します。

f:id:tamafuyou:20161125181250p:plain

iOSのLibraryにあるBindingLibraryを作成してください。

名前は適当で良いです。AquesTaklLibとしました。

f:id:tamafuyou:20161125182720p:plain

そうしたらアプリプロジェクトにてバインディングライブラリを参照追加してください。

これでとりあえずソリューションとプロジェクトの準備が完了です。

Objective Sharpie

これは参考までにということで・・・

developer.xamarin.com

iOSライブラリへのP/Invokeを行うC#クラスを作成してくれるツールがObjective Sharpieです。

ヘッダファイル、Frameworkを元に作成することができます。

ただあまり精度が良くありません。複雑でない関数を5,6個という事であればヘッダファイルをみながら自分で関数を書いた方が早いです。

今回もObjectiveSharpieは試してみましたが良い結果は得られなかったため自分でP/Invokeを書きました。

バインディングライブラリ

先ほど作成したバインディングライブラリにaファイルを追加します。

すると

f:id:tamafuyou:20161125185607p:plain

こんな風にLinkWithファイルができていると思います。

このLinkWithファイルを開きLinkWithAtributesにIsCxx=trueとする指定を追加します。

IsCxxフラグはNativeライブラリにC++が使用されている場合に指定します。

次にP/Invokeするクラスを追加します。

ヘッダファイルを参考にこのようなクラスを作成しました。

AquesTalk_Xamarin_Sample/StructsAndEnums.cs at master · yuka1984/AquesTalk_Xamarin_Sample · GitHub

P/Invoke用に関数を書くときのポイントとしては

  • 値型は長さに気を付けてそのまんま
  • ポインタ型はIntPtrにしておけばOK

って感じです。

アクセスをinternalにしているのは外部からアクセスさせないためです。

なのでラッパークラスを作成します。

AquesTalk_Xamarin_Sample/AquesTalk.cs at master · yuka1984/AquesTalk_Xamarin_Sample · GitHub

ラッパークラスとしてはあまり良いとは言えない手抜きなので参考程度にお願いします。

stringをエンコードしてbyte配列にした上でMarshalでIntPtrにして渡しています。

アプリ

ダウンロードしたzipファイルに付属されているサンプルアプリをベースに作成します。

まずは画面を作ります。

まずはサンプルアプリのmain.storyboardファイルをxamarinプロジェクトの物と入れ替えます。

そのまま入れ替えてしまえばOKです。

そうしたらMain.Storyboardを開きplayボタン、stopボタンをダブルクリックしてViewControllerクラスにクリック時の呼び出し関数を追加します。

サンプルアプリのObjective-Cで書かれたViewController.mファイルを参考にViewControllerクラスを作成します。

AquesTalk_Xamarin_Sample/ViewController.cs at master · yuka1984/AquesTalk_Xamarin_Sample · GitHub

ほぼそのまんまです。

1点ポイントとしては、NsNotificationによるコールバック関数コールはUIスレッドで実行されていないようなのでLabelのTextを変更する際にUIスレッドで処理するようにしないエラーになる。

というくらいです。

それにしてもXamarinがほんとに良いです。

Objective-CであろうとSwiftであろうとJavaであろうとネイティブのコードを参考にほとんど迷いなくC#に移植することができます。

逆にXamarinで作成してあるアプリをNativeに持っていくこともできると思います。あまり意味はないと思いますが・・・

次回はXamarin.Formsでゆっくりボイスを・・・・という事を考えていたのですが実はうまくないのです。

XFってAndroidのAPI15移行に対応しているんですがAquesTalkの評価版はarmeabiしかsoファイルが無いのでエミュレータが用意できないのです。

API15だとarmeabi-v7aになってしまうのです。

なので開発ライセンス買うしかないのです。XFで使えるか評価したかったのですが残念です。

ですので株式会社AQUEST AquestTalkを使用したゆっくりボイスをXamarinで喋らせてみるシリーズは終了です。

AquesTalkの開発ライセンスは

使用ライセンス - AQUEST オンラインストア

こちらで購入することができます。

ではでは('ω')ノ

Xamarin.Androidでゆっくりボイスを喋らせてみた( *´艸`)

ごあいさつ

先週は頭に霧がかかったみたいにずっとモヤモヤしていたのと吐き気で物が食べられなくて大変でしたが、金曜日にとあるエンジニアの方々とお話しする機会がありまして色々と意見をもらえた事と、私自身が現状の何が嫌なのかがハッキリしてとてもスッキリしたことが相まって調子が回復いたしました。

ですのでおうちプログラムをしてみました。

きっかけ

この間Xamarin Dev Daysの課題アプリで音声読み上げがあったのですが、日本で音声読み上げといえば・・・

ゆっくりしていってね!!!

ゆっくりボイス

ゆっくりしていってね!!!

でおなじみゆっくりボイスは

dic.nicovideo.jp

softalkという音声読み上げソフトが読み上げる独特な音声です。

SoftalkAquesTalkというライブラリを使用して作られています。

このAquesTalk Android用ライブラリ、iOS用ライブラリがあるんです。

ということは~~

なんとかすればXamarinでも使えるのではないでしょうか?

ということで まずはAndroidでゆっくりボイスをしゃべらせてみましょう

ダウンロード

まずは評価版のライブラリをダウンロードしてきます。

http://www.a-quest.com/download/index.html

このAndroidの評価版は二つの制限があるそうです。

  1. 「ナ行、マ行」を指定すると、すべて「ヌ」と発声します
  2. armeabi用だけで、x86mips用のライブラリは含まれません

とくに二つ目の制限が結構きついです。

armeabi-v7aではありません。 armeabi用のsoファイルしか用意されていないのです。

v7aでは無いということはAndroid 2.3辺りということです。

AQUEST様、さすがにv7aじゃないarmeabiはつらいです。

今どきのエミュレーター事情を考えるとx86用を評価用に用意してもらえると嬉しいです。

zipファイルを展開すると

  • soファイル
  • NativeLibrary呼び出しクラスサンプル(.java)
  • サンプルアプリプロジェクト

が入っています。

今回はXamarin Androidで Samplesの中にあるAqTkAppというアプリを作ってみたいと思います。

サンプルプロジェクト

github.com

こちらのリポジトリに今回作成したアプリを載せました。

詳しくはこちらをご覧ください。

  • なお、こちらのリポジトリにはsoファイルは入っていません。*

作成

プロジェクト作成

Xamarin.Androidプロジェクトを普通に作ってください。

プロジェクトへSOファイルを追加する

NativeLibraryを使用するため

f:id:tamafuyou:20161121214850p:plain

このようなフォルダ構成でsoファイルをプロジェクトに追加します。

f:id:tamafuyou:20161121215012p:plain

追加したsoファイルのビルドアクションをAndroidNativeLibraryに変更します。

Layoutとstringsを作成する

f:id:tamafuyou:20161121215227p:plain

参考元のプロジェクトのmain.xmlファイルをそのままコピーしてきます。

strings.xmlもそのまんま丸写しで大丈夫です。

f:id:tamafuyou:20161121215650p:plain

こんな感じになるかと思います。

AquresTalkクラスを作成する

今回の核心部分です。これで3日も悩みました。

当初soファイルを追加したのでP/Invokeで直接soファイルの関数を呼び出せばよいのだろうと考えていたのですが、どうしてもうまくいきませんでした。

2日頑張ってNativeメソッドのコールまでは出来ていそうな感じになったのですがエラーでアプリが落ちてしまってどうしても原因がわかりませんでした・・・

ですので今回はNativeLibraryのメソッドをコールするjavaクラスを追加して、そのクラスへのバインディングクラスを作成してコールする形式をとってみました。

f:id:tamafuyou:20161121221708p:plain

まずはjavaファイルをプロジェクトに追加してビルドアクションをAndroidJavaSourceに変更します。

package aquestalk;

public class AquesTalk {
    static {
        System.loadLibrary("AquesTalk");
    }
    /**
    * 音声記号列から音声データを生成します。JNI実装(native修飾子)
    * <p>発話速度は通常の速度を100として、50 - 300 の間で指定します(単位は%)。</p>
    * @param kanaText 音声記号列(UTF-8)
    * @param speed 発話速度(%)
    * @return wavフォーマットのデータ
    */
    public synchronized native byte[] syntheWav(String kanaText, int speed);

}

中身はこんな感じです。

次にバインディングクラスを作成します。

作成したクラスはこちらです。

AquesTalk_Xamarin_Sample/AquesTalk.cs at master · yuka1984/AquesTalk_Xamarin_Sample · GitHub

Working With JNI - Xamarin

このあたりのサンプルコードをベースに作成しました。

ちょっと悩んだのはこの関数です。

        [Register("syntheWav", "(Ljava/lang/String;I)[B", "GetsyntheHandler")]
        public virtual unsafe byte[] synthe(string kana, int speed)
        {
            if (id_syntheWav == IntPtr.Zero)
                id_syntheWav = JNIEnv.GetMethodID(ClassRef, "syntheWav", "(Ljava/lang/String;I)[B");
            try
            {
                var ptr = IntPtr.Zero;
                if (GetType() != ThresholdType)
                    ptr = JNIEnv.CallNonvirtualObjectMethod(Handle, ThresholdClass, JNIEnv.GetMethodID(ThresholdClass, "syntheWav", "(Ljava/lang/String;I)[B"), new JValue(new Java.Lang.String(kana)), new JValue(speed));
                else
                    ptr = JNIEnv.CallObjectMethod(Handle, id_syntheWav, new JValue(new Java.Lang.String(kana)), new JValue(speed));
                return JNIEnv.GetArray<byte>(ptr);
            }
            finally
            {
            }
        }

RegisterAttributeの第2引数、JNIEnv.GetMethodIDなどでメソッドのシグネチャを指定する必要があります。

要するにメソッドの形ですね。

Determine the signature of a method - Real's Java How-to

このページが例がついててわかりやすいです。

今回のメソッドは byte[] syntheWav(String kanaText, int speed)なので (Ljava/lang/String;I)[Bとなるわけです。

そして関数の実行と戻り値の受け取りはJNIEnv.CallxxxMethidを使用します。

JNIEnvクラスにはintとか単純な方はCallintMethodみたいな感じでコール用の関数が用意されているのですが戻り値が配列の場合には

CallObjectMethiodを使用してIntPrtを受け取りJNIEnv.GetArrayで配列に変換します。

MatinActivityを作成する

Javaで書かれているMainActivityクラスをC#に移植します。

単純作業でよいと思います。

AquesTalk_Xamarin_Sample/MainActivity.cs at master · yuka1984/AquesTalk_Xamarin_Sample · GitHub

実行

評価版はsoファイルがarmeabi用だけしかないのでAVDでarmeabiのバーチャルデバイスを用意します。

f:id:tamafuyou:20161121224415p:plain

Android2.3にて作成する必要がありAPIレベルが10になってしまいますのでプロジェクトのMinimum Android to Targetを変更します。

f:id:tamafuyou:20161121224612p:plain

以上で実行すれば ゆっくりしていってね!!!ってしゃべると思います。

以上、次回はXamarin.iOSゆっくりしていってね!!!ってしてみたいと思います。