Microsoft 系のあれこれ

港区の SIer で よくわからんことをしている人です。Xamarin 中心でした。(過去形)

Visual Studio 2017 Version 15.5 にアップデートしたら Android が表示されなくなった時の対処方法

qiita.com
↑のクリスマスイブ分の穴埋めです。

やっつけですが、ご容赦を。


Visual Studio が 2017 になってからアップデートが短いサイクルで行われるようになりました。
一応、ReleaseNote はぺろーっと眺めてから(なにも考えず)実行しているのですが、問題が発生しました。
Visual Studio 2017 15.5 リリース ノート

久しぶりに Xamarin.Forms のプロジェクトを開いてみると、ツールメニューから「Android」がなくなりました。
なにを言ってるかわからないかもしれませんが、なくなりました。
f:id:ShunsukeKawai:20171226154456p:plain:w400

↓↓↓正しい姿↓↓↓
f:id:ShunsukeKawai:20171226155422p:plain:w400

Androidデバッグ実行もアーカイブもできなくなっています。

対処方法

Visual Studio Installer を起動して以下の2つを選択してからインストールを実行します。
f:id:ShunsukeKawai:20171226154805p:plain

Ver.15.5 から Android 標準の SDK Manager とは別に Xamarin 用のが追加されたようですね。
そしてそれはデフォルトではインストール対象外になっているようです。。
今回の問題自体は Android SDK セットアップ(API レベル 25)が原因らしいですが、SDK Manager も一緒に入れちゃいましょう。

【参考:Xamarin Android SDK Manager の画面】
f:id:ShunsukeKawai:20171226160607p:plain

蛇足

ちゃんと開発環境の更新をする時は変更内容を確認しましょう。(自戒)
でもアップデートが頻繁過ぎてつらいなぁ。
Xamarin も VS に含まれて更新されるから全然関係ない更新もあるし、個別に更新してた時の方が楽だったかもな。
チームメンバー内で環境を統一するのは楽になったけど、1週間に1回ぐらい更新すべきかを判断して更新するって(30分もかからないけど)タスクが増えちゃう。
みんなめんどくさくないのかなぁ?

Visual Studio 2017 Version 15.2 にアップデートしたら Xamarin.Forms の Android アプリがすごい遅くなったから回避した

============================================
2017/5/31 追記
Visual Studio 2017 version 15.2 (26430.12) で対応されたようです。
>Fixed a performance dedgration sometimes occuring in Xamairn Android apps.
Visual Studio 2017 Release Notes
============================================

============================================
2017/5/25 追記
Mac、VS 2015 は対応されたようです。
Stable Release: 15.2.2 Servicing Release | Xamarin Releases


2017 はまだかな…
============================================

============================================
2017/5/17 追記
下記手順を行うと Android の Release ビルドで作成したアプリがうまく動かなくなります。
Debug 時の回避手段とお考え下さい。
============================================

※この記事の手順は自己責任でお願いします。

タイトルの通りです。
Xamairn.Forms、Prism(Unity) で作成した Android アプリがなんか InitializeComponent で数秒かかる感じに遅くなったんです。
Android 4.4では発生せず、6.0、7.0で現象を確認できました。

環境は以下の通り。

  • Windows 10 Pro Creators Update (バージョン1703、ビルド15063)
  • Visual Studio 2017 Version 15.2 (26430.4)
  • Xamarin 4.5.0.443
  • Xamarin.Android.SDK 7.3.0.13


色々皆さんのご協力をいただき、対症療法的に回避しました。

調べていると下記 bugzilla がヒットしてみんな Xamarin.Android 7.3 が原因っぽいことを言っています。

56240 – Performance Degradation When Using Expressions

ということで Xamarin.Android を前のバージョンにダウングレードしたいと思います。

下記サイトから以前の Xamarin インストーラー(4.4)をダウンロードしてきます。

※ Xamarin のアカウントが必要です。
https://store.xamarin.com/account/my/subscription/downloads
f:id:ShunsukeKawai:20170515215324p:plain

ダウンロードした Xamarin インストーラーを起動します。

※この時点で Build Tools 2015 が必要です。みたいなことを言われたらインストールしてください。
Download Microsoft Build Tools 2015 from Official Microsoft Download Center

インストーラー起動後、今回は Xamarin.Androidだけ必要なので、他のチェックは外しちゃいます。

f:id:ShunsukeKawai:20170515215944p:plain

インストールされたファイルは基本的には以下にあると思います。

C:\Program Files (x86)\MSBuild\Xamarin

実際に VisualStudio で使用している Xamarin.Android のフォルダーをリネーム(バックアップ)して先ほどのファイルを丸ごと持ってきます。

C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin
f:id:ShunsukeKawai:20170515220606p:plain

以上で終了です。

Visual Studio を起動して出力の Xamarin Diagnostics に以下のように 7.2 だよー的なのが出ていれば成功です。
早くなりました。
f:id:ShunsukeKawai:20170515220830p:plain

Prism との組み合わせなのかなー。すぐ修正されるといいなぁ。

以下、みなさんのご協力



Daiki Kawanuma (@Santea3173) | Twitter
さんが
クワーティ (@qwerty2501) | Twitter
さんも悩んでいたことを教えてくれて



かむ (@muak_x) | Twitter
さんも参戦し


Mac 版はサクッと解決してくれたので

参考にして Windows も回避です。

Visual Studio 2017でXamainのUpdate Channelを切り替える方法(というかVisual Studio 2017のインストーラーの仕組み)

Visual Studio 2015 では Xamarin の最新の機能を試したい場合、ツール⇒オプション⇒Xamarin⇒その他でチャンネルを切り替えることができました。
しかし、昨日リリースされた Visual Studio 2017 ではその設定がなくなっています。

Visual Studio 2017

f:id:ShunsukeKawai:20170309112803p:plain

で、どうするかと言うと、Xamarin 公式サイトに答えがありました。
Change the Updates Channel - Xamarin
ちゃんとすぐ更新されていて素晴らしいですね。
結論から言うと、Xamarin 個別にチャンネルを切り替えることができなくなり、Visual Studio 自体のバージョンにより Xamarin のリリースも制御されるようになったみたいです。

インストール手順

プレビュー版の Visual Studio インストーラーをダウンロード

Visual Studio Preview Release Notes
のサイトの以下のリンクからプレビュー版のインストーラーをダウンロードします。
f:id:ShunsukeKawai:20170309113900p:plain
※ このサイトには Visual Studio Enterprise 用のインストーラーリンクしかありませんが、別のエディションをインストールしたくてもそのままダウンロードしてください。

インストールしたいエディションを選択して実行

ダウンロードしたインストーラーを起動すると以下のような画面が開きます。
f:id:ShunsukeKawai:20170309115551p:plain
このまま進むと Enterprise 版になってしまうので、一旦右上の×で閉じます。
そうすると以下の画面になるので、好きなエディションを選択して、インストールに進みます。
f:id:ShunsukeKawai:20170309120422p:plain
その際にインストールのニックネームを付けることでどのバージョンかとかがわかるようできるみたいです。
f:id:ShunsukeKawai:20170309122949p:plain

ここで疑問

今回やりたいことは Xamarin の Update Channel を切り替えたいだけなのに VS 自体を別でインストールしないといけないとしたらディスク容量はすぐ一杯になってしまうでしょうよ。
インストールする対象を Xamarin だけにしてちゃんと開発できるのか?(上の画像は Xamarin だけを選んだ。容量3.98GB)
ちょっと私のディスク容量はすでにカツカツなので、どなたか確認したら教えてくださいm(_ _)m

Visual Studio 2017 のインストーラーの仕組み

今回からインストーラー自体がアプリとして自動的に更新されるような仕組みになったみたいです。
それぞれのエディションごとにダウンロードリンクは別で起動時の対象は違うけど上述の通り、全部選べる。
また、すでに製品版を既にインストールしている端末でプレビュー版のインストーラーを起動すると、インストーラーが更新されて以下のように製品版もプレビュー版も管理できるようになります。
f:id:ShunsukeKawai:20170309123908p:plain

そもそも、OS の「プログラムと機能」からは Visual Studio 2017 の変更が選べず、アンインストールしかありません。
ここにある Visual Studio 2017 は VS のことではなく、インストーラーを指すようです。(表示されているバージョンもインストーラーのバージョン)
f:id:ShunsukeKawai:20170309124225p:plain
インストーラーを使い捨てのモノでなくアプリとして作成することで、製品の更新や管理を統合的にできる仕組みになった感じですかね。

本来の目的は達成できてないけど、今日はここまで。

【続】Xamarin.Formsでぺこぺこ凹むアイコンボタンを作った

先日アイコンボタンを作ったと書きましたが、色々更新しました。
shunsukekawai.hatenablog.com

f:id:ShunsukeKawai:20170110224311g:plain

追加内容

  • ラベル追加(DescriptionText)
  • ラベル位置プロパティ設定(DescriptionPosition)
  • ラベルサイズプロパティ設定(DescriptionSize)
  • ラベルカラープロパティ設定(DescriptionColor)
  • アイコン高さプロパティ設定(IconHeight)
使い方

なんか設定する項目が多くなってヤダけど、しょうがない。
ラベルが必要なければ設定しなくて OK です。

<controls:IconButton
    DescriptionColor="#636161"
    DescriptionPosition="Bottom"
    DescriptionSize="24"
    DescriptionText="削除"
    HeightRequest="120"
    HorizontalOptions="Center"
    IconHeight="70"
    IconMargin="10"
    IconSource="{Binding Source=IconButtonSample.Images.Trash.png, Converter={StaticResource ImageSourceConverter}}"
    VerticalOptions="Center">
    <controls:IconButton.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding Path=DeleteCommand}" />
    </controls:IconButton.GestureRecognizers>
</controls:IconButton>

めんどくさかったところ

  • 位置を設定する

横着してボタン全体を囲う2行2列の Grid を追加して位置プロパティ(Enum)によってボタンとラベルの位置を設定しましたが、
Xamarin.Forms なのか UIView なのかわかりませんが、Grid の Definition が Auto かつコントロールが何もなくても微妙にスペースが空いちゃうので、RowSpacing と ColumnSpacing を 0 に設定しています。

<?xml version="1.0" encoding="utf-8" ?>
<ContentView
    x:Class="IconButtonSample.Controls.IconButton"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <Grid
        x:Name="grdIconButton"
        ColumnSpacing="0"
        HorizontalOptions="CenterAndExpand"
        RowSpacing="0"
        VerticalOptions="CenterAndExpand">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Image
            x:Name="imgIcon"
            Aspect="AspectFit"
            BindingContextChanged="imgIcon_BindingContextChanged" />
        <Label
            x:Name="lblDescription"
            HorizontalOptions="CenterAndExpand"
            VerticalOptions="CenterAndExpand" />
    </Grid>
</ContentView>
private void setPosition(DescriptionPosition position)
{
    switch (position)
    {
        case DescriptionPosition.None:
            imgIcon.SetValue(Grid.RowProperty, 0);
            lblDescription.SetValue(Grid.RowProperty, 0);
            imgIcon.SetValue(Grid.ColumnProperty, 0);
            lblDescription.SetValue(Grid.ColumnProperty, 0);
            lblDescription.IsVisible = false;
            break;
        case DescriptionPosition.Left:
            imgIcon.SetValue(Grid.RowProperty, 0);
            lblDescription.SetValue(Grid.RowProperty, 0);
            imgIcon.SetValue(Grid.ColumnProperty, 1);
            lblDescription.SetValue(Grid.ColumnProperty, 0);
            break;
        case DescriptionPosition.Top:
            imgIcon.SetValue(Grid.RowProperty, 1);
            lblDescription.SetValue(Grid.RowProperty, 0);
            imgIcon.SetValue(Grid.ColumnProperty, 0);
            lblDescription.SetValue(Grid.ColumnProperty, 0);
            break;
        case DescriptionPosition.Right:
            imgIcon.SetValue(Grid.RowProperty, 0);
            lblDescription.SetValue(Grid.RowProperty, 0);
            imgIcon.SetValue(Grid.ColumnProperty, 0);
            lblDescription.SetValue(Grid.ColumnProperty, 1);
            break;
        case DescriptionPosition.Bottom:
            imgIcon.SetValue(Grid.RowProperty, 0);
            lblDescription.SetValue(Grid.RowProperty, 1);
            imgIcon.SetValue(Grid.ColumnProperty, 0);
            lblDescription.SetValue(Grid.ColumnProperty, 0);
            break;
        default:
            break;
    }
}

こちらも更新しています。
github.com

Xamarin.Formsでぺこぺこ凹むアイコンボタンを作った

Image だけをボタンにしたいケースが多々あり、TapGestureRecognizer で簡単に作れるのですが、押した感がなくイマイチだし好みに合うヤツが見当たらなかったので作りました。
f:id:ShunsukeKawai:20170106115747g:plain
わかりにくいですが、黒い背景でも微妙にボタン裏の色が変わっています。

凹む処理はここを参考にしました。
app-evolve/FavoriteImage.cs at master · xamarinhq/app-evolve · GitHub

最初は Image コントロールだけを拡張していましたが、それだと凹ますと背景色まで凹んでしまいかっこ悪かったので Content View の中に Image を入れました。

IconButton.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
    x:Class="IconButtonSample.Controls.IconButton"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
    <Image x:Name="imgIcon" BindingContextChanged="imgIcon_BindingContextChanged" />
</ContentView>
IconButton.xaml.cs
using System;
using System.Threading.Tasks;

using Xamarin.Forms;

namespace IconButtonSample.Controls
{
    public partial class IconButton : ContentView
    {
        private bool addedAnimation;

        public static readonly BindableProperty IconSourceProperty =
            BindableProperty.Create(
                "IconSource",
                typeof(ImageSource),
                typeof(IconButton),
                null,
                propertyChanged: (bindable, oldValue, newValue) =>
                {
                    ((IconButton)bindable).IconSource = (ImageSource)newValue;
                }
            );

        public ImageSource IconSource
        {
            get { return (ImageSource)GetValue(IconSourceProperty); }
            set
            {
                SetValue(IconSourceProperty, value);
                imgIcon.Source = value;
            }
        }

        public static readonly BindableProperty IconMarginProperty =
            BindableProperty.Create(
                "IconMargin",
                typeof(Thickness),
                typeof(IconButton),
                new Thickness(0),
                propertyChanged: (bindable, oldValue, newValue) =>
                {
                    ((IconButton)bindable).IconMargin = (Thickness)newValue;
                }
            );

        public Thickness IconMargin
        {
            get { return (Thickness)GetValue(IconMarginProperty); }
            set
            {
                SetValue(IconMarginProperty, value);
                imgIcon.Margin = value;
            }
        }

        public IconButton()
        {
            InitializeComponent();
        }

        private void imgIcon_BindingContextChanged(object sender, EventArgs e)
        {
            if (addedAnimation || GestureRecognizers.Count == 0)
                return;

            var tapGesture = GestureRecognizers[0] as TapGestureRecognizer;
            if (tapGesture == null)
                return;

            tapGesture.Tapped += (tapsender, tape) =>
            {
                Device.BeginInvokeOnMainThread(async () => await tappedAnimation());
            };

            addedAnimation = true;
        }

        private async Task tappedAnimation()
        {
            BackgroundColor = Color.FromRgba(68, 68, 68, 70);
            await imgIcon.ScaleTo(0.8, 75);
            await imgIcon.ScaleTo(1.0, 75);
            BackgroundColor = Color.Transparent;
        }
    }
}

凹ます処理の前後に Content View 自体の背景色を適当な灰色にしています。
ポイントとして Alpha 値を設定して透過にすることで画面の背景色になじむようにしています。
本来はこの辺も BindableProperty にして公開した方がよかったかもしれませんが、まぁいいかなと。

使う画面.xaml
<control:IconButton
    HeightRequest="50"
    HorizontalOptions="Center"
    IconMargin="10"
    IconSource="{Binding Source=IconButtonSample.Images.Trash.png, Converter={StaticResource ImageSourceConverter}}"
    VerticalOptions="Center">
    <control:IconButton.GestureRecognizers>
        <TapGestureRecognizer Command="{Binding Path=DeleteCommand}" />
    </control:IconButton.GestureRecognizers>
</control:IconButton>

ImageSource を Converter 使っていますが、これは画像を埋め込みリソースにして PCL 側に置いているからです。
その辺も含めてこちらにまるごとサンプルを置いてありますので、ご自由にどうぞー。
Prism 使ってます。
github.com

あとは指が抑えている状態(Hold 時)にも色変えたいけど、とりあえず標準のヤツよりいいから満足です。

更新しました

shunsukekawai.hatenablog.com

Xamarin.Forms と Mobile Engagement でユーザー分析しちゃえ!

Xamarin Advent Calendar 2016 - Qiita "その1" 9日目の投稿です。

はい、ということでこんな状況の中、なんとか書きました。。


ホントは0時きっかりにアップしたかったけど、ご了承ください。

さて、Microsoft さんのイベントで使用したアプリケーションの開発をやった話の記事で簡単に説明しましたが、Azure の Mobile Engagement というサービスはとても楽しいサービスです。
shunsukekawai.hatenablog.com

本記事では Xamarin.Forms でどのように Mobile Engagement でどんなことができるのか、どう使用するかを解説をします。

Mobile Engagement でできること

リアルタイムのアクティブユーザー

こんな感じで今正にアクティブなユーザー数が表示されます。
f:id:ShunsukeKawai:20161102190000p:plain

どの画面がどれだけ使われているか

画面の起動時にコードを1行埋め込むことで、勝手にデータを蓄積してくれます。
f:id:ShunsukeKawai:20161102190017p:plain

どんな画面遷移を行っているか

どこからどこの画面に行ってるかよくわからん図で表示されます。
f:id:ShunsukeKawai:20161208225124p:plain

セッション時間はどのくらいか

どのくらいアクティブにアプリを使ってくれているのかが表示されます。
f:id:ShunsukeKawai:20161208225753p:plain

バイスはなにか

iOS(iPhone9,1とかなんなのか…)
f:id:ShunsukeKawai:20161208225228p:plain
Android は製造元を選択するとモデルまで表示されます。
f:id:ShunsukeKawai:20161208230027p:plain

OSはなにか

サポート対象OSを決める時に役に立ちそう。
f:id:ShunsukeKawai:20161208225325p:plain

どのアプリバージョンを使っているか

ちゃんとユーザーがバージョンアップしてくれてるかわかりますね。
f:id:ShunsukeKawai:20161208225357p:plain

画面サイズはなにか

どのサイズで動かされているかわかると色々対策できそうです。
f:id:ShunsukeKawai:20161208225512p:plain

アプリがクラッシュしている原因とその詳細

StackTrace 的なのも出てます。
f:id:ShunsukeKawai:20161208225632p:plain

と、まぁここに挙げたのは一部ですが、見てるだけでも酒の肴になりそうですね。

Xamarin.Forms に組み込む方法

ここからは Mobile Engagement をどうやってXamarin.Forms に組み込むかです。

Azure ポータルから Mobile Engagement のサービスを追加

f:id:ShunsukeKawai:20161201212016p:plain:w500

  • 対象プラットフォームを UWP、AndroidiOSを選択する

f:id:ShunsukeKawai:20161201215231p:plain:w500

  • その他設定はよしなに
  • 作成完了(3つのアプリが作成されます)

Mobile Engagement アプリはプラットフォームごとに作成する必要があります。
f:id:ShunsukeKawai:20161201215715p:plain:w500

Xamarin.Forms プロジェクトに Mobile Engagement 接続(Android 編)

基本的に以下のチュートリアルに沿って進めていけば大丈夫です。(人任せ)
もう Mobile Engagement 作成は済んでいるので、キーをコピーするところ以降ぐらいから。
Xamarin.Android 用 Azure Mobile Engagement の使用

  • 【注意1】NuGet から Microsoft.Azure.Engagement.Xamarin をインストールしたら勝手に作られるフォルダの対処

NuGet からインストールすると勝手にフォルダが作られてそこに Mobile Engagement 用のリソースが置かれます。
(おそらく Xamarin.Android 用だからかな)
そのためその状態でビルドすると以下の様なエラーが発生します。
f:id:ShunsukeKawai:20161208150417p:plain
↓犯人
f:id:ShunsukeKawai:20161208150802p:plain
↓該当するフォルダに移動します。(+になってるヤツを移動した)
f:id:ShunsukeKawai:20161208150959p:plain

  • 【注意2】using は Microsoft.Azure.Engagement.Xamarin だけでいい

MainActivity.cs の using は一つだけで大丈夫です。

  • 【注意3】MainActivity.cs に EngagementActivity の継承をすることは Xamarin.Forms ではできない(FormsAppCompatActivity をすでに継承しているため)

こっち側の手順でやる必要がある
Azure Mobile Engagement Android SDK の詳細なレポート オプション

Xamarin.Forms プロジェクトに Mobile Engagement 接続(iOS 編)

基本的に以下のチュートリアルに沿って進めていけば大丈夫です。(人任せ2)
もう Mobile Engagement 作成は済んでいるので、キーをコピーするところ以降から。
Xamarin.iOS 用 Azure Mobile Engagement の使用

Xamarin.Forms プロジェクトに Mobile Engagement 接続(UWP 編)

基本的に以下のチュートリアルに沿って進めていけば大丈夫です。(人任せ3)
もう Mobile Engagement 作成は済んでいるので、キーをコピーするところ以降から。

Windows ユニバーサル アプリの Azure Mobile Engagement の概要

  • 【注意1】UWP は他と NuGet のパッケージが違うから注意(~Xamarin ではない)
  • 【注意2】リンク先にも書いてありますが、NuGet は、Windows 10 UWP アプリケーションで SDK のリソースを自動的にコピーしません。 NuGet パッケージのインストール時に表示される手順 (readme.txt) に従って、手動で行う必要があります。

とあります。readme.txtの内容は以下の通り。はい。自分で作れっつーことですね。

NuGet does not automatically copy the SDK resources in your Windows 10 UWP application. You have to do it manually until the scaffolding feature is reintroduced. 
Here are the steps for a new integration:

* Open your File Explorer.
* Navigate to the following location: %USERPROFILE%\.nuget\packages\MicrosoftAzure.MobileEngagement\3.4.1\content\win81
* Drag and drop the "Resources" folder from the file explorer to the root of your project in Visual Studio.
* In Visual Studio select your project and activate the "Show All files" icon on top of the "Solution Explorer".
* Some files may not be included in the project. To import them at once right click on the "Resources" folder, "Exclude from project" then another right click on the "Resources" folder, "Include in project" to re-include the whole folder. All files from the "Resources" folder are now included in your project.

まとめ

この辺までの基本的な設定 + PCL に interface 作って各プラットフォーム側で処理を追加して PCL の MainPage.xaml.cs にアクティブにする処理入れたヤツを以下のリポジトリにアップしてあります。
github.com

Mobile Engagement 側の接続文字列を設定すればとりあえず動くと思います。
Push 通知したい場合は各プラットフォームのリンク先を参考に設定してみてください。(最後も人任せ)

それではお疲れ様でした。

VSTS で Team Foundation Version Control で Xamarin のソース管理をする際に package フォルダーを除外したい

かなりニッチな投稿です。

Visual Studio Team Services(VSTS)でソース管理を行う場合、以下の2つから選択できます。

正直 Git が今は主流だと思うのですが、ウチのチームは旧 Visual Source Safe(VSS)からの名残で Team Foundation Server(TFS) ベースの方を利用しています。

Xamarin.Forms のテンプレートで作ったプロジェクトを上記ソース管理に追加をすると、管理対象に package フォルダーを追加してしまいます。
f:id:ShunsukeKawai:20161118180510p:plain
もちろんこのチェックインからは除外することはできるのですが、永続的に対象から除外することは Visual Studio のメニューからはできなそうでした。
Xamarin が悪いのか、Visual Studio が悪いのか VSTS が悪いのか、それともほかの要因なのかわかりませんが。

チームで作業している場合、package フォルダーがソース管理されてしまうと、各作業者がビルドする時に NuGet からパッケージをダウンロードしてくる時に競合したり、読み取り専用になってるからエラーになったり、作業者が別のソースをチェックインしようとすると一緒にわんさか「こいつも変更しとるな?チェックインするけ?」と聞かれて毎回除外する必要がありとても面倒でした。

除外方法

ソリューションと同階層に以下のフォルダ/ファイルを置くだけ
・.tfignore ファイル
・.nuget フォルダ
 ・NuGet.config ファイル

.tfignore ファイルの中身

除外したいフォルダやファイルのパスを記載するだけ
今回なら

\package
NuGet.config ファイルの中身
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>
</configuration>

注意点1

Windowsエクスプローラー上だと、頭が「.(ドット)」のファイルが作れません。
そのため、適当なテキストファイルを作成してメモ帳で開く→名前を付けて保存→すべてのファイルを選択して「.tfignore」と命名して保存してやらないといけない。

注意点2

Windowsエクスプローラー上だと、頭が「.(ドット)」のフォルダーが作れません。
頭だけじゃなくお尻にも「.(ドット)」を付けてやると作れます。今回なら「.nuget.」で。

Tech Summit の資料・動画が公開されました

shunsukekawai.hatenablog.com
↑こちらで登壇した旨を記載しましたが、資料、動画が公開されました。

資料

docs.com

なにかご質問があれば Twitter かコメントで遠慮なくどうぞー!

Visual Studio から 作成した iOS の ipa をアプリケーションローダーに喰わせると ITMS-90023 が発生する

Xamarin で開発して iOS の AppStore にアップロードするための ipa を作成する際にアプリケーションローダーを使用してます。

Visual Studio の Xamarin.Forms のテンプレートから作ったプロジェクトをそのままアップロードすると以下のエラーが発生します。

ERROR ITMS-90023: "Missing required icon file. The bundle does not contain an app icon for iPad of exactly '167x167' pixels, in .png format for iOS versions supporting iPad Pro."

f:id:ShunsukeKawai:20161013161447p:plain

対応方法

Info.plist を XML エディター等で開きます。
f:id:ShunsukeKawai:20161013161924p:plain

その中のアイコンの指定が並んでいる箇所を選択して

<array>
	<string>Icon-72@2x.png</string>
	<string>Icon-72.png</string>
	<string>Icon@2x.png</string>
	<string>Icon.png</string>
	<string>Icon-60@2x.png</string>
	<string>Icon-76.png</string>
	<string>Icon-76@2x.png</string>
	<string>Default.png</string>
	<string>Default@2x.png</string>
	<string>Default-568h@2x.png</string>
	<string>Default-Portrait.png</string>
	<string>Default-Portrait@2x.png</string>
	<string>Icon-Small-50@2x.png</string>
	<string>Icon-Small-50.png</string>
	<string>Icon-Small-40.png</string>
	<string>Icon-Small-40@2x.png</string>
	<string>Icon-Small.png</string>
	<string>Icon-Small@2x.png</string>
</array>

の中に

	<string>Icon-83.5@2x.png</string>

を追加します。

あとは対応するサイズ(167x167)のアイコンを追加すればOKです。

注意点

Visual Studio 上で iOS のプロジェクトのプロパティを編集(プロビジョニングファイル等の設定を編集)して保存すると上記のplistの設定が勝手に消えますw
なので、申請用 ipa を作成する際にはちゃんと確認した方がいいかもですね。。

追記

田淵さん(@ytabuchi)に教えていただいた方法の方が楽ちんですね。
ytabuchi.hatenablog.com

(おそらく)世界一簡単にXamarin.Formsのアプリに特定の値でQRコードを生成して表示する方法

public MainPage()
{
    var QrValue = "QRコードにしたい文字列";

    var imgQr = new Image { Aspect = Aspect.AspectFit };
    imgQr.Source = ImageSource.FromUri(new Uri($"http://chart.apis.google.com/chart?cht=qr&chs=200x200&chld=H|0&chl={QrValue}"));

    Content = imgQr;
}

以上!


というのも寂しいので、ちょっと解説です。
みなさんご存知の通り、XamarinにはURLを画像ソースに指定する機能があります。
developer.xamarin.com

それを利用してGoogleQRコード生成のAPIを呼び出し、その結果を設定しているだけです。
QR Codes  |  Infographics  |  Google Developers
※Warning: This API is deprecated. Please use the actively maintained Google Charts API instead. See our deprecation policy for details.
 ということで現在、このAPIは非推奨のようなのでいつ使えなくなるかわかりません。
 また、非推奨になったことでライセンスもよくわかりませんでした。
 なので自己責任でお願いします

画像として返却してくれるAPIであればこれでなくてもなんでも大丈夫だと思います。

さらにおまけで…

こんな感じでイメージコントロールとインジケーターを重ねておいてイメージの読み込みが完了するまでぐるぐるが表示されるようにするといい感じですね。
(このAPIからのレスポンスが一瞬なのでぐるぐるが見えることはないかもしれません。。。)

public MainPage()
{
    var QrValue = "QRコードにしたい文字列";

    var imgQr = new Image { Aspect = Aspect.AspectFit };
    imgQr.Source = ImageSource.FromUri(new Uri($"http://chart.apis.google.com/chart?cht=qr&chs=200x200&chl={QrValue}"));

    var prgIndicator = new ActivityIndicator{
                                HorizontalOptions = LayoutOptions.CenterAndExpand,
                                VerticalOptions = LayoutOptions.CenterAndExpand
                            };

    imgQr.PropertyChanged += (sender, e) =>
    {
        if (e.PropertyName != nameof(imgQr.IsLoading))
            return;
        prgIndicator.IsRunning = imgQr.IsLoading;
        prgIndicator.IsVisible = imgQr.IsLoading;
    };

    Content = new Grid { Children = { prgIndicator, imgQr } };
}

Androidでアプリアンインストール時の確認メッセージに「~は次のアプリの一部です」と出てくる

Android開発に慣れている人は当たり前のことなのかもしれませんが)
Xamarin.Formsでデフォルトの設定で作成したアプリをアンインストールをしようとすると、以下のように謎の確認メッセージがでてきます。
Android 5以降で確認)
f:id:ShunsukeKawai:20160808115816p:plain

変ですよね。
普通のアプリはこんな感じになります。
f:id:ShunsukeKawai:20160808115850p:plain


それで直し方。

アプリの名前なので、AndroidManifestの記載とMainActivity.csの記載を一致させると期待する結果になりました。
f:id:ShunsukeKawai:20160808120150p:plain
f:id:ShunsukeKawai:20160808120159p:plain

結果
f:id:ShunsukeKawai:20160808120354p:plain

上の例はテスト用の命名でしたが、通常の開発だとプロジェクトの命名にスペースは普通入れないけど、アプリの命名にはスペース入れるってケースは多いと思います。
その場合、MainActivity側を修正しないといけないって点がちょっとハマりました…
(MainActivityの記載はプロジェクト作成時に勝手に作成されて、かつ違いがスペースの有無だけなので…)

"ConvertResourcesCases" タスクが予期せずに失敗しました。

備忘

Xamarinでソリューションのファイルに日本語のパスが含まれているとAndroidのビルド時にタイトルのエラーが出る。
ユーザー名が日本語だと意図せず日本語パスが含まれる可能性もあるから要注意。

エラー "ConvertResourcesCases" タスクが予期せずに失敗しました。
System.IO.DirectoryNotFoundException: パス 'C:\Users\kawai\Documents\Visual Studio 2015\Projects\XamarinTestApp縺・XamarinApp\XamarinApp.Droid\obj\Debug\__library_projects__\Xamarin.Forms.Platform.Android\library_project_imports\res' の一部が見つかりませんでした。
場所 System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
場所 System.IO.FileSystemEnumerableIterator`1.CommonInit()
場所 System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
場所 System.IO.Directory.EnumerateDirectories(String path, String searchPattern, SearchOption searchOption)
場所 Xamarin.Android.Tasks.ConvertResourcesCases.FixupResources(ITaskItem item, Dictionary`2 acwMap)
場所 Xamarin.Android.Tasks.ConvertResourcesCases.FixupResources(Dictionary`2 acwMap)
場所 Xamarin.Android.Tasks.ConvertResourcesCases.Execute()
場所 Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
場所 Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext() XamarinApp.Droid

Android only allows one navigation page on screen at a time

備忘

Xamarin.FormsのAndroid実行でタイトルのようなエラーが出たら、

だめ

public App()
{
    MainPage = new NavigationPage(new MediaPage());
}

だいじょうぶ

public App()
{
    MainPage = new MainPage();
}

MSDN サブスクリプション ユーザーのXamarin登録方法

XamarinがVisualStudioユーザーに無料でついてくるようになりTLがその話題で持ち切りですが、実際にアクティベーションする方法がわかりづらく、また、どこにも書いてなかったのでメモ。


<前提>
Visual Studio Enterprise with MSDN のライセンスの場合です。
その他のサブスクリプションに関してはわかりません。


MSDNサブスクリプションのページへ行きます。
https://msdn.microsoft.com/ja-jp/subscriptions/manage


② アカウントタブの「Xamarin Studio (for OS X)」の「Register and download」を選択
f:id:ShunsukeKawai:20160406133449p:plain


③ Xamarinの登録ページに飛ぶので必要事項を記入して登録!!!
f:id:ShunsukeKawai:20160406154257p:plain

f:id:ShunsukeKawai:20160406133552p:plain
無料だーー!

Windows 10 × Visual Studio 2015 でAndroid実機デバッグ(Xamarin)

すでに、色んな方がサイトで公開してますが、自分用にまとめ。

 

Androidで実機デバッグするための手順。

  • 端末の設定
  • PC側に端末のドライバーをインストール
  • PC側での接続確認
  • Visual Studioからの起動

端末の設定

ここは簡単なので割愛します。

①端末の開発者オプションを有効にし、USBデバッグを許可にする

PC側に端末のドライバーをインストール

ここは結構手こずりました。

Google USB Driverのインストール

Android SDK ManagerからGoogle USB Driverを指定してインストール。

 

android_winusb.infの編集

  • USBで実機を接続した状態で、デバイスマネージャーからその実機のハードウェアIDをメモ。
  • AndroidSDKがある場所(以下は一例)のandroid_winusb.infを編集する。

%USERPROFILE%\AppData\Local\Android\android-sdk\extras\google\usb_driver

  もしくは

C:\Program Files (x86)\Android\android-sdk\extras\google\usb_driver

  <編集内容>

  メモしたハードウェアIDを以下の対応する箇所に入れて

  「Google.NTx86」、「Google.NTamd64」両方に追加する。

;機種名のコメント
%SingleAdbInterface% = USB_Install, USB\VID_[端末のVID]&PID_[端末のVID]
%CompositeAdbInterface% = USB_Install, USB\VID_[端末のVID]&PID_[端末のVID]&MI_01 

※デバイスマネージャーからコピーしたのをそのままだと余計な(REVなんとかとか)がついてるから対応する箇所だけ抜き出す。

 

③PCに端末のドライバーをインストール

ここまでで準備ができたと思いきや、まだデバイスマネージャーからのドライバーのインストールができない。

Windows 8ぐらいから未署名のドライバーのインストールが簡単にできなくなったらしい。

※色んなサイトにはテストモードにするとかありましたが、不要なようです。

 

  • 設定から起動オプションを指定する用の再起動を行う

f:id:ShunsukeKawai:20151013181351p:plain

  • オプションから「トラブルシューティング」を選択

f:id:ShunsukeKawai:20151013181950p:plain

  •  「詳細オプション」を選択

f:id:ShunsukeKawai:20151013181828p:plain

  •  「スタートアップ設定」を選択

f:id:ShunsukeKawai:20151013182049p:plain

  • 「ドライバー署名の強制を無効にする」を行いたいので、数字の7を押下する

f:id:ShunsukeKawai:20151013182142p:plain

  •  再起動後にデバイスマネージャーから対象の機種を選択し、「ドライバーの更新」を選択
  • Andoroid SDKの場所を指定し、インストールを実行f:id:ShunsukeKawai:20151013182549p:plain

完了です!!やったー!!

 

PC側での接続確認

adbコマンドでちゃんと接続確認できているか確認をします。

adb devices

XXXXXXXX        device

みたいに表示されていればOKです。

最初、deviceの箇所が「unauthorized」になっていましたが、実機に以下の確認メッセージが出ていたのに気づいていませんでした。。。

これをOKで本当にOKです!

f:id:ShunsukeKawai:20151013182848p:plain

 

Visual Studioからの起動

とうとう大詰め。

もう後は簡単です。

Visual Studio 2015を起動してXamarinのソリューションを開いてデバッグ先を先ほどの実機に指定して実行。

f:id:ShunsukeKawai:20151013184306p:plain

 

ドキドキ。

 

 

f:id:ShunsukeKawai:20151013184441p:plain

やったーーーーー!

 

今日はここまで。