다음을 통해 공유


4부 - 다중 플랫폼 처리

플랫폼 차이 및 기능 처리

차이는 단지 '플랫폼 간' 문제가 아닙니다. '동일한' 플랫폼의 디바이스에는 다양한 기능(특히 사용할 수 있는 다양한 Android 디바이스)이 있습니다. 가장 명백하고 기본적인 것은 화면 크기이지만 다른 디바이스 특성은 다를 수 있으며 애플리케이션이 특정 기능에 대해 검사 현재 상태(또는 부재)에 따라 다르게 동작하도록 요구할 수 있습니다.

즉, 모든 애플리케이션은 기능의 정상적인 저하를 처리하거나, 그렇지 않으면 매력적이지 않은 가장 낮은 공통 분모 기능 집합을 제공해야 합니다. Xamarin은 각 플랫폼의 네이티브 SDK와 긴밀하게 통합되어 애플리케이션이 플랫폼별 기능을 활용할 수 있으므로 이러한 기능을 사용하도록 앱을 디자인하는 것이 좋습니다.

플랫폼 기능이 어떻게 다른지에 대한 개요는 플랫폼 기능 설명서를 참조하세요.

플랫폼 차이의 예

플랫폼 간에 존재하는 기본 요소

범용 모바일 애플리케이션의 몇 가지 특성이 있습니다. 이러한 개념은 일반적으로 모든 디바이스에 적용되므로 애플리케이션 디자인의 기초를 형성할 수 있는 상위 수준 개념입니다.

  • 탭 또는 메뉴를 통한 기능 선택
  • 데이터 목록 및 스크롤
  • 데이터의 단일 보기
  • 데이터의 단일 보기 편집
  • 뒤로 이동

높은 수준의 화면 흐름을 디자인할 때 이러한 개념에 대한 일반적인 사용자 환경을 기반으로 할 수 있습니다.

플랫폼별 특성

모든 플랫폼에 존재하는 기본 요소 외에도 디자인의 주요 플랫폼 차이를 해결해야 합니다. 이러한 차이점을 고려(및 특히 처리하기 위해 코드를 작성)해야 할 수 있습니다.

  • 화면 크기 – 일부 플랫폼(예: iOS 및 이전 Windows 전화 버전)에는 대상으로 비교적 간단한 표준화된 화면 크기가 있습니다. Android 디바이스에는 다양한 화면 크기가 있으므로 애플리케이션에서 지원하기 위해 더 많은 노력이 필요합니다.
  • 탐색 비유 – 플랫폼(예: 하드웨어 '뒤로' 단추, Panorama UI 컨트롤) 및 플랫폼(Android 2 및 4, i전화 vs iPad) 간에 다릅니다.
  • 키보드 – 일부 Android 디바이스에는 물리적 키보드가 있고 다른 디바이스에는 소프트웨어 키보드만 있습니다. 소프트 키보드가 화면의 일부를 가리는 경우를 감지하는 코드는 이러한 차이점에 민감해야 합니다.
  • 터치 및 제스처 – 제스처 인식에 대한 운영 체제 지원은 특히 이전 버전의 각 운영 체제에서 다양합니다. 이전 버전의 Android는 터치 작업에 대한 지원이 매우 제한적이므로 이전 디바이스를 지원하려면 별도의 코드가 필요할 수 있습니다.
  • 푸시 알림 – 각 플랫폼에 다양한 기능/구현이 있습니다(예: Windows의 라이브 타일).

디바이스별 기능

애플리케이션에 필요한 최소 기능을 결정합니다. 또는 각 플랫폼에서 활용할 추가 기능을 결정할 때 기능을 검색하고 기능을 사용하지 않도록 설정하거나 대안을 제공하는 코드가 필요합니다(예: 지리적 위치에 대한 대안은 사용자가 위치를 입력하거나 지도에서 선택할 수 있도록 하는 것일 수 있음).

  • 카메라 – 장치마다 기능이 다릅니다. 일부 장치에는 카메라가 없고, 다른 장치에는 전면 및 후면 카메라가 모두 있습니다. 일부 카메라는 비디오 녹화가 가능합니다.
  • 지리적 위치 및 지도 – GPS 또는 Wi-Fi 위치에 대한 지원은 모든 디바이스에 없습니다. 또한 앱은 각 메서드에서 지원하는 다양한 수준의 정확도를 충족해야 합니다.
  • 가속도계, 자이로스코프 및 나침반 – 이러한 기능은 종종 각 플랫폼의 장치 선택에서만 찾을 수 있으므로 하드웨어가 지원되지 않는 경우 앱은 거의 항상 대체 기능을 제공해야 합니다.
  • Twitter 및 Facebook – iOS5 및 iOS6에서는 각각 '기본 제공'만 가능합니다. 이전 버전 및 기타 플랫폼에서는 각 서비스의 API와 직접 고유한 인증 기능 및 인터페이스를 제공해야 합니다.
  • NFC(근거리 통신) – (일부) Android 휴대폰(쓰기 시)에서만 가능합니다.

플랫폼 차이 처리

동일한 코드 기반의 여러 플랫폼을 지원하는 방법에는 각각 고유한 이점과 단점이 있는 두 가지 방법이 있습니다.

  • 플랫폼 추상화 – 비즈니스 외관 패턴은 플랫폼 간에 통합된 액세스를 제공하고 특정 플랫폼 구현을 단일 통합 API로 추상화합니다.
  • 다양한 구현 – 인터페이스 및 상속 또는 조건부 컴파일과 같은 아키텍처 도구를 통해 다양한 구현을 통해 특정 플랫폼 기능을 호출합니다.

플랫폼 추상화

클래스 추상화

공유 코드에 정의되고 플랫폼별 프로젝트에서 구현되거나 확장된 인터페이스 또는 기본 클래스를 사용합니다. 클래스 추상화로 공유 코드를 작성하고 확장하는 것은 사용 가능한 프레임워크의 하위 집합이 제한되어 있고 플랫폼별 코드 분기를 지원하는 컴파일러 지시문을 포함할 수 없기 때문에 이식 가능한 클래스 라이브러리에 특히 적합합니다.

인터페이스

인터페이스를 사용하면 공유 라이브러리에 전달될 수 있는 플랫폼별 클래스를 구현하여 공통 코드를 활용할 수 있습니다.

인터페이스는 공유 코드에 정의되고 공유 라이브러리에 매개 변수 또는 속성으로 전달됩니다.

그런 다음 플랫폼별 애플리케이션은 인터페이스를 구현하고 공유 코드를 활용하여 '처리'할 수 있습니다.

장점

구현에는 플랫폼별 코드가 포함될 수 있으며 플랫폼별 외부 라이브러리도 참조할 수 있습니다.

단점

구현을 만들고 공유 코드에 전달해야 합니다. 인터페이스가 공유 코드 내에서 깊이 사용되는 경우 여러 메서드 매개 변수를 통해 전달되거나 호출 체인을 통해 푸시다운됩니다. 공유 코드에서 다양한 인터페이스를 사용하는 경우 모든 인터페이스를 만들고 공유 코드에서 어딘가에 설정해야 합니다.

상속

공유 코드는 하나 이상의 플랫폼별 프로젝트에서 확장할 수 있는 추상 또는 가상 클래스를 구현할 수 있습니다. 인터페이스를 사용하는 것과 비슷하지만 일부 동작은 이미 구현되어 있습니다. 인터페이스 또는 상속이 더 나은 디자인 선택인지에 대한 다양한 관점이 있습니다. 특히 C#은 단일 상속만 허용하기 때문에 API를 설계할 수 있는 방법을 결정할 수 있습니다. 상속을 주의해서 사용합니다.

인터페이스의 장점과 단점은 상속에 동일하게 적용되며, 기본 클래스에 일부 구현 코드(선택적으로 확장될 수 있는 전체 플랫폼 제약 없는 구현)를 포함할 수 있다는 추가적인 이점이 있습니다.

Xamarin.Forms

Xamarin.Forms 설명서를 참조하세요.

기타 플랫폼 간 라이브러리

이러한 라이브러리는 C# 개발자를 위한 플랫폼 간 기능도 제공합니다.

조건부 컴파일

공유 코드가 각 플랫폼에서 다르게 작동해야 하는 경우도 있으며, 다르게 동작하는 클래스 또는 기능에 액세스할 수 있습니다. 조건부 컴파일은 서로 다른 기호가 정의된 여러 프로젝트에서 동일한 원본 파일을 참조하는 공유 자산 프로젝트에서 가장 적합합니다.

Xamarin 프로젝트는 항상 iOS 및 Android 애플리케이션 프로젝트 모두에 적합한 것을 정의 __MOBILE__ 합니다(이러한 기호에 대한 이중 밑줄 사전 및 사후 수정 참고).

#if __MOBILE__
// Xamarin iOS or Android-specific code
#endif

iOS

Xamarin.iOS는 iOS 디바이스를 __IOS__ 검색하는 데 사용할 수 있는 항목을 정의합니다.

#if __IOS__
// iOS-specific code
#endif

시계 및 TV 관련 기호도 있습니다.

#if __TVOS__
// tv-specific stuff
#endif

#if __WATCHOS__
// watch-specific stuff
#endif

Android

Xamarin.Android 애플리케이션으로만 컴파일해야 하는 코드는 다음을 사용할 수 있습니다.

#if __ANDROID__
// Android-specific code
#endif

또한 각 API 버전은 새 컴파일러 지시문을 정의하므로 이와 같은 코드를 사용하면 최신 API가 대상으로 지정된 경우 기능을 추가할 수 있습니다. 각 API 수준에는 모든 '하위' 수준 기호가 포함됩니다. 이 기능은 여러 플랫폼을 지원하는 데 유용하지 않습니다. 일반적으로 기호로 __ANDROID__ 충분합니다.

#if __ANDROID_11__
// code that should only run on Android 3.0 Honeycomb or newer
#endif

Mac

Xamarin.Mac은 __MACOS__ macOS용으로만 컴파일하는 데 사용할 수 있는 항목을 정의합니다.

#if __MACOS__
// macOS-specific code
#endif

UWP(유니버설 Windows 플랫폼)

WINDOWS_UWP을 사용합니다. Xamarin 플랫폼 기호와 같은 문자열을 둘러싼 밑줄이 없습니다.

#if WINDOWS_UWP
// UWP-specific code
#endif

조건부 컴파일 사용

조건부 컴파일의 간단한 사례 연구 예제는 SQLite 데이터베이스 파일의 파일 위치를 설정하는 것입니다. 세 플랫폼은 파일 위치를 지정하기 위한 요구 사항이 약간 다릅니다.

  • iOS – Apple은 사용자가 아닌 데이터를 특정 위치(라이브러리 디렉터리)에 배치하는 것을 선호하지만 이 디렉터리에 대한 시스템 상수는 없습니다. 올바른 경로를 빌드하려면 플랫폼별 코드가 필요합니다.
  • Android – 반환된 Environment.SpecialFolder.Personal 시스템 경로는 데이터베이스 파일을 저장할 수 있는 위치입니다.
  • Windows 전화 – 격리된 스토리지 메커니즘은 전체 경로를 지정할 수 없으며 상대 경로 및 파일 이름만 지정할 수 있습니다.
  • 유니버설 Windows 플랫폼 – API를 사용합니다Windows.Storage.

다음 코드는 조건부 컴파일을 사용하여 각 플랫폼에 DatabaseFilePath 대해 올바른지 확인합니다.

public static string DatabaseFilePath
{
    get
    {
        var filename = "TodoDatabase.db3";
#if SILVERLIGHT
        // Windows Phone 8
        var path = filename;
#else

#if __ANDROID__
        string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
#else
#if __IOS__
        // we need to put in /Library/ on iOS5.1 to meet Apple's iCloud terms
        // (they don't want non-user-generated data in Documents)
        string documentsPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal); // Documents folder
        string libraryPath = Path.Combine (documentsPath, "..", "Library");
#else
        // UWP
        string libraryPath = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
#endif
#endif
        var path = Path.Combine(libraryPath, filename);
#endif
        return path;
    }
}

그 결과 SQLite 데이터베이스 파일을 각 플랫폼의 다른 위치에 배치하여 모든 플랫폼에서 빌드하고 사용할 수 있는 클래스가 생성됩니다.