えむにわリソース

ITのスキマ的なあれこれを書きます。

Xamarin.FormsのAndroidアプリでDebug実行時エラーが出る問題(対処のみ)

Xamarinを使ったアプリ開発で、
まっこと初見殺しな実行時エラー事案にぶつかったので、
対処法とかを共有します。

起こった事象

開発中に System.NullReferenceException エラーに襲われる
f:id:m2wasabi:20170216221315j:plain

調査するもソースコードにエラーは見つからず、
ビルドしてDebugを実施、デプロイに成功するも実行時に System.NullReferenceException で落ちる。

Releaseビルドだと正常に動く。

結論

デバッグライブラリを消せば動く

解決方法

以下のいずれか

  • プロジェクトでインストールしたアプリをいったんすべて消す
  • エミュレーターなら初期化や作り直しでも良い

原因

残念ながら原因の特定には至っていません。
あるビルドから突然 Android用プロジェクトの MainActivity.csbase.Oncreateが認識しなくなり、
対応策としてIDEの指示に従って csproj に変更を加えたあたりが怪しいですが、
再現性が無いので難しいところです。
f:id:m2wasabi:20170216223832j:plain

現象としては、SDKのバージョンが変わった場合の挙動と同じようです。

手掛かりなしで手元のソースを漁ったお陰で Xamarin.Forms のソースけっこう追いかけました。
泥臭い知識としては役に立つと思われますが、問題解決の視点では徒労でした…(´・ω・`)

Xamarinを使った開発で、実行時エラーによく遭うのですが、 その時の対処法100選の一つにでも。

ネタ元

Twitterのモーメントに上げました。 twitter.com

問題の解決に際し @nuits_jp さんをはじめ JXUGの皆様にとても助けられました。
ありがとうございました。

Azure Web Apps に Let's Encrypt を使って簡単に SSL を導入する

本稿の目的

OSと旧ポータルに依存せずに、 Azure-CLIを用いて手早く Let’s Encrypt を設定します

本稿の対象者

本稿は下記の全てに当てはまっている人が対象です。

独自ドメインではなく *.azurewebsites.ne で構わない場合は
元々用意されているワイルドカード証明書を使いましょう。

Let’s encrypt設定完了までの手順

1. Azure-CLIをインストールする

Node.jsがインストールされた環境で、以下を実行します。
sudoの有無は環境によって適宜判断してください。

npm install -g azure-cli

インストールが完了したらAzure-CLIでAzureにログインしましょう

azure login

f:id:m2wasabi:20170207043233p:plain リンクにアクセスして コードを入力して Azureのアカウントでログインしましょう。 f:id:m2wasabi:20170207043321p:plain

2. 対象の WebAppsを立てる

カスタムドメインが設定された App Service を用意しましょう
App Service プランは Basic以上を選択しましょう
f:id:m2wasabi:20170207052737p:plain

3. ストレージアカウントの作成する

Let’s EncryptのSite Extentionが使うストレージアカウントを作成します。
ストレージアカウントは壊れて困るデータは入らないので、任意の設定で構いません。
今回は、パフォーマンス:Standard , レプリケーション:LRS にしました。

Azure-CLIで作る場合は以下のコマンドで作成します。

azure storage account create --sku-name LRS --kind Storage -l <location> -g <resourcegroup> <name>

例えばこんなコマンドになります。

azure storage account create --sku-name LRS --kind Storage -l japaneast -g myresource letsencrypt

ブラウザでportalにアクセスして作成しても良いです。
f:id:m2wasabi:20170207044625p:plain

4. Azure AD でアプリを登録し、サービス プリンシパルを作成する

Let'sEncryptのSiteExtensionがリソースにアクセスするための サービス プリンシパルを作成します。
難しい専門用語ですが、要は「サービス用のアカウント」と「アクセス権」という認識で良いと思います。

Azure-CLIで以下のコマンドで作成します。

azure ad sp create -n <application_name> -p <password>
azure ad sp create -n letsencrypt -p HogeFuga123

実行すると、Object IDとService Principal Namesが得られるのでメモしておきましょう。 f:id:m2wasabi:20170207044951p:plain

これはブラウザでportalにアクセスして作成する場合少し面倒です。
サービスプリンシパルは旧ポータルでしか作成できません。
旧ポータルは繋がらないこともあるので、Azure-CLI使うことを強くお勧めします…

5. リソースグループへのアクセス権限付与

作成したサービス プリンシパルが、リソースグループへアクセスできるよう権限を付与します。
よく嵌るのが、間違えて対象のAppServicesに与えてしまうことです。

Azure-CLIでもできますが、これはportalから設定したほうが楽です。
役割を「共同作成者」、
ユーザーを先ほど追加したアプリ名にしましょう。(選択肢には無いですが、フォームに入力すると出てきます。) f:id:m2wasabi:20170207045222p:plain

尚、Azure-CLI登録する場合は、

azure role assignment create --objectId <サービスプリンシパルのObject ID> -o Contributor -c /subscriptions/<WebAppsの所属するサブスクリプションID>/resourceGroups/<リソースグループ名>

参考になりにくいですが、実際に入力する場合、以下のようなイメージになります。
なお例示のIDはランダム文字です。

azure role assignment create --objectId abc12345-1234-5678-9abc-0123456789ab -o Contributor -c /subscriptions/98765412-9876-4567-3214-0123456789ab/resourceGroups/myawsomeproject

6. サービスプリンシパルのSecretKeyの生成

AzureAD(Azure Active Directory) →アプリの登録→アプリ名→設定→キー
でsecret keyを生成します。 f:id:m2wasabi:20170207045613p:plain

7. WebAppsの環境変数を登録する

WebAppsの環境変数に設定する文字列は以下です ストレージアカウント接続文字列の取得
ストレージアカウントの「アクセス キー」の項目より、
key1の右端の「・・・」をクリックし、「接続文字列の表示」を押すと以下のフォーマットの文字列が取得できます。
f:id:m2wasabi:20170207050021p:plain

DefaultEndpointsProtocol=https;AccountName={ストレージ アカウント名};AccountKey={key1};

この文字列を 【ストレージ】 と定義する。

AzureAD の「ドメイン名」の項目より、プライマリドメインをコピー。(*.onmicrosoft.comの形式) この文字列を 【ADドメイン と定義する。 f:id:m2wasabi:20170207050341p:plain

課金>作成したアクティブなサブスクリプション から得られる サブスクリプションID】 f:id:m2wasabi:20170207050946p:plain

項目名 入れる内容
AzureWebJobsStorage 【ストレージ】
AzureWebJobsDashboard 【ストレージ】
letsencrypt:Tenant 【ADドメイン
letsencrypt:SubscriptionId サブスクリプションID】
letsencrypt:ClientId 4で取得したサービスプリンシパルのObject ID
letsencrypt:ClientSecret 6で取得したサービスプリンシパルのSecretKey
letsencrypt:ResourceGroupName リソースグループ名
letsencrypt:ServicePlanResourceGroupName リソースグループ名

f:id:m2wasabi:20170207051225p:plain

8. SiteExtensionをインストールする

SiteExtension(拡張機能)でAzure Let’s Encrypt (x86)をインストールする f:id:m2wasabi:20170207051415p:plain

9. 証明書を発行する

拡張機能の【参照】から
UIに従っていけば発行できます。
f:id:m2wasabi:20170207051600p:plain

f:id:m2wasabi:20170207051742p:plain f:id:m2wasabi:20170207051754p:plain

f:id:m2wasabi:20170207052130p:plain f:id:m2wasabi:20170207052135p:plain f:id:m2wasabi:20170207052140p:plain f:id:m2wasabi:20170207052147p:plain

10. 確認と後片づけ

これでめでたくSSLの導入が出来ました。httpsでサイトにアクセスしてみましょう。
f:id:m2wasabi:20170207052340p:plain

また、WebJobsは次の証明書更新まで用がないので止めても大丈夫です。

11. 証明書を再発行するときは

WebJobsでLet'sEncryptを起動して、9の手順を行います。

簡単ですね!

付録:ルートディレクトリを変更する場合

PHPとか入れた時にドキュメントルート移動したら証明書作れなくなった!」
そんな時

アプリケーションでpublicの階層掘ってる場合は
challengeファイルにアクセスするためのweb.configを書けばOKです

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>

        <!-- Letsencrypt challenge file -->
        <rule name="AcmeChallenge" stopProcessing="true">
          <match url="^.well-known/acme-challenge/(.*)$" />
        </rule>

      </rules>
    </rewrite>
  </system.webServer>
</configuration>

参考リンク

http://blog.shibayan.jp/entry/20151111/1447172124
しばやん氏のブログ。
証明書の作成方法が本家準拠なので素直にこの方法で出来ます。
しかし実施環境に多少のハードルがあります

https://github.com/sjkp/letsencrypt-siteextension/wiki/How-to-install
今回使う Let’s Encrypt Site Extension の本家wikiです。
Azureの周辺知識が完璧で英語もさくさく読めるなら、もうここに行ってみてください。

https://blogs.technet.microsoft.com/mskk-cloudos/2016/02/22/lets-encrypt-azure-web-apps-https/
マイクロソフトの中の人のブログ。
導入説明は間違ってないけれど、用語の意味が分からなくてどうしていいか詰んだり、
旧ポータル使うとか小さすぎるスクショがダウンロードとかぐぬぬ
旧ポータルがちゃんと動いてくれれば私の記事は必要ないはずです。

AzureでCROSとカスタムヘッダを併用する場合の注意

API AppsのCORS設定機能は、カジュアルにアクセス元サイトを指定できて便利ですが、

f:id:m2wasabi:20161130123126j:plain

portalで設定できるCORSを使うと、アプリケーションからのhttpヘッダの変更ができなくなります。
Web.configやアプリケーションからヘッダを触りたい場合は、
Azure portalのCORS設定には何も書かずに自分でヘッダを書きましょう。

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD, OPTIONS" />
        <add name="Access-Control-Allow-Credentials" value="true"/>
        <add name="Access-Control-Allow-Headers" value="X-Requested-With, origin, content-type, accept" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

参考:
CORS support in App Service | Microsoft Docs

VisualStudio 2017 RC のXamarinを入れたら VisualStudio2015からXamarinが消える問題

2017/3/10追記

VisualStudio 2017 GA版で、2015以前のVisualStudio と Xamarinを問題なく共用できるようになりました。
安心して VisualStudio 2017 をインストールしましょう。



先日のConnect();で VisualStudio 2017 RCが発表されました。
What's New in Visual Studio 2017


起動が爆速になったり、WepPIの呪いから解放されてそうだったり環境構築が趣味の自分的には楽しみではあります。


また、Xamarinの新機能として、Preview版の機能だった奴等が正式版になったりと、良い話は公式にお任せします。
Connect(); Keynote Releases | Xamarin Releases

本題

VisualStudio 2017 RCはインストールした後に、各開発プラットフォームの機能をインストールするのですが、
f:id:m2wasabi:20161119063213p:plain
ここでXamarinをインストールすると、 VisualStudio 2015 側でXamarinが消えてしまいます。
f:id:m2wasabi:20161119063259p:plain
ビルドも新規作成も出来なくなるので詰んでます。

最新のXamarin for Visual Studioには、VisualStudio 15 (2017のこと)の対応は入ってますが、
入れてもVisualStudio 2017 RCでXamarinを認識しません。
f:id:m2wasabi:20161119064153p:plain

いろいろなインストール方法を試したのですが、両方動く組み合わせはありませんでした。

インストール方法 VS2015 VS2017RC
VisualStudio 2017 RC から Xamarinを入れる ×
VisualStudio 2015 から Xamarinを入れる ×
Xamarin Universal Installer からインストール ×
Xamarin for Visual Studioを直接インストール ×

XamarinのUniversal Installerが Android SDKを何度でも上書きしたり、
Cドライブにしかインストールできなかったりするのはストレスしかないので何とかしてほしいですね。

今のところお勧めは、VisualStudioのインストールオプションでインストールするか、
以下のように直接ダウンロードしてインストールです。
https://dl.xamarin.com/XamarinforVisualStudio/Windows/Xamarin.VisualStudio_4.2.1.62.msi


尚、公式でインストーラーからの VisualStudio2017対応はサポートしてない旨、書いてあります。
https://developer.xamarin.com/releases/vs/xamarin.vs_4/xamarin.vs_4.2/#XVS_4.2.0.680
f:id:m2wasabi:20161119065543p:plain

結論

現時点では VisualStudio 2015 と VisualStudio 2017 RC の両方で Xamarin for VisualStudioを動かすことはできない。

※試した時点でのXamarin for VisualStudioのバージョンは4.2.1.62です。

仕事でXamarinのアプリ作ってる人は、公式の両対応を待つか、VisualStudio 2017 RCでXamarinを入れないようにしましょう。
それかXamarin StudioとVisualStudio for Macの共存できるMac買いましょう

Xamarin入門者の集いでLTしてきました

Xamarin入門者の集いでLTしてきました。
jxug.connpass.com


発表までに用意していたネタがほとんど被ってしまったので、
ほぼネタLTになってしまいました。

トークもうちょっとがんばれればよかったのですが、
いざ喋りだすとネタ全部忘れてスライド読みだすのは良くない癖ですね。

doc.co

余談ですが、後半のいかにも前時代パワポ臭いスライドはわざとです!
何名か笑ってくれたのでよかった!

そういえばUnity初心者の会で発表してた

そういえば、人知れず14日のUnity初心者勉の会に参加してきました。
web3dj.connpass.com

最先端について語りたいけど、なにぶんへっぽこなので、
モデルの差し替えで詰まりがちなMechanim with Humanoidの使い方について、 Stabdard Assets について、LTしてきました。
分かってる方には学びでも何でもなくサクサクなのですが、分かってないと何やっていいのかサッパリな部分なので、初心者向けには良いかなと。
スライドにアニメーションGIF使ってますが、オンラインだと動かないので、ちゃんと見たい方はpptxをダウンロードして見てください。
doc.co

明日はXamarinについて何か喋るらしいです。
jxug.connpass.com


ジャンル横断で発表するなんて完全に勉強会五郎ですね。
後ろで「ほーいいじゃないか こういうのでいいんだよこういうので」とか「すごいことになっちゃったぞ」とか心の声で言ってる時が至福です。

Azure Web Apps のPHPでSecureなAPIにアクセスするときの設定

OAuth2や外部のRestAPIが普及してきたことで、curlを使ってSSLを叩く機会が増えてきました。
しかしながら、Azureを含むWindowsプラットフォームで、設定無しにsslサイトにcurlすると、

cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

とか言われて怒られます。

f:id:m2wasabi:20161005144711j:plain

適切なCA証明書の場所をPHPに教えてやればいいのですが、
ググっても、証明書の検証を無効化するとかは論外として、
自分で証明書入れたり*1、Gitの証明書を流用すればいいろ書いてあるものの、結果そこには何もありませんでした事案*2ばかりだったので、
現在の構成で正しい場所を共有します。*3


"D:\Program Files (x86)\Git\etc\pki\ca-trust\extracted\openssl\ca-bundle.trust.crt"

以下のファイルを wwwroot 以下にデプロイしてやれば、sslcurlがばっちり使えます。

.user.ini


それでは、良いAPIライフを。

*1:https://blogs.msdn.microsoft.com/tsmatsuz/2014/12/12/azure-web-site-curl-ssl-https/ blogs.msdn.microsoft.com

*2:azure.microsoft.com

*3:WebAppsの中を探索しまくれば一応見つかりますが、無駄な労力です