rksoftware

Visual Studio とか C# とかが好きです

Xamarin Froms で写真を撮影する

Xamarin.Froms で写真を撮影するには MediaPlugin を使うのが簡単です。
[ MediaPlugin : https://github.com/jamesmontemagno/MediaPlugin ]

■ NuGet パッケージのインストール

・Forms プロジェクトを .NET Standard で作成します。
・NuGet から「xam.plugin.media」を共通プロジェクトとプラットフォーム毎のプロジェクト全てにインストールします。
※Android、と iOS のみで確認しています。

非常にシンプルに使えるので、上記リポジトリの readme に書かれたコードをコピペすればすぐに使えてしまいます。
ただ、折角なので日本語でコメントを入れてみましたので、良かったら参考にしてください。

■ 独自の試み

1 点独自の試みとして、撮影時に保存されたファイルをすぐに消すようにしています。
デバッグしているとどんどんファイルが増えていってしまうのが気になって。

■ コード

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        // UI の構築。 Plugin の使い方とは直接関係ない
        var sl = (StackLayout)(this.Content = new StackLayout() { VerticalOptions = LayoutOptions.Fill });
        var button1 = new Button() { Text = "Take Photo" };
        var image1 = new Image() { HorizontalOptions = LayoutOptions.Fill, VerticalOptions = LayoutOptions.Fill };
        sl.Children.Add(button1);
        sl.Children.Add(image1);

        // ボタンクリックイベント。 この中身が Plugin の使い方
        button1.Clicked += async (sender, e) =>
        {
            // Plugin の初期化。おまじない
            await Plugin.Media.CrossMedia.Current.Initialize();

            // カメラが使用可能で、写真が撮影可能かを判定。
            if (!Plugin.Media.CrossMedia.Current.IsCameraAvailable || !Plugin.Media.CrossMedia.Current.IsTakePhotoSupported)
            {
                // カメラが使用不可または写真が撮影不可の場合、終了
                return;
            }

            // カメラが起動し写真を撮影する。撮影した写真はストレージに保存され、ファイルの情報が return される
            var file = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
            {
                // ストレージに保存するファイル情報
                // すでに同名ファイルがある場合は、temp_1.jpg などの様に連番がつけられ名前の衝突が回避される
                Directory = "TempPhotos",
                Name = "temp.jpg"
            });

            // 端末のカメラ機能でユーザーが「キャンセル」した場合は、file が null となる
            if (file == null)
                return;

            // 今回独自に試してみた部分
            // ストレージに保存された社員ファイルの中身をメモリに読み込み、ファイルは削除してしまう
            var bytes = new Queue<byte>();
            using (var s = file.GetStream())
            {
                var length = s.Length;
                int b;
                while ((b = s.ReadByte()) != -1)
                    bytes.Enqueue((byte)b);
            }
            System.IO.File.Delete(file.Path);
            file.Dispose();

            // 写真を画面上の image 要素に表示する
            image1.Source = ImageSource.FromStream(() =>
            {
                // 元のサンプルはファイルから読み込んでいたが、
                // 今回独自にメモリからの表示を試している
                return new System.IO.MemoryStream(bytes.ToArray());
            });
        };
    }
}

たったこれだけで写真を撮影して画面上に表示できます。
素晴らしいですね。