시계 모드 만들기

이 가이드에서는 Android Wear 1.0용 사용자 지정 시계 얼굴 서비스를 구현하는 방법을 설명합니다. 디지털 워치 페이스 서비스를 빌드하기 위한 단계별 지침과 아날로그 스타일의 시계 얼굴을 만드는 코드가 더 많이 제공됩니다.

개요

이 연습에서는 사용자 지정 Android Wear 1.0 시계 얼굴을 만드는 데 필요한 필수 사항을 설명하기 위해 기본 시계 얼굴 서비스를 만듭니다. 초기 시계 얼굴 서비스는 현재 시간을 시간 및 분 단위로 표시하는 간단한 디지털 시계를 표시합니다.

Screenshot shows the initial digital watch face.

이 디지털 시계 얼굴을 개발하고 테스트한 후에는 세 손으로 더 정교한 아날로그 시계 얼굴로 업그레이드하기 위해 더 많은 코드가 추가됩니다.

Screenshot shows the final analog watch face.

시계 얼굴 서비스가 번들로 묶이고 Wear 1.0 앱의 일부로 설치됩니다. 다음 예제 MainActivity 에서는 Watch 얼굴 서비스를 패키징하고 앱의 일부로 스마트 워치에 배포할 수 있도록 Wear 1.0 앱 템플릿의 코드만 포함합니다. 실제로 이 앱은 디버깅 및 테스트를 위해 Wear 1.0 디바이스(또는 에뮬레이터)에 로드된 시계 얼굴 서비스를 가져오기 위한 수단으로만 사용됩니다.

요구 사항

조사식 얼굴 서비스를 구현하려면 다음이 필요합니다.

Android 5.0은 조사식 얼굴 서비스를 구현하기 위한 최소 API 수준이지만 Android 5.1 이상을 사용하는 것이 좋습니다. Android 5.1(API 22) 이상을 실행하는 Android Wear 디바이스를 사용하면 디바이스가 저전력 앰비언트 모드인 동안 Wear 앱이 화면에 표시되는 내용을 제어할 수 있습니다. 디바이스가 저전력 앰비언트 모드를 벗어나면 대화형 모드입니다. 이러한 모드에 대한 자세한 내용은 앱 표시 유지를 참조하세요.

앱 프로젝트 시작

WatchFace라는 새 Android Wear 1.0 프로젝트를 만듭니다(새 Xamarin.Android 프로젝트를 만드는 방법에 대한 자세한 내용은 Hello, Android 참조).

패키지 이름을 다음으로 com.xamarin.watchface설정합니다.

또한 아래로 스크롤하여 인터넷WAKE_LOCK 권한을 사용하도록 설정합니다.

Required permissions

다음으로, preview.png 다운로드합니다. 이 작업은 이 연습의 뒷부분에 있는 drawables 폴더에 추가됩니다.

Xamarin.Android Wear 패키지 추가

NuGet 패키지 관리자 시작합니다(Visual Studio에서 솔루션 탐색기 참조 를 마우스 오른쪽 단추로 클릭하고 NuGet 패키지 관리 선택...). 프로젝트를 안정적인 최신 버전의 Xamarin.Android.Wear로 업데이트합니다.

NuGet Package Manager add

다음으로 Xamarin.Android.Support.v13 이 설치되어 있으면 제거합니다.

NuGet Package Manager remove

Wear 디바이스 또는 에뮬레이터에서 앱을 빌드하고 실행합니다(이 작업을 수행하는 방법에 대한 자세한 내용은 시작 가이드 참조). 착용 디바이스에 다음 앱 화면이 표시됩니다.

App screenshot

이 시점에서 기본 착용 앱은 아직 시계 얼굴 서비스 구현을 제공하지 않기 때문에 시계 얼굴 기능이 없습니다. 이 서비스는 다음에 추가됩니다.

CanvasWatchFaceService

Android Wear는 클래스를 통해 시계 얼굴을 구현합니다 CanvasWatchFaceService . CanvasWatchFaceServiceWatchFaceService은 다음 다이어그램에 표시된 대로 파생되는 WallpaperService 파생된 것입니다.

Inheritance Diagram

CanvasWatchFaceService 에는 중첩된 CanvasWatchFaceService.Engine개체가 포함되어 있으며, 조사식 얼굴을 그리는 실제 작업을 수행하는 개체를 인스턴스화 CanvasWatchFaceService.Engine 합니다. CanvasWatchFaceService.Engine 는 위 다이어그램에 표시된 대로 파생 WallpaperService.Engine 됩니다.

이 다이어그램에 표시되지 않는 것은 CanvasCanvasWatchFaceService 시계 얼굴을 그리는 데 사용하는 것입니다. 이는 Canvas 아래 설명된 대로 메서드를 OnDraw 통해 전달됩니다.

다음 섹션에서는 다음 단계에 따라 사용자 지정 조사식 얼굴 서비스를 만듭니다.

  1. 에서 CanvasWatchFaceService파생되는 클래스를 MyWatchFaceService 정의합니다.

  2. 내에서 MyWatchFaceService파생된 중첩 클래스를 MyWatchFaceEngine 만듭니다 CanvasWatchFaceService.Engine.

  3. 에서 MyWatchFaceService인스턴스화 MyWatchFaceEngine 하고 반환하는 메서드를 구현 CreateEngine 합니다.

  4. 에서 MyWatchFaceEngine조사식 얼굴 스타일을 만들고 다른 초기화 작업을 수행하는 메서드를 구현 OnCreate 합니다.

  5. 의 메서드를 OnDraw 구현합니다 MyWatchFaceEngine. 이 메서드는 시계 얼굴을 다시 그려야 할 때마다 호출됩니다(즉, 무효화됨). OnDraw 는 시계 얼굴 요소(예: 시간, 분 및 초침)를 그리는(및 다시 그리기) 메서드입니다.

  6. 의 메서드를 OnTimeTick 구현합니다 MyWatchFaceEngine. OnTimeTick 는 분당 한 번 이상(앰비언트 모드 및 대화형 모드 모두) 또는 날짜/시간이 변경된 경우 호출됩니다.

자세한 CanvasWatchFaceService내용은 Android CanvasWatchFaceService API 설명서를 참조하세요. 마찬가지로 CanvasWatchFaceService.Engine 은 시계 얼굴의 실제 구현을 설명합니다.

CanvasWatchFaceService 추가

MyWatchFaceService.cs이라는 새 파일을 추가합니다(Visual Studio에서 솔루션 탐색기 WatchFace를 마우스 오른쪽 단추 클릭하고 새 항목 추가 > 를 클릭하고 클래스를 선택합니다.)

이 파일의 내용을 다음 코드로 바꿉니다.

using System;
using Android.Views;
using Android.Support.Wearable.Watchface;
using Android.Service.Wallpaper;
using Android.Graphics;

namespace WatchFace
{
    class MyWatchFaceService : CanvasWatchFaceService
    {
        public override WallpaperService.Engine OnCreateEngine()
        {
            return new MyWatchFaceEngine(this);
        }

        public class MyWatchFaceEngine : CanvasWatchFaceService.Engine
        {
            CanvasWatchFaceService owner;
            public MyWatchFaceEngine (CanvasWatchFaceService owner) : base(owner)
            {
                this.owner = owner;
            }
        }
    }
}

MyWatchFaceService(파생)CanvasWatchFaceService 는 시계 얼굴의 "기본 프로그램"입니다. MyWatchFaceService 는 하나의 메서드만 구현합니다. 이 메서드 OnCreateEngine는 개체를 인스턴스화하고 반환 MyWatchFaceEngine 합니다(MyWatchFaceEngine 파생됨 CanvasWatchFaceService.Engine). 인스턴스화된 MyWatchFaceEngine 개체는 .로 WallpaperService.Engine반환되어야 합니다. 캡슐화 MyWatchFaceService 개체가 생성자에 전달됩니다.

MyWatchFaceEngine 는 실제 시계 얼굴 구현입니다. 시계 얼굴을 그리는 코드가 포함되어 있습니다. 또한 화면 변경(앰비언트/대화형 모드, 화면 끄기 등)과 같은 시스템 이벤트를 처리합니다.

Engine OnCreate 메서드 구현

이 메서드는 OnCreate 조사식 얼굴을 초기화합니다. 다음 필드를 다음 필드에 추가합니다 MyWatchFaceEngine.

Paint hoursPaint;

Paint 개체는 시계 얼굴에 현재 시간을 그리는 데 사용됩니다. 다음으로 다음 메서드를 다음 메서드에 추가합니다 MyWatchFaceEngine.

public override void OnCreate(ISurfaceHolder holder)
{
    base.OnCreate (holder);

    SetWatchFaceStyle (new WatchFaceStyle.Builder(owner)
        .SetCardPeekMode (WatchFaceStyle.PeekModeShort)
        .SetBackgroundVisibility (WatchFaceStyle.BackgroundVisibilityInterruptive)
        .SetShowSystemUiTime (false)
        .Build ());

    hoursPaint = new Paint();
    hoursPaint.Color = Color.White;
    hoursPaint.TextSize = 48f;
}

OnCreate 는 시작된 직후 MyWatchFaceEngine 에 호출됩니다. Wear 디바이스가 WatchFaceStyle 사용자와 상호 작용하는 방식을 제어하는 설정 및 시간을 표시하는 데 사용할 개체를 인스턴스화 Paint 합니다.

호출 SetWatchFaceStyle 은 다음을 수행합니다.

  1. 미리 보기 모드PeekModeShort설정하여 알림이 디스플레이에 작은 "피킹" 카드 표시되도록 합니다.

  2. 백그라운드 표시 유형을 Interruptive설정합니다. 그러면 피킹 카드 배경이 중단 알림을 나타내는 경우에만 간략하게 표시됩니다.

  3. 사용자 지정 시계 얼굴이 대신 시간을 표시할 수 있도록 시계 얼굴에 기본 시스템 UI 시간이 그려지지 않도록 설정합니다.

이러한 및 기타 시계 얼굴 스타일 옵션에 대한 자세한 내용은 Android WatchFaceStyle.Builder API 설명서를 참조하세요.

SetWatchFaceStyle 완료되면 OnCreate 개체(hoursPaint)를 인스턴스화 Paint 하고 색을 흰색으로 설정하고 텍스트 크기를 48픽셀로 설정합니다(TextSize는 픽셀 단위로 지정해야 합니다).

Engine OnDraw 메서드 구현

OnDraw 메서드는 아마도 가장 중요한 CanvasWatchFaceService.Engine 방법일 것입니다. 숫자 및 시계 얼굴 손과 같은 시계 얼굴 요소를 실제로 그리는 방법입니다. 다음 예제에서는 시계 면에 시간 문자열을 그립니다. MyWatchFaceEngine에 다음 메서드를 추가합니다.

public override void OnDraw (Canvas canvas, Rect frame)
{
    var str = DateTime.Now.ToString ("h:mm tt");
    canvas.DrawText (str,
        (float)(frame.Left + 70),
        (float)(frame.Top  + 80), hoursPaint);
}

Android가 호출 OnDraw하면 얼굴을 그릴 수 있는 인스턴스와 범위를 전달 Canvas 합니다. 위의 코드 예제 DateTime 에서는 현재 시간을 시간 및 분(12시간 형식)으로 계산하는 데 사용됩니다. 결과 시간 문자열은 메서드를 사용하여 Canvas.DrawText 캔버스에 그려집니다. 문자열은 왼쪽 가장자리에서 70픽셀 이상, 위쪽 가장자리에서 80픽셀 아래로 표시됩니다.

메서드에 OnDraw 대한 자세한 내용은 Android onDraw API 설명서를 참조하세요.

Engine OnTimeTick 메서드 구현

Android는 주기적으로 메서드를 OnTimeTick 호출하여 시계 얼굴에 표시된 시간을 업데이트합니다. 앰비언트 모드와 대화형 모드 모두에서 분당 한 번 이상 호출되거나 날짜/시간 또는 표준 시간대가 변경된 경우 호출됩니다. MyWatchFaceEngine에 다음 메서드를 추가합니다.

public override void OnTimeTick()
{
    Invalidate();
}

이 구현은 OnTimeTick 단순히 호출 Invalidate합니다. 이 메서드는 Invalidate 조사식 얼굴을 다시 그리도록 예약 OnDraw 합니다.

이 메서드에 대한 OnTimeTick 자세한 내용은 Android onTimeTick API 설명서를 참조하세요.

CanvasWatchFaceService 등록

MyWatchFaceService 는 연결된 Wear 앱의 AndroidManifest.xml 등록해야 합니다. 이렇게 하려면 섹션에 다음 XML을 <application> 추가합니다.

<service
    android:name="watchface.MyWatchFaceService"
    android:label="Xamarin Sample"
    android:allowEmbedded="true"
    android:taskAffinity=""
    android:permission="android.permission.BIND_WALLPAPER">
    <meta-data
        android:name="android.service.wallpaper"
        android:resource="@xml/watch_face" />
    <meta-data
        android:name="com.google.android.wearable.watchface.preview"
        android:resource="@drawable/preview" />
    <intent-filter>
        <action android:name="android.service.wallpaper.WallpaperService" />
        <category android:name="com.google.android.wearable.watchface.category.WATCH_FACE" />
    </intent-filter>
</service>

이 XML은 다음을 수행합니다.

  1. android.permission.BIND_WALLPAPER 사용 권한을 설정합니다. 이 권한은 시계 얼굴 서비스에 디바이스의 시스템 배경 화면을 변경할 수 있는 권한을 부여합니다. 이 권한은 외부 <application> 섹션이 <service> 아닌 섹션에서 설정해야 합니다.

  2. 리소스를 watch_face 정의합니다. 이 리소스는 리소스를 선언하는 wallpaper 짧은 XML 파일입니다(이 파일은 다음 섹션에서 만들어집니다).

  3. 조사식 선택기 선택 화면에서 표시할 그리기 가능 이미지를 선언 preview 합니다.

  4. intent-filter 시계 얼굴을 표시할 것을 Android MyWatchFaceService 에 알리는 기능이 포함되어 있습니다.

기본 WatchFace 예제의 코드를 완료합니다. 다음 단계는 필요한 리소스를 추가하는 것입니다.

리소스 파일 추가

조사식 서비스를 실행하려면 먼저 watch_face 리소스와 미리 보기 이미지를 추가해야 합니다. 먼저 Resources/xml/watch_face.xml 새 XML 파일을 만들고 해당 내용을 다음 XML로 바꿉니다.

<?xml version="1.0" encoding="UTF-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android" />

이 파일의 빌드 작업을 AndroidResource설정합니다.

이 리소스 파일은 조사식 얼굴에 사용할 간단한 wallpaper 요소를 정의합니다.

아직 다운로드하지 않은 경우 preview.png 다운로드합니다. Resources/drawable/preview.png 설치합니다. 이 파일을 프로젝트에 추가해야 합니다 WatchFace . 이 미리 보기 이미지는 착용 장치의 시계 얼굴 선택기에서 사용자에게 표시됩니다. 사용자 고유의 시계 얼굴에 대한 미리 보기 이미지를 만들려면 시계가 실행되는 동안 시계 얼굴의 스크린샷을 찍을 수 있습니다. (Wear 디바이스에서 스크린샷을 가져오는 방법에 대한 자세한 내용은 다음을 참조하세요 .스크린샷을 찍는 중).

사용해 보세요.

앱을 빌드하고 Wear 디바이스에 배포합니다. 앱 착용 화면이 이전과 같이 표시됩니다. 다음을 수행하여 새 조사식 얼굴을 사용하도록 설정합니다.

  1. 시계 화면의 배경이 표시될 때까지 오른쪽으로 살짝 밉다.

  2. 화면 배경의 아무 곳이나 터치하고 2초 동안 길게 누릅니다.

  3. 왼쪽에서 오른쪽으로 살짝 밀어 다양한 시계 얼굴을 탐색합니다.

  4. Xamarin 샘플 시계 얼굴(오른쪽에 표시)을 선택합니다.

    Watchface Picker

  5. Xamarin 샘플 시계 얼굴을 탭하여 선택합니다.

이렇게 하면 Wear 디바이스의 시계 얼굴이 변경되어 지금까지 구현된 사용자 지정 시계 얼굴 서비스를 사용합니다.

Screenshot shows a custom digital watch running on Wear device.

앱 구현이 매우 미미하기 때문에 상대적으로 조잡한 시계 얼굴입니다(예: 시계 얼굴 배경을 포함하지 않으며 모양을 개선하기 위해 앤티앨리어스 메서드를 호출 Paint 하지 않음). 그러나 사용자 지정 시계 얼굴을 만드는 데 필요한 베어본 기능을 구현합니다.

다음 섹션에서 이 시계 얼굴은 보다 정교한 구현으로 업그레이드됩니다.

시계 얼굴 업그레이드

이 연습 MyWatchFaceService 의 re기본der에서는 아날로그 스타일의 시계 얼굴을 표시하도록 업그레이드되었으며 더 많은 기능을 지원하도록 확장되었습니다. 업그레이드된 시계 얼굴을 만들기 위해 다음 기능이 추가됩니다.

  1. 아날로그 시간, 분 및 초침을 사용하여 시간을 나타냅니다.

  2. 표시 유형 변경에 반응합니다.

  3. 앰비언트 모드와 대화형 모드 간의 변경 내용에 응답합니다.

  4. 기본 Wear 디바이스의 속성을 읽습니다.

  5. 표준 시간대 변경이 발생하는 시간을 자동으로 업데이트합니다.

아래 코드 변경 내용을 구현하기 전에 drawable.zip 다운로드하고 압축을 풀고 압축을 푼 .png 파일을 Resources/drawable로 이동합니다(이전 preview.png 덮어쓰기). 프로젝트에 새 .png 파일을 추가합니다 WatchFace .

엔진 기능 업데이트

다음 단계는 MyWatchFaceService.cs 아날로그 시계 얼굴을 그리고 새로운 기능을 지원하는 구현으로 업그레이드하는 것입니다. MyWatchFaceService.cs 내용을 MyWatchFaceService.cs 시계 얼굴 코드 의 아날로그 버전으로 바꿉니다(이 소스를 잘라내어 기존 MyWatchFaceService.cs 붙여넣을 수 있음).

이 버전의 MyWatchFaceService.cs 기존 메서드에 더 많은 코드를 추가하고 더 많은 기능을 추가하기 위해 재정의된 추가 메서드를 포함합니다. 다음 섹션에서는 소스 코드를 안내하는 둘러보기를 제공합니다.

OnCreate

업데이트 된 OnCreate 메서드는 이전과 같이 시계 얼굴 스타일을 구성하지만 몇 가지 추가 단계가 포함되어 있습니다.

  1. 배경 이미지를 Resources/drawable-hdpi/xamarin_background.png 있는 xamarin_background 리소스로 설정합니다.

  2. 시간 손, 분 손 및 초침을 그리기 위한 개체를 초기화 Paint 합니다.

  3. 시계 얼굴의 가장자리 주위에 시간 틱을 그리기 위한 개체를 초기화 Paint 합니다.

  4. 초가 1초마다 다시 그려지도록 (다시 그리기) 메서드를 호출 Invalidate 하는 타이머를 만듭니다. 이 타이머는 1분에 한 번만 호출 Invalidate 되므로 OnTimeTick 필요합니다.

이 예제에는 xamarin_background.png 이미지가 하나만 포함되어 있지만 사용자 지정 시계 얼굴이 지원하는 각 화면 밀도에 대해 다른 배경 이미지를 만들 수 있습니다.

Ondraw

업데이트된 OnDraw 메서드는 다음 단계를 사용하여 아날로그 스타일의 시계 얼굴을 그립니다.

  1. 개체에 기본 time 현재 시간을 가져옵니다.

  2. 그리기 표면과 그 가운데의 경계를 결정합니다.

  3. 배경을 그릴 때 디바이스에 맞게 배율 조정된 배경을 그립니다.

  4. 시계 얼굴 주위에 12개의 틱을 그립니다(시계 얼굴의 시간에 해당).

  5. 각 시계 손의 각도, 회전 및 길이를 계산합니다.

  6. 시계 표면에 각 손을 그립니다. 시계가 앰비언트 모드인 경우에는 초침이 그려지지 않습니다.

OnPropertiesChanged

이 메서드는 Wear 디바이스의 속성(예: 낮은 비트 앰비언트 모드 및 번인 보호)에 대해 알리 MyWatchFaceEngine 기 위해 호출됩니다. 이 메서드는 MyWatchFaceEngine낮은 비트 앰비언트 모드에 대해서만 검사(낮은 비트 앰비언트 모드에서는 화면이 각 색에 대해 더 적은 비트를 지원함).

이 방법에 대한 자세한 내용은 Android onPropertiesChanged API 설명서를 참조하세요.

OnAmbientModeChanged

이 메서드는 Wear 디바이스가 앰비언트 모드로 들어가거나 종료되면 호출됩니다. 구현에서 MyWatchFaceEngine 조사식 얼굴은 주변 모드일 때 앤티앨리어싱을 사용하지 않도록 설정합니다.

이 메서드에 대한 자세한 내용은 Android onAmbientModeChanged API 설명서를 참조하세요.

OnVisibilityChanged

이 메서드는 시계가 표시되거나 숨겨질 때마다 호출됩니다. 에서 MyWatchFaceEngine이 메서드는 표시 유형 상태에 따라 표준 시간대 수신기(아래에 설명됨)를 등록/등록 취소합니다.

이 방법에 대한 자세한 내용은 Android onVisibilityChanged API 설명서를 참조하세요.

표준 시간대 기능

MyWatchFaceService.cs 표준 시간대가 변경 될 때마다 현재 시간을 업데이트 하는 기능도 포함 됩니다 (예: 표준 시간대를 통해 이동 하는 동안). MyWatchFaceService.cs 끝부분에서 표준 시간대 변경 BroadcastReceiver 의도 개체를 처리하는 표준 시간대 변경이 정의됩니다.

public class TimeZoneReceiver: BroadcastReceiver
{
    public Action<Intent> Receive { get; set; }
    public override void OnReceive (Context context, Intent intent)
    {
        if (Receive != null)
            Receive (intent);
    }
}

UnregisterTimezoneReceiver 메서드는 RegisterTimezoneReceiver 메서드에 OnVisibilityChanged 의해 호출됩니다. UnregisterTimezoneReceiver 는 조사식 얼굴의 표시 상태가 숨김으로 변경될 때 호출됩니다. 조사식 얼굴이 다시 RegisterTimezoneReceiver 표시되면 호출됩니다(메서드 참조 OnVisibilityChanged ).

엔진 RegisterTimezoneReceiver 메서드는 이 표준 시간대 수신기 이벤트에 Receive 대한 처리기를 선언합니다. 이 처리기는 표준 시간대가 교차할 때마다 새 시간으로 개체를 업데이트합니다 time .

timeZoneReceiver = new TimeZoneReceiver ();
timeZoneReceiver.Receive = (intent) => {
    time.Clear (intent.GetStringExtra ("time-zone"));
    time.SetToNow ();
};

표준 시간대 수신기에 대한 의도 필터가 만들어지고 등록됩니다.

IntentFilter filter = new IntentFilter(Intent.ActionTimezoneChanged);
Application.Context.RegisterReceiver (timeZoneReceiver, filter);

이 메서드는 UnregisterTimezoneReceiver 표준 시간대 수신기의 등록을 취소합니다.

Application.Context.UnregisterReceiver (timeZoneReceiver);

향상된 시계 얼굴 실행

앱을 빌드하고 Wear 디바이스에 다시 배포합니다. 이전과 같이 시계 얼굴 선택기에서 시계 얼굴을 선택합니다. 시계 선택기에서 미리 보기가 왼쪽에 표시되고 새 시계 얼굴이 오른쪽에 표시됩니다.

Screenshot shows an improved analog face in picker and on device.

이 스크린샷에서는 초침이 초당 한 번 이동합니다. Wear 디바이스에서 이 코드를 실행하면 시계가 앰비언트 모드로 전환되면 초침이 사라집니다.

요약

이 연습에서는 사용자 지정 Android Wear 1.0 Watchface를 구현하고 테스트했습니다. CanvasWatchFaceService 클래스 및 CanvasWatchFaceService.Engine 클래스가 도입되었으며, 간단한 디지털 시계 얼굴을 만들기 위해 엔진 클래스의 필수 방법이 구현되었습니다. 이 구현은 아날로그 시계 얼굴을 만드는 더 많은 기능으로 업데이트되었으며, 표시 유형, 주변 모드 및 디바이스 속성의 차이를 처리하기 위해 추가 메서드가 구현되었습니다. 마지막으로 표준 시간대 브로드캐스트 수신기가 구현되어 시계가 표준 시간대가 교차하는 시간을 자동으로 업데이트합니다.