티스토리 뷰

반응형

Windows Template Studio를 이용해서 UWP 앱 개발 시작하기 포스트에서 이어서, 활용 및 심화 과정 포스트를 시작 하도록 하겠습니다. 자세한 설명보다는 간단하게 개념을 정리하고, 상세 내용을 알기 위해서는 어디를 참고하면 되는지에 대한 정보 제공을 목표로 합니다.



1. 프로젝트 생성


File -> New -> Project -> Windows Template Studio -> Name : WTSSample1 -> OK -> Blank -> MVVM Basic -> Next 여기까지는 공통으로 하고, 


Suspend and Resume +, Background Task + 이름은 WTSBackgroundTask 2개를 선택하고 Create를 눌러서 완료 합니다.



2. 백그라운드 작업에 대한 변경 사항


Windows 10 Anniversary Update가 되면서, 추가된 기능 중에 하나 중 기존 Multi Process Model에서만 Background 작업을 할 수 있던 것을 Single Process Model에서도 가능하도록 했습니다. 이 기능을 수행하기 위해서 새로운 앱 라이프 사이클이 필요하게 되었고, Background activity with the Single Process Model 페이지를 참고하면 변경된 사항을 자세하게 확인 할 수 있습니다.


Windows 10 universal Windows platform (UWP) app lifecycle

백그라운드 작업으로 추천되는 작업은 Background Triggers, App Services, Background media playback, Extended Execution가 있습니다.


이제 코드를 추가해서, 확인을 하도록 하겠습니다. 아래 코드에 굵은 글씨대로 추가를 한 후에 앱을 실행 합니다.


App.xaml.cs


        public App()
        {
            InitializeComponent();

            EnteredBackground += App_EnteredBackground;
            Suspending += (s, e) =>
            {
                Debug.WriteLine("Suspending");
            };
            LeavingBackground += (s, e) =>
            {
                Debug.WriteLine("LeavingBackground");

            };
            Resuming += (s, e) =>
            {
                Debug.WriteLine("Resuming");

            };

            // Deferred execution until used. Check https://msdn.microsoft.com/library/dd642331(v=vs.110).aspx for further info on Lazy<T> class.
            _activationService = new Lazy<ActivationService>(CreateActivationService);
        }


        private async void App_EnteredBackground(object sender, EnteredBackgroundEventArgs e)
        {
            var deferral = e.GetDeferral();
            Debug.WriteLine("EnteredBackground");
            await Helpers.Singleton<SuspendAndResumeService>.Instance.SaveStateAsync();
            deferral.Complete();
        }



Output 창 내용을 확인해 보면


LeavingBackground


라는 문자가 출력된 것을 볼 수 있습니다. 즉, 앱이 시작될 때부터 Background에서 시작한 것이라는 것을 알 수 있습니다. 


이제 Suspend를 상태로 변경해 보겠습니다.



Output 창을 보면 EnteredBackground 모드가 실행 된 후 쭈욱 내려가서 마지막에 Suspending이라는 글씨가 출력된 것을 볼 수 있습니다. 


Suspend 상태였다가 앱이 완전히 종료가 되던지, Resume으로 살아날 수 있습니다.

이번에는 Resume 상태로 변경해 보겠습니다.


LeavingBackground
EnteredBackground

'WTSSample.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'E:\samples\WTSSample\WTSSample\bin\x86\Debug\AppX\Newtonsoft.Json.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
...
'WTSSample.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'Anonymously Hosted DynamicMethods Assembly'.
Suspending


Suspending 뒤에 바로 Resuming과 LeveingBackground가 호출되면서 앱이 Activate되는 것을 확인 할 수 있습니다.


Suspending
The thread 0x10d4 has exited with code 0 (0x0).
Resuming
LeavingBackground




일단 기본적인 앱의 라이프사이클을 알 고 있어야, 백그라운드 작업을 만들고 이해하는데 도움이 되기 때문에 언급을 했으며, 추후 백그라운드 작업을 실제로 구현하는 내용은 나중에 다시 설명을 할 예정입니다.



3. 백그라운드 작업이 없을 때는 Suspend, Resume 상태로 변경될 때 무슨 작업을 하나요?


Suspend 상태가 될 때 현재 사용자가 보고 있는 화면의 상태를 저장했다가, Resume이 될 때 처음 상태대로 되 돌리는 작업을 추가 한다면, 앱의 사용자 경험을 높이는 좋은 앱의 기본이 되겠죠.


MainPage에 입력된 택스트 내용을 저장했다가, 앱이 시작했을 때 복구해 주는 방법을 간단하게 만들어 보겠습니다.


아래 내용을 추가합니다.


MainPage.xaml


        <Grid
            Grid.Row="1"
            Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
            <!--The SystemControlPageBackgroundChromeLowBrush background represents where you should place your content.
                Place your content here.-->
            <TextBox x:Name="SampleTextbox" VerticalAlignment="Center" HorizontalAlignment="Left" MinWidth="100"/>
        </Grid>


MainPage.xaml.cs


    public sealed partial class MainPage : Page
    {
        public MainViewModel ViewModel { get; } = new MainViewModel();

        public MainPage()
        {
            InitializeComponent();

            if (DesignMode.DesignModeEnabled) return;
            //백그라운드 모드로 전환되는 이벤트 핸들러 추가
            Singleton<SuspendAndResumeService>.Instance.OnBackgroundEntering += Instance_OnBackgroundEntering;

        }

        private void Instance_OnBackgroundEntering(object sender, OnBackgroundEnteringEventArgs e)
        {
            //백그라운드 모드로 전환되면, 입력된 텍스트를 저장합니다.
            e.SuspensionState.Data = SampleTextbox.Text;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //네비게이션 파라메터가 저장된 내용인지 확인합니다. 이 예제에서는 MainPage가 첫번째 페이지 이기 때문에 발생하지 않습니다.
            if (e.Parameter is SuspensionState == false) return;
            var para = (SuspensionState) e.Parameter;
            SampleTextbox.Text = para.Data.ToString();
        }

        public void SetParameter(SuspensionState saveStateSuspensionState)
        {
            //파라메터 값을 전달 받기 위해서 추가한 메서드 입니다.
            SampleTextbox.Text = saveStateSuspensionState.Data.ToString();
        }

    }



SuspendAndResumeService.cs


        private async Task RestoreStateAsync()
        {
            var saveState = await ApplicationData.Current.LocalFolder.ReadAsync<OnBackgroundEnteringEventArgs>(StateFilename);
            if (saveState?.Target != null && typeof(Page).IsAssignableFrom(saveState.Target))
            {
                //첫번째 페이지와 네비게이션 하려는 페이지가 동일하다면, false가 반환됩니다.
                if (NavigationService.Navigate(saveState.Target, saveState.SuspensionState) == false)
                {
                    //이 경우 프레임에 Content를 뷰로 형변환해서 강제로 파라메터를 전달 합니다.
                    //이 내용은 일반적인 내용이 아니기 때문에 필요에 의해서만 추가되어야 할 것입니다.
                    var view = NavigationService.Frame.Content as MainPage;
                    if (view == null) return;
                    view.SetParameter(saveState.SuspensionState);
                }

            }
        }



App.xaml.cs


            LeavingBackground += async (s, e) =>
            {
                Debug.WriteLine("LeavingBackground");
                var deferral = e.GetDeferral();
                //저장된 내용의 복구를 시도합니다.
                await Singleton<SuspendAndResumeService>.Instance.HandleAsync(e);
                deferral.Complete();

            };


결과 화면 입니다. 한번 입력한 내용이 앱을 재시작 해도 계속 나타납니다.



생각나는데로 하나씩 올리도록 하겠습니다...


반응형
댓글