こんにちは。コタツです。
Macbookを購入して以来、iOSアプリの開発ができてうれしい毎日です。
今回はXamarin FormsでiOSのカメラロールへアクセスする方法を紹介します。
Xamarin Forms側
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; namespace CommonFunction { #region イベント /// <summary> /// 画像を取得するイベントです。 /// </summary> public class ImageEventArgs : EventArgs { public string ImagePath { set; get; } } /// <summary> /// 画像を取得するイベントハンドラです /// </summary> /// <param name="sender">イベントソース</param> /// <param name="args">イベントデータ</param> public delegate void ImageEventHandler(object sender, ImageEventArgs args); #endregion /// <summary> /// 画像を操作するインターフェースです。 /// </summary> public interface IImage { /// <summary> /// 画像を選択します。 /// </summary> void SelectImage(); /// <summary> /// 画像を取得するイベントです。 /// </summary> event ImageEventHandler ImageReceived; } } |
Xamarin Formsの「DependencyService」の機能を使用して実装します。「DependencyService」とはiOS/Androidの各プラットフォーム固有の機能を実装する方法ですが、「DependencyService」の説明に関してはここでは省かせていただきます。
Xamarin Forms側でインターフェースを定義します。「SelectImage()」メソッドでカメラロールを開いて「ImageEventHandler」でカメラロールで選択した写真のパスを取得する機能です。
iOS側
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Xamarin.Forms; using CommonFunction; using Foundation; using UIKit; using ObjCRuntime; using CoreGraphics; [assembly: Dependency(typeof(CImageCtrl_iOS))] namespace CommonFunction { public class CImageCtrl_iOS : IImage { #region 変数 private UIImagePickerController m_ImagePicker; /// <summary> /// ファイル一覧 /// </summary> private string[] m_Files; #endregion #region イベントハンドラ /// <summary> /// 画像を取得するイベントハンドラ /// </summary> public event ImageEventHandler ImageReceived; #endregion #region メソッド /// <summary> /// 画像を選択します。 /// </summary> public void SelectImage() { // カメラロールを選択します。 m_ImagePicker = new UIImagePickerController(); m_ImagePicker.SourceType = UIImagePickerControllerSourceType.PhotoLibrary; m_ImagePicker.MediaTypes = UIImagePickerController.AvailableMediaTypes(UIImagePickerControllerSourceType.PhotoLibrary); m_ImagePicker.FinishedPickingMedia += Handle_FinishedPickingMedia; m_ImagePicker.Canceled += Handle_Canceled; var window = UIApplication.SharedApplication.KeyWindow; var vc = window.RootViewController; while (vc.PresentedViewController != null) { vc = vc.PresentedViewController; } vc.PresentModalViewController(m_ImagePicker, false); } #endregion #region イベントハンドラ /// <summary> /// カメラロール選択時の処理をします。 /// </summary> /// <param name="sender">イベントソース</param> /// <param name="e">イベントデータ</param> protected void Handle_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e) { // 画像判別をします。 bool isImage = false; switch (e.Info[UIImagePickerController.MediaType].ToString()) { // 画像 case "public.image": isImage = true; break; // ビデオ case "public.video": break; } // 画像URLを取得します。 string imagePath = ""; if (isImage) { NSUrl referenceURL = e.Info[new NSString("UIImagePickerControllerReferenceUrl")] as NSUrl; if (referenceURL != null) { imagePath = referenceURL.ToString(); } else { UIImage originalImage = e.Info[UIImagePickerController.OriginalImage] as UIImage; imagePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); imagePath = imagePath + "/" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".PNG"; using (var data = originalImage.AsPNG()) { byte[] bytes = data.ToArray(); NSData myData = NSData.FromArray(bytes); myData.Save(imagePath, true); } } } else { NSUrl mediaURL = e.Info[UIImagePickerController.MediaURL] as NSUrl; if (mediaURL != null) { imagePath = mediaURL.ToString(); } } // イベントデータに保管します。 ImageEventArgs imageArgs = new ImageEventArgs { ImagePath = imagePath, }; // 画像取得イベントの終了を知らせます。 ImageReceived(null, imageArgs); m_ImagePicker.FinishedPickingMedia -= Handle_FinishedPickingMedia; m_ImagePicker.Canceled -= Handle_Canceled; //カメラロールを閉じます。 m_ImagePicker.DismissModalViewController(true); } /// <summary> /// カメラロールキャンセル時の処理をします。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void Handle_Canceled(object sender, EventArgs e) { m_ImagePicker.DismissModalViewController(true); } #endregion } } |
info.plist
権限を指定しなくて嵌りました。権限を指定していないとアプリは突然落ちます。最初はバグと思いデバックを繰り返したので原因は見つからず嵌っていたのですが、権限を付けたらすんなり動きました。
1 2 3 4 |
<key>NSPhotoLibraryUsageDescription</key> <string>ここに目的を書きます。</string> <key>UIImageWriteToSavedPhotosAlbum</key> <string>ここに目的を書きます。</string> |
上記の二行を追加してください。
Xamarin Formsでの呼び出し方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; namespace CommonFunction { /// <summary> /// 画像の処理をするクラスです。 /// </summary> public class CImageCtrl { #region プロパティ /// <summary> /// 画像取得クラスを設定または取得します。 /// </summary> public IImage ImageCtrl { get; set; } #endregion #region コンストラクタ /// <summary> /// 新しいインスタンスを生成します。 /// </summary> public CImageCtrl() { // 画像クラスを生成します。 ImageCtrl = DependencyService.Get<IImage>(); // 画像取得するイベントを定義します。 ImageCtrl.ImageReceived += OnSelectImageResult; } #endregion #region メソッド /// <summary> /// 画像を選択します。 /// </summary> public void SelectImage() { // 画像を選択します。 ImageCtrl.SelectImage(); } /// <summary> /// 画像選択結果を取得します。 /// </summary> /// <param name="sender">イベントソース。</param> /// <param name="args">イベントデータ。</param> public void OnSelectImageResult(object sender, ImageEventArgs args) { // カメラロールで選択した画像パスを取得 } #endregion } } |
まとめ
今回はXamarin Formsでカメラロールの画像取得方法を紹介しました。次回もiOSアプリ開発のネタを紹介いたします。