Windows Phone 7 - 存取聯絡人與行事曆資料
在WP 7.0的時候App要與聯絡人溝通需要透過Chooser的方式,例如:EmailAddressChooserTask、PhoneNumberChooserTask。
但是到了WP 7.1之後,針對存取聯絡人資料的功能更加強了,並且支援存取行事曆的資料。因此,隨著Mango更新之後便可以在
Marketplace看到很多結合聯絡人與行事曆相關的功能,包括:WhatsApp(存取聯絡人)、Tasks(存取行事曆)…等。
〉WP7.1 提供的匯總資料範圍(Aggregated Data Sources):
WP7.1 針對聯絡人/行事曆的部分提供了匯總的機制,將不同的帳號之間的聯絡人/行事曆資訊匯總起來,因此,資料來源可能包括:
原Windows Live ID聯絡人、系統中的連絡人/行事曆資訊、Facebook聯絡人或其他資料來源。然而,這些資料也不是全部都可以取得到,
需要依照該帳戶對應設定的公開(publicly)程度來決定。因此,在存取Contacts與Calendar API時,可以透過StorageKind enumeration來找
出可能存取的資料清單。
以下為MSDN所提供針對不同資料來源提供可存取的範圍表:
Data Provider | Contact Name | Contact Picture | Other contact data | Calendar appointments | StorageKind enumeration |
Windows Phone Device (資料來自電話本身,例如:sim卡聯絡電話) |
Yes | Yes | Yes | Yes |
Phone, 預設是取得該來源的資料內容。 |
Windows Live Social (資料來自Windows Live帳號) |
Yes | Yes | Yes | Yes | WindowsLive |
Windows Live Rolodex (資料來自Windows Live帳號) |
Yes | Yes | Yes | Yes | WindowsLive |
Exchange Accounts (Contacts are from the local address book only, not the global address list.)(資料來自Outlook帳號) |
Yes | Yes | Yes | Yes | Outlook |
Mobile Operator Address Book (資料來自其他的位置) |
Yes | Yes | Yes | No | Other |
Facebook (資料來自Facebook帳號) |
Yes | Yes | No | No | |
Windows Live Aggregated Networks (Twitter, LinkedIn, and so on)(由Windows Live匯總的其他帳號來源,例如:Twitter等) | No | No | No | No | None |
由上表可以得知目前WP7.1針對聯絡人與行事曆提供存取的功能範圍。
在練習實作Contact與Calendar API互動時,有幾個重要的元素需要去了解:
〉Microsoft.Phone.UserData Namespace:
UserData命名空間主要整合了WP7用戶的聯絡人與行事曆資料,讓開發人員可以透過該命名空間中的類別與資料進行互動。
主要互動類別:Contacts、Contact、Appointments、Appointment。以下將仔細說明。
a. Contacts Class & Contact Class:
Contacts允許App搜尋用戶的聯絡人資訊,並且回傳一個Contact物件,Contact物件是集合個體,其內容擁有相關搜尋結果的聯絡人資料。
a-1. Contacts:
該類別提供了搜尋的方法與對應的事件,加以整合所有的用戶聯絡人資訊。重點屬性、事件與方法:
a-1-1. SearchAsync:提供非同步的方法搜尋聯絡人資訊。搜尋完成時,觸發SearchCompleted事件。另外,在使用SearchAsync方法時,
有三個重要的參數:SearchAsync(string filter, FilterKind filterkind, Object state):
‧filter:搜尋聯絡人的字串;
‧filterkind:指定搜尋聯絡人的類型;類型包括:
EmailAddress、PhoneNumber、DisplayName,這三種需要配合filter一起使用;
None、PinnedToStar,filter為空白即可以使用;
‧state:用戶自行定義的資訊包括運作時要搜尋的match樣式。而state會出現在SearchCompleted中的參數:ContactsSearchEventArgs。
a-1-2. SearchCompleted:當SearchAsync完成後即觸發該事件,該事件中可以取得搜尋結果的Contact集合。
a-1-3. Accounts:取得所有可用的聯絡人資料來源。
a-1-4. BaseUri:取得<PhoneDataSharingContext>分享的聯絡人與行事曆資訊。透過Uri來識別資料的內容。
a-2. Contact:
該類別包含了所有個別用戶的可用聯絡資訊。可取得的屬性資料包括:Address、Birthdays、CompleteName、PhoneNumbers、
IsPinnedToStart、DisplayName、Accounts等相關資訊。有些屬性是複數的名詞其中都是資料的集合要特別注意。
a-3. 範例說明:指定搜尋所有的聯絡人。
1: private void GetContact()
2: {
3: //實例化Contacts類別
4: Contacts tContancts = new Contacts();
5: //註冊SearchCompleted事件處理
6: tContancts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(tContancts_SearchCompleted);
7: //利用FilterKind.None指定搜尋所有的聯絡人。
8: tContancts.SearchAsync(string.Empty, FilterKind.None, null);
9: }
10:
11: void tContancts_SearchCompleted(object sender, ContactsSearchEventArgs e)
12: {
13: lstContacts.DataContext = e.Results;
14: }
b. Appointments Class & Appointment Class:
Appointments允許App搜尋用戶的行事曆資訊,並且回傳Appointment物件集合,Appointment物件是資料實體,其內容擁有相關搜尋結果
的行事曆約會資料。Appointments與Contacts的機制相近採用非同步(asynchronous)執行搜尋的任務。往下介紹幾個執行時需注意的方法:
b-1. Appointments:
該類別提供了搜尋的方法與對應的事件,加以整合用戶行事曆中約會資訊。重點屬性、事件與方法:
b-1-1. SearchAsync:提供搜尋用戶行事曆中的約會資訊。由於此方法是多載的型式,因此,針對不同的參數加以說明:
‧SearchAysnc(DateTime, DateTime, Object):
搜尋在指定啟始與結束時間區段的約會資訊。
‧SearchAysnc(DateTime, DateTime, Accout, Object):
搜尋在指定Account、啟始與結束時間區段的約會資訊。
‧SearchAsync(DateTime, DateTime, Int32, Object):
搜尋在指定啟始與結束時間區段的約會資訊,根據指定的回傳數量回傳結果。
‧SearchAysnc(DateTime, DateTime, Int32, Account, Object):
搜尋在指定Account、啟始與結束時間區段的約會資訊,根據指定的回傳數量回傳結果。
b-1-2. SearchCompleted:當SearchAsync完成後即觸發該事件,該事件中可以取得搜尋結果的Appointment集合。
b-1-3. DefaultMaximumItems:預設搜尋結果的回傳數量。
b-1-4. Accounts:取得所有可用的行事曆資料來源。
b-1-5. BaseUri:取得<PhoneDataSharingContext>分享的聯絡人與行事曆資訊。透過Uri來識別資料的內容。
b-2. Appointment:
該類別包含了所有相關此約會的所有資訊。可取得的屬性資料包括:Attendee、Details、StartTime、EndTime、IsPrivate等相關資訊。
b-3. 範例說明:搜尋指定時間內的所有約會清單:
1: private void ListAppointments()
2: {
3: //實例化Appointments類別
4: Appointments tCalendar = new Appointments();
5: //註冊SearchCompleted事件處理
6: tCalendar.SearchCompleted += new EventHandler<AppointmentsSearchEventArgs>(tCalendar_SearchCompleted);
7:
8: //設定Start time與End time
9: DateTime tStart = DateTime.Now.AddDays(-3);
10: DateTime tEnd = DateTime.Now;
11: //搜尋,並指定回傳前10筆資料
12: tCalendar.SearchAsync(tStart, tEnd, 10, null);
13: }
14:
15: void tCalendar_SearchCompleted(object sender, AppointmentsSearchEventArgs e)
16: {
17: lstAppointments.DataContext = e.Results;
18: }
以上是針對使用聯絡人與行事曆API的介紹,其MSDN中也有提供相當容易的範例。如果想了解SearchAsync在搜尋比對的依據,
可以參考<Contact Filtering and Matching for Windows Phone>內容,裡面詳細表列了在人名、電話與Mail上的搜尋比對方式。
[注意]
a. 特別提醒的是這些聯絡人或行事曆的資料是「read-only」的。
b. 在開發支援存取聯絡人與行事曆資料的App時,記得告知用戶該App會存取到他的聯絡人與行事曆宣告隱私權與相關權限的使用。
c. App的WMAppManifest.xml記得設定對應的Capability,App送審時才會通過,可參考<Application Manifest File for Windows Phone>。
1: <Capabilities>
2: <Capability Name="ID_CAP_CONTACTS"/>
3: </Capabilities>
d. 當在程式中宣告使用Contact Data時,系統是採用Snapshot(快照)機制,所以資料都是read-only的。如果需要最新的資料,
建議定期初始化搜尋的元件與Contact instance。
e. 由於Contact資料來源很多種,因此App使用到的Contact資料大小通常是不固定的。因此,建議在讀取過程裡顯示通知介面(如ProgressBar)
告知用戶目前App處理的狀態。
[補充]
〉取得與顯示Contact中聯絡人圖片:
在MSDN<How to: Display the Photo of a Contact for Windows Phone>中介紹「Data Binding Photos to the User Interface」的做法,
我覺得需要好好研究一下,開發過WP7或Silverlight的人應該都知道,在實作ListBox時可以透過DataBinding的方式,將資料與XAML直接
結合,不一定需要從後端寫程式一個個Insert至Item中,但使用前提是要Insert的Item需要是Data Item並且指定結合的對象要是屬性才行。
由於Contact中的取得圖片不是一個屬性(而是使用Contact.GetPicture方法),因此沒有辦法直接在DataBinding中直接使用。
MSDN裡介紹了一個實作轉換的方法,讓在XAML中直接指定對應的方法,即可以完成。往下來看看是怎麼實作的:
a. 在要呈現聯絡人資料的程式(例如:ContactsPage.xaml.cs)之後,增加延伸轉換Value的類別;
為何需要加在指定的Page.cs之後呢?主要是限定該延伸轉換Value的類別,只限定於該Page中使用。當然,如果這方法需要被其他Page使用,
可以移到App.xaml.cs之中。以下擷取MSDN上的範例程式:
1: namespace ContactsAndCalendar
2: {
3: public partial class MainPage : PhoneApplicationPage {// ... Main Page的處理邏輯 }
4:
5: /// <summary>
6: /// 客製一個轉換聯絡人圖片的類別,透過實作IValueConverter Interface覆寫指定轉換的功能。
7: /// </summary>
8: public class ContactPictureConverter : System.Windows.Data.IValueConverter
9: {
10: public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
11: {
12: Contact c = value as Contact;
13: if (c == null) return null;
14:
15: System.IO.Stream imageStream = c.GetPicture();
16: if (null != imageStream)
17: {
18: //回傳writeableBitmap
19: return Microsoft.Phone.PictureDecoder.DecodeJpeg(imageStream);
20: }
21: return null;
22: }
23:
24: public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
25: {
26: throw new NotImplementedException();
27: }
28: }
29: }
b. 在要呈現聯絡人資料頁面(例如:ContactsPage.xaml)的<phone:PhoneApplicationPage>裡加上獨立實作的xmlns;
1: //使用自己方案的名稱
2: xmlns:MyApp="clr-namespace:ContactsAndCalendar"
c. 在<phone:PhoneApplicationPage>到第一個Grid element之間的空白,加上該Phone可以用的Resources;
1: <phone:PhoneApplicationPage.Resources>
2: <MyApp:ContactPictureConverter x:Key="ContactPictureConverter" />
3: </phone:PhoneApplicationPage.Resources>
d. 在要顯示聯絡人的ListBox清單中加上Image Element與Board Element;
1: <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
2: <Grid.RowDefinitions>
3: <RowDefinition Height="100*" />
4: </Grid.RowDefinitions>
5: <ListBox Grid.Row="0" x:Name="lstContacts" Width="460" ItemsSource="{Binding}">
6: <ListBox.ItemTemplate>
7: <DataTemplate>
8: <StackPanel Orientation="Horizontal" >
9: <!-- 加上要呈現的Image範圍 -->
10: <Border BorderThickness="2" HorizontalAlignment="Left" BorderBrush="{StaticResource PhoneAccentBrush}" >
11: <Image Source="{Binding Converter={StaticResource ContactPictureConverter}}" Width="48" Height="48" Stretch="Fill" />
12: </Border>
13: <!-- 顯示聯絡人名稱 -->
14: <TextBlock Text="{Binding Path=DisplayName, Mode=OneWay}" VerticalAlignment="Center" />
15: </StackPanel>
16: </DataTemplate>
17: </ListBox.ItemTemplate>
18: </ListBox>
19: </Grid>
f. 執行結果;
以上是針對MSDN上介紹的方法加上一些自己的說明,另外,其中技術裡有用到<WriteableBitmap>的元件來將聯絡人圖片轉至Bitmap中,
讓指定的Image可以直接透過「Binding Converter={StaticResource ContactPictureConverter}」的方法來取得資料。至於WriteableBitmap
的相關說明可以參考<Windows Phone 7 – Screenshot你的WP7 App>裡面有更詳細的說明。
[範例程式]
======
以上是針對WP7存取聯絡人與行事曆API的部分。由於WP7跟其他系統一樣也支援整合了多種不同帳號的聯絡人資料,
因此,在開發過程裡一定要切記有效的去處理聯絡人的搜尋,這樣可以讓效能比較好一些。如果有寫錯的地方,也請
大家跟我提醒一下,謝謝,希望對大家有所幫助。
References:
‧Microsoft.Phone.UserData Namespace
‧Contacts and Calendar for Windows Phone
‧How to: Access Contact Data for Windows Phone
‧How to: Access Calendar Data for Windows Phone
‧How to: Display the Photo of a Contact for Windows Phone
‧Contact Filtering and Matching for Windows Phone (重要,可加速搜尋聯絡人的效果)
‧Walkthrough: Accessing Contact and Calendar Data for Windows Phone
‧Data Templating Overview & Data Binding Overview
‧How to retreive all contacts from Windows Phone 7 using C# ?
‧【译】如何通过C#代码检索出Windows Phone中的所有联系人