티스토리 뷰

반응형
이 포스트의 내용은 Summary of Chapter 9. Platform-specific API calls (https://docs.microsoft.com/en-us/xamarin/xamarin-forms/creating-mobile-apps-xamarin-forms/summaries/chapter09) 을 번역한 자료입니다. 한글로 표현하기 어색하거나 모호한 문장은 임의로 조정하거나 삭제하였으므로 필요한 경우 원문을 참고하시기 바랍니다. 또한 언제든지 원저자의 요청에 의해 게시물이 내려지거나 수정될 수 있음을 알려드립니다. 마지막으로 이 글은 개인적인 학습목적으로 번역한 자료이며, 따라서 오역이나 잘못된 해석이 포함되어 있을 수 있으며 이로인한 어떠한 일체의 보장을 하지 않습니다.

이 문서에서는 다음 주제를 다룹니다.

참고
이 페이지에서  참고 영역은  Xamarin.Forms 책의 내용에서 달라진 부분이 무엇인지 기술하고 있습니다.

이 챕터에서는 플렛폼 별로 서로 다르게 제공되는 API를 Xamarin.Forms에서 실행하는 방법을 소개합니다.

Shared Asset Project의 전처리기

Xamarin.Forms의 Shared Asset Project에서는 플렛폼 별로 서로 다른 코드를 C# 전처리기 #if, #elif, endif를 통해 실행가능합니다. 전처리기에 사용할 수 있는 심볼은 다음과 같습니다.

  • __IOS__ : iOS
  • __ANDROID__ : Android
  • WINDOWS_UWP : Universal Windows Platform
  • WINDOWS_APP : Windows 8.1
  • WINDOWS_PHONE_APP : Windows Phone 8.1

스마트폰 모델이나 버전 정보에 따라 다른 분기처리를 하는 방법은 플렛폼 별로 서로 다릅니다.

  • iOS: UIKit namespace 내부의 UIDevice 사용
  • Android: Android.OS namespace 내부의 Build Class 사용
  • Windows 플렛폼: Windows.Security.ExchangeActiveSyncProvisioning namespace의 EasClientDeviceInformation
using System;
using Xamarin.Forms;

//전처리기를 통한 플렛폼별 분기처리
#if __IOS__
using UIKit;
#elif __ANDROID__
using Android.OS;
#elif WINDOWS_APP || WINDOWS_PHONE_APP || WINDOWS_UWP
using Windows.Security.ExchangeActiveSyncProvisioning;
#endif

namespace PlatInfoSap1
{
    public partial class PlatInfoSap1Page : ContentPage
    {
        public PlatInfoSap1Page ()
        {
            InitializeComponent ();
#if __IOS__
            UIDevice device = new UIDevice();
            modelLabel.Text = device.Model.ToString();
            versionLabel.Text = String.Format("{0} {1}", device.SystemName, device.SystemVersion);
#elif __ANDROID__
            modelLabel.Text = String.Format("{0} {1}", Build.Manufacturer, Build.Model);
            versionLabel.Text = Build.VERSION.Release.ToString();
#elif WINDOWS_APP || WINDOWS_PHONE_APP || WINDOWS_UWP
            EasClientDeviceInformation devInfo = new EasClientDeviceInformation();
            modelLabel.Text = String.Format("{0} {1}", devInfo.SystemManufacturer, devInfo.SystemProductName);
            versionLabel.Text = devInfo.OperatingSystem;
#endif
        }
    }
}

PlatInfoSap1 샘플은 이에 대해 다룹니다.
SAP 전처리기 사용 결
전처리기를 사용하는 코드는 보기에도 장황하고 코드 가독성에도 좋지 않다는 단점이 있습니다.

Shared Asset Project의 병렬클래스

SAP에서 플렛폼 별로 다른 코드를 실행하기 위해 전처리기를 사용하지 않고, 좀더 구조적으로 접근하는 방법은 PlatInfoSap2 샘플에서 소개하고 있습니다. 각 플렛폼 프로젝트에서 동일한 이름과 멤버를 가진 Class를 작성하였습니다. 그리고 SAP 프로젝트의 공통코드에서 해당 Class의 멤버를 호출하고 있습니다.

DependencyService와 Portable Class Library

참고
Portable Class Library는 .NET Standard Library로 대체되었습니다. 책에서 모든 샘플코드는 .NET Standard Library를 사용하도록 변경되었습니다.

SAP가 아니라 Xamarin.Forms 라이브러리 프로젝트를 사용하면 각 플렛폼 프로젝트의 API들을 호출할 수 없습니다. 따라서 PlatInfoSap과 같은 접근법은 Xamarin.Forms 라이브러리 프로젝트에서는 사용할 수 없습니다. 그러나 Xamarin.Forms는 DependencyService Class을 제공하며 .NET Reflection을 통해 플렛폼 프로젝트의 API를 Xamarin.Forms 라이브러리 프로젝트에서 호출 할 수 있게합니다.

DependencyService를 사용하려면 먼저 Xamarin.Forms 라이브러리 프로젝트에 interface를 생성해야 하고 필요한 멤버를 정의해야 합니다.

namespace DisplayPlatformInfo
{
    public interface IPlatformInfo
    {
        string GetModel();
        string GetVersion();
    }
}

각 플렛폼 프로젝트에서는 해당 interface를 구현해야 합니다. interface를 구현하는 class는 어셈블리 레벨에서 TextVariations를 사용하여야 합니다. DependencyAttribute의 매개변수에 interface를 구현한 Class의 type을 지정함으로써 Xamarin.Forms의 DependencyService는 .NET Reflection을 통해 접근할 수 있게 됩니다.

using System;
using UIKit;
using Xamarin.Forms;

//iOS에서 interface를 구현하는 예제, Dependency Attribute는 반드시 선언해야 한다
[assembly: Dependency(typeof(DisplayPlatformInfo.iOS.PlatformInfo))]
namespace DisplayPlatformInfo.iOS
{
    public class PlatformInfo : IPlatformInfo
    {
        UIDevice device = new UIDevice();
        public string GetModel()
        {
            return device.Model.ToString();
        }
        public string GetVersion()
        {
            return String.Format("{0} {1}", device.SystemName, device.SystemVersion);
        }
    }
}

Xamarin.Forms 라이브러리 프로젝트에서는 DependencyService Class의 Get 메서드를 사용하여 플렛폼 프로젝트에서 구현한 Class의 인스턴스를 얻을 수 있습니다.

IPlatformInfo platformInfo = DependencyService.Get<IPlatformInfo>();
modelLabel.Text = platformInfo.GetModel();
versionLabel.Text = platformInfo.GetVersion();

DisplayPlatformInfo 샘플에서 구현예제를 보실 수 있습니다.

Platform 별 사운드 발생

MonkeyTapWithSound 샘플은 MonkeyTap 프로그램에 비프 소리를 추가한 에제입니다. DepedencyService를 활용하였으며 각 플렛폼에서 소리를 발생시키는 API를 작성하였습니다.

댓글