Windows 10 UWP 8 of N: Contact, appointments, message, user`s data
早在Windows Phone的時候很多APP就已經跟People hub (人員),藉由連結各個Contact provider的APP連結成一個聯絡人資訊。
主要跟user data非常相關的有以下幾個功能
appointment (行事曆)
calls(撥號)
contacts(聯絡人)
Email(電子信箱)
Text messages(簡訊)
User data accounts(使用者帳號[ Aka 新增帳戶 ])
在抓取這些資訊時必須先在Manifest[ Package.appmanifest檔案 ]做宣告。這邊不能用內建的UI介面做調整,需要使用XML開啟並在capabilities加入以下權限。
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="contacts"/>
</Capabilities>
預設情形會加入internetClient,需手動加入的是contacts。
接者來寫Code存取聯絡人資訊!
public async void GetContact(ContactStoreAccessType accessType)
{
var contactStore = await ContactManager.RequestStoreAsync(accessType);
if (contactStore == null)
{
return null;
}
var reader = contactStore.GetContactReader();
var readerBatch = await reader.ReadBatchAsync();
var contactList = new List<Contact>();
while (readerBatch.Status == ContactBatchStatus.Success && readerBatch.Contacts.Count != 0)
{
foreach (var contact in readerBatch.Contacts)
{
contactList.Add(contact);
}
readerBatch = await reader.ReadBatchAsync();
}
return contactList;
}
這邊有幾點必須注意在抓取contact的資料時帶入存取的權限enum
public enum ContactStoreAccessType
{
//
// Summary:
// Read and write contacts that belong to the app only.
AppContactsReadWrite = 0,
//
// Summary:
// Read access to all app and system contacts.
AllContactsReadOnly = 1,
//
// Summary:
// Read and write access to all app and system contacts.
AllContactsReadWrite = 2
}
存取權限可以分為->讀寫、唯讀、所以系統註冊之聯絡人讀寫。所有系統註冊就是包含其他開發人員所提供contact store!
接者是如果抓取失敗的時候會丟回null值。
讀取聯絡人方式需要用ContactReader來做讀取的物件並且讀取的方式是採用批次[Batch]的方式做讀取。
讀取成功後抓取聯絡人資料到ListView的畫面如下
PS:由於抓取我個人的Contact所以將上籃線遮蔽
接下來是建立自己的APP的Contact Store
public async Task CreateContactStoreAsync()
{
var success = await TryOpenContactStoreAsync();
if (!success)
return;
var contactLists = await store.FindContactListsAsync();
if (contactLists.Count != 0)
{
System.Diagnostics.Debug.WriteLine("Contact List exit");
return;
}
var simpleContactList = await store.CreateContactListAsync(contactListId);
simpleContactList.IsHidden = false;
simpleContactList.OtherAppReadAccess = ContactListOtherAppReadAccess.Full;
simpleContactList.OtherAppWriteAccess = ContactListOtherAppWriteAccess.SystemOnly;
await simpleContactList.SaveAsync();
}
這邊建立的方式需要先抓取系統的ContactStore並建立ContactList!
ContactList有以下幾點重要的API
Read-Only
屬性 | 存取層級 | 敘述 |
ChangeTracker | Read-only | 取得該ContactList的ContactChangeTracker |
DisplayName | Read/Write | 顯示名稱 |
Id | Read-Only | 取得該ContactList的識別碼 |
IsHidden | Read/Write | 是否顯示ContactList在UI上 |
OtherAppReadAccess | Read/Write | 設定其他APP讀取該APP的權限 |
OtherAppWriteAccess | Read/Write | 設定其他APP寫入該APP的權限 |
SourceDisplayName | Read-Only | ContactList的提供來源字串 |
SupportsServerSearch | Read-Only | 是否能搜尋遠端伺服器 |
SyncManager | Read-Only | 與伺服器溝通物件 |
UserDataAccountId | Read-Only | 取得建立該contactlist的使用者帳號ID |
這邊會有個非常強大的功能ChangeTracker!沒錯就像是版本控制相似的功能,可以抓取聯絡人資訊變更紀錄。在文章下半段會詳細介紹該API使用。
基本上調整IsHidden、OtherAppReadAccess和OtherAppWriteAccess就可以建立基本的ContactList了!
這邊關於OtherAppWriteAccess的權限要特別注意,因為這會取決於是否能夠藉由系統的APP來刪除以及修改聯絡人資訊。
以下程式碼來新增聯絡人
public async void InserNewContact()
{
var contactInfo = new Contact();
contactInfo.FirstName = "EW";
contactInfo.LastName = "Taicho";
contactInfo.Phones.Add(new ContactPhone() { Number = "0963600700" });
contactInfo.Emails.Add(new ContactEmail() { Address = "testAc@msftUwp.com" });
var contactList = await store.GetContactListAsync(contactListId);
await contactList.SaveContactAsync(contactInfo);
}
加入之後重新抓取聯絡人列表就可以看到新增進去的EW的聯絡人了。
以及克制詳細的聯絡人資訊。
甚至在People的APP中可以看到建立該Contact的APP[ App1 ]
ContactTracker and ContactTrackerTrigger
接下來介紹的是ContactTracker的部分!
需要啟用ContactTracker在建立Contact的時候就將Tracker的功能開啟並註冊該事件就可以。
public async Task CreateContactStoreAsync()
{
var success = await TryOpenContactStoreAsync();
if (!success)
return;
var contactLists = await store.FindContactListsAsync();
if (contactLists.Count != 0)
{
System.Diagnostics.Debug.WriteLine("Contact List exit");
contactListId = contactLists.FirstOrDefault().Id;
return;
}
var simpleContactList = await store.CreateContactListAsync(contactDisplayName);
contactListId = simpleContactList.Id;
simpleContactList.IsHidden = false;
simpleContactList.OtherAppReadAccess = ContactListOtherAppReadAccess.Full;
simpleContactList.OtherAppWriteAccess = ContactListOtherAppWriteAccess.SystemOnly;
store.ChangeTracker.Enable();
store.ContactChanged += new Windows.Foundation.TypedEventHandler<ContactStore, ContactChangedEventArgs>(ContactStoreTrackerHandler);
await simpleContactList.SaveAsync();
}
ContactChanged的事件註冊如下
private async void ContactStoreTrackerHandler(ContactStore sender, ContactChangedEventArgs args)
{
var defferal = args.GetDeferral();
var reader = sender.ChangeTracker.GetChangeReader();
var changes = await reader.ReadBatchAsync();
while (changes.Count != 0)
{
foreach (var change in changes)
{
switch (change.ChangeType)
{
case ContactChangeType.Created:
case ContactChangeType.Modified:
case ContactChangeType.Deleted:
var toastMessage = string.Format($"{change.Contact.FirstName}, {change.ChangeType}");
SentToast(toastMessage);
break;
case ContactChangeType.ChangeTrackingLost:
sender.ChangeTracker.Reset();
defferal.Complete();
break;
default:
break;
}
}
changes = await reader.ReadBatchAsync();
}
reader.AcceptChanges();
defferal.Complete();
}
這邊的Change type需要注意的是要有ChangeTrackingLost以及Default的預留!當系統出現問題或是進行聯絡人重新設定就會將ChangeTraker重新Refresh所以會Lost調ChangeTrack。至於留下Default則是之後有可能新增其他類型的Type作為預留空間。
當Foreground的event註冊好就可以新增資料來測試!如下就是Create[ Insert contact ]就會提示的Toast Notification。
接下來說明一下Background的TrackEvent是如何被觸發。
之前在前幾篇就有說明到Background的部分所以我就沿用之前的Code
await RegistrationBackgroundTaskHelper.RegisterBackgroundTasksAsync("SimpleBackgroundTask", typeof(ContactStoreTask), new ContactStoreNotificationTrigger());
註冊ContactStoreNotificationTrigger就可以抓取到ContactStore的Tracker。
寫個BackgroundTask的Class並使用以下的Code就可以收到Background的Contact Change的事件
public sealed class BackgroundToastTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
taskInstance.Canceled += TaskInstance_Canceled;
if (taskInstance.TriggerDetails is ContactStoreNotificationTriggerDetails)
ShowToast("Contact Changed!!");
}
private void TaskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
}
private void ShowToast(string toastMessage)
{
var toastTemplate = ToastTemplateType.ToastText01;
var toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
var toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(toastMessage));
var toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier("App").Show(toast);
}
}
這邊比較可惜的是ContactStoreNotificationTriggerDetails目前只是空的Detail Object...所以沒辦法抓取ChangeType等資訊。
***以上Code以及說明都有可能隨著Windows 10 的版本以及Visual Studio 2015版本有所調整!***
參考資料 2-684 User Data: working with contacts, appointments, text message and more on Windows 10, MSDN Blogs
下次再分享Windows 10 的新技術拉~