Windows Phone 8 - Runtime Location API - 2

Windows Phone 8 - Runtime Location API - 2

在<Windows Phone 8 - Runtime Location API - 1>介紹基本的APIs資訊與操作元件,裡面介紹面的內谷主要專注

在於App需在前景模式下,如果您希望App是做像常見的,例如:美食導航、慢跑路線、約會地點連結…等,

那麼接下來該篇將討論如何在背景模式下持續取得座標資訊的能力。

 

[觀念]

‧WP上的App如果不在前景運作中(例如:開其他程式或按Start鍵回到桌面),該App是被暫停的;

    如果其他App需要更大的Memory被暫停的App可能會被關閉或進入tombstoned的;

    參考資料<App activation and deactivation for Windows Phone>。

‧WP8允許如果app屬於「location-tracking」類型,它被允許在背景模式下持續進行,這個與Background Agent

    屬於不同的處理機制。

‧實作「location-tracking」類型的App,自動支援Fast resume特性。

    參考<Fast app resume for Windows Phone 8>或<Windows Phone 8 – Launch Apps與Fast Resume>。

‧由於app是執行於行動設備上,電力的考量是最重要的部分,所以在App執行於背景時需要特別注意:

    a. 最小化次數/數量的網路請求;

        =>如果可以的話,應統合所有請求改用批次的方式或是固定時間區間來發出請求。

    b. 如果使用TimerDispatcherTimer物件只為了更新前景的UI,請不要使用;

    c. 停止使用所有的XAML動畫;

    d. 如果App並非常時間需要做背景執行,可以搭配PositionChanged與StatusChanged的事件來停止座標追踨;

 

 

[背景可用APIs]

‧背景執行的App具有些限制但也有開發一些可用的APIs,

   可參考<Features that can be used while running in the background for Windows Phone 8>。

   例如:ShellToast、ApplicationModel.Store、Speech.Synthesis、Notification、IsolatedStorage、HttpWebRequest、Sockets…等。

 

 

〉Location-tracking被系統通知Deactivation的條件

    WP為了維持系統的穩定性,雖允許Location-Tracking類型的App可在背景執行,但具某些條件時系統會通知

Deactivated事件給App加以關閉。Deactivated事件就跟一般應用程式在前景模式收到Deactivated事件相同,這點與

Background Agent是不同的。

 

根據<Running location-tracking apps in the background for Windows Phone 8>中介紹,被通知Deactivated的條件:

 

‧App本身停止座標追蹤能力。App可在PositionChangedStatusChanged事件搭配GeolocatorGeoCoordinateWatcher

    停止持續座標追蹤。

‧App處於背景執行4個小時,但沒有用戶加以互動。

‧省電模式被啟動。

‧設備記憶體過低。

‧用戶關閉了設備的位置服務。

‧其他應用程式開始在背景模式執行。

 

這些條件發生後系統觸發Deactivated事件,可搭配事件中的Reason參數來加以了解是什麼狀態。

在撰寫好的App時這些條件最好均要測試,以免在送審過程被退件。

 

 

有了以上的觀念後,往下便來看看<How to run location-tracking apps in the background for Windows Phone 8>要怎麼實作吧。

 

A. 在WMAppManifest.xml宣告必要的特性 ID_CAP_LOCATION與設定DefaultTask具有<BackgroundExecution />

      image

      在<DefaultTask />中宣告該App支援Background模式下的任務:

<Tasks>
  <DefaultTask Name="_default" NavigationPage="MainPage.xaml">
    <!-- 宣告為BackgroundExecution,固定的Name = LocationTracking -->
    <BackgroundExecution>
      <ExecutionType Name="LocationTracking" />
    </BackgroundExecution>
  </DefaultTask>
</Tasks>

      宣告使用的是<BackgroundExecution />與<BackgroundServiceAgent />二者不同,

      並且使用固定的Type Name:LocationTracking

 

 

B. 在App.xaml中覆寫 shell:PhoneApplicationService 中的RunningInBackground事件

     在一般的App裡 shell:PhoneApplicationService僅註冊了四個事件:Launching、Closing、Activated與Deactivated。

     在此,增加了新的事件處理:RunningInBackground。它主要觸發於當App執行於背景模式時。

     目前僅開放在location-aware型的App才可以有這樣的功能。那麼一來需要將App.xaml修改成如下:

<Application.ApplicationLifetimeObjects>
   <!--Required object that handles lifetime events for the application-->
   <shell:PhoneApplicationService
       Launching="Application_Launching" Closing="Application_Closing"
       Activated="Application_Activated" Deactivated="Application_Deactivated"
       RunningInBackground="Application_RunningInBackground"/>
</Application.ApplicationLifetimeObjects>

 

 

C. 實作最重要的RunningInBackground事件

    在App.xaml.cs中宣告二個重要的變數:

    ‧Geolocator:用於同時儲存App在前景與背景模式下所取得座標資訊;

    ‧RunningInBackground:用於識別目前處於前景或背景模式下;

     有了這二個變數的使用,便在Application_Activated與Application_RunningInBackground分別

     設定RunningInBackground的變數值,如下:

private void Application_RunningInBackground(object sender, RunningInBackgroundEventArgs args)
{
    RunningInBackground = true;
    // 當進入背景模式時,要記把相關UI更新或動畫全部取消;
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
    RunningInBackground = false;
    // 回到前景時,則設定關閉背景的執行任務,以節省電力
}

     為何不寫在Application_Launch呢?因為有可能用戶是從暫存區開啟程式它就不會經過Launch, 而Activated則不管是第一次開啟或

     從暫存區返回均可以使用。

 

 

D. 根據範例建立一個Page用於放置當Geolocator取得座標資訊時用於顯示座標的畫面

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <StackPanel>
        <TextBlock x:Name="LatitudeTextBlock" Text="latitude"/>
        <TextBlock x:Name="LongitudeTextBlock" Text="longitude"/>
    </StackPanel>
</Grid>

 

 

E. 在該Page的OnNavigatedTo時,實例化Geolocator並註冊PositionChanged的事件

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);
 
    // 實例化宣告於App.xaml的Geolocator
    if (App.Geolocator == null)
    {
        App.Geolocator = 
                new Windows.Devices.Geolocation.Geolocator();
        App.Geolocator.DesiredAccuracy =
                 Windows.Devices.Geolocation.PositionAccuracy.High;
        App.Geolocator.MovementThreshold = 100;
        App.Geolocator.PositionChanged += Geolocator_PositionChanged;
    }
}

 

 

F. 實作在PositionChanged事件下,前景模式更新畫面中的資料、背景模式下透過ShellToast通知座標已更新

void Geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    if (App.RunningInBackground == false)
    {
        //代表處於前景畫面可以直接更新畫面;
        Dispatcher.BeginInvoke(() =>
        {
            LatitudeTextBlock.Text = args.Position.Coordinate.Latitude.ToString("0.00");
            LongitudeTextBlock.Text = args.Position.Coordinate.Longitude.ToString("0.00");
        });
    }
    else
    {
        //代表處於背景模式,僅能利用ShellToas來通知;
        Microsoft.Phone.Shell.ShellToast toast = new Microsoft.Phone.Shell.ShellToast();
        toast.Content =string.Format("{0},{1}",
            args.Position.Coordinate.Latitude.ToString("0.00"),
            args.Position.Coordinate.Longitude.ToString("0.00"));
        toast.Title = "Location: ";
        toast.NavigationUri = new Uri("/Page2.xaml", UriKind.Relative);
        toast.Show();
    }            
}

 

 

G. 覆寫重要的事件PhoneApplicationPage.OnRemovedFromJournal

    為什麼需要覆寫這樣的功能呢?為了就是當我們實作的Page是用於支援LocationTracking時,該頁如果被關閉時,

註冊於該頁擷取Geolocator的事件需要被取消,以免造成不同Thread的Exception問題。而該事件會被呼叫,也代表該

Page已經被呼叫從journal移除掉了,例如:呼叫RemoveBackEntry()事件之後。

protected override void OnRemovedFromJournal(JournalEntryRemovedEventArgs e)
{
    //在該Page被移除之前,先取消註冊處理PositionChanged的事件
    App.Geolocator.PositionChanged -= Geolocator_PositionChanged;
    App.Geolocator = null;
 
    base.OnRemovedFromJournal(e);
}

 

 

[執行畫面]

444(背景模式)555(前景模式)

測試的方式我是使用Emulator加上Additional Tools一起模擬目前移動的座標位置。相關於如何使用Additional Tool來模擬座標,

可參以下的步驟:

image

 

[範例程式]

======

以上是分享如何實作LocationTracking的App,其中內容主要擷取MSDN上的內容來加以說明,

希望對大家有所幫助。

 

References

Location for Windows Phone 8

How to get the phone's current location for Windows Phone 8

How to continuously track the phone's location for Windows Phone 8

How to run location-tracking apps in the background for Windows Phone 8 (重要)

Location Sample for Windows Phone 8

Location Service Sample

NET Location API for Windows Phone 8.

Acquiring a single Geoposition in Windows Phone 8

Windows Phone 8 and Windows 8 platform comparison

Using the Location API in Your Windows Phone 8 Applications

Features that can be used while running in the background for Windows Phone 8

Fast app resume for Windows Phone 8 (重要)

App activation and deactivation for Windows Phone (重要)

Features that can be used while running in the background for Windows Phone 8 (重要)

Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 1

Maps in Windows Phone 8 and Phone toolkit: a winning team – Part 2

 

Dotblogs 的標籤: