基于Microsoft Graph打造自己的Timeline应用
原文链接:https://github.com/chenxizhang/office365dev/blob/e9b5a59cb827841d36692cc4ec52c11d43062e04/docs/timeline.md
前言
前不久微软正式放出了Windows 10 春季更新(1803),其中有一个非常有特色的应用,就是Windows 10 新增了一个Timeline(时间线)的应用,这个应用可以让用户一目了然地看到最近一段时间所有在Windows中的活动,包括浏览过什么网页,打开过什么文档,设置过什么选项等。下图是一个示范的效果图:
请注意,这里看到的信息不是一个静态的图片,每一个卡片都是可以点击的,而且点击之后会通过调用对应的应用程序自动打开这些活动(恢复到之前的状态),就好像时光倒流了一样。
看起来很酷,不是吗?那么,这样一个应用到底是怎么实现的呢?我们如果也想实现类似的场景,有什么样的思路呢?答案在上周的Microsoft Build 大会上做了揭晓:其实Timeline是一个基于Microsoft Graph实现的应用,只不过他读取的数据,不仅限于Office 365的文档历史,还包括了Windows 10 上面的活动,这也是近年来一个重大的变化:微软已经把Office 365、Windows 10、EMS这三个产品合并为一个——Microsoft 365,将为最终用户提供最佳的体验,他们的能力也将统一通过Microsoft Graph向开发者提供服务。
原理解析
首先,从技术上说,要实现这个Timeline应用,用户需要允许相关的活动源将有关信息发送给Microsoft Graph。这里所谓的活动源,可以是Office客户端,也可以是Windows 10的应用程序。微软一直致力于保护用户的隐私,所以这个Timeline的功能,默认是不开启的,只有用户在被明确告知上述行为并且选择接受的情况下,才会开始收集数据并进行展现。
其次,除了Windows 10自带的Timeline应用,其实只要几行代码,就能实现一个类似的时间线应用。那么问题就来了,这些应用之间的数据是不是隔离的呢?答案是肯定的,也就是说Windows 10这个Timeline应用只能读取到它在经用户同意的前提下收集的那部分活动数据,而我们自定义的应用也是如此。
最后,这里面还有一个有意思的概念。一个活动(Activity)可以对应一个或者多个历史记录(History Items)。历史纪录相当于是活动在某个时间点的快照。
据说这个技术,最早在内部有一个代码叫做“Project Rome”,现在合并到了Microsoft Graph中,并且已经在V1.0中提供。相关官方文档请参考 https://developer.microsoft.com/en-us/graph/docs/concepts/activity-feed-concept-overview .
创建Timeline应用
有了如上概念,我们就闲话少说,撸起袖子加油干吧。因为要访问Microsoft Graph,所以你就必须要注册一个AAD的应用程序。注册这样一个应用程序没有什么特别的,唯一要了解的是,要支持用户活动的读写,需要申请一个UserActivity.ReadWrite.CreatedByApp的委派权限(Delegated Permission),如下图所示
大家可以看到,这个权限并不需要管理员认可就能工作。
请注意,目前UserActivity.ReadWrite.CreatedByApp这个权限,仅在国际版的环境中可以用,而且必须在AAD 1.0的环境中实现。AAD 2.0还不支持,国内版(Gallatin)也暂时不支持。
如何发布Activity
Windows 10自带的Timeline其实是一个UWP应用,不过你可以用你最熟悉的方式来实现自定义的Timeline应用。但抛开这些具体的界面,我们可以快速了解一下如何创建和更新用户活动(Activity)。
创建或更新Activity的API,请参考 https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/projectrome_put_activity, 大体上说,这里的关键是用PUT方法操作,同时我们既可以单独创建Activity,也可以在创建Activity的时候同时创建History Item,后者也称为“Deep Insert”。
为了给大家直观演示效果,我这里简化一下步骤。我将采用官方的Microsoft Graph Explorer来模拟一个客户端,并且直接用REST API来进行操作。如果你对Microsoft Graph Explorer不太熟悉,你可能需要先阅读一下这篇文章。
正如上一节提到的,你需要确保授予了UserActivity.ReadWrite.CreatedByApp这个权限,请参考下图
我直接用官方给的例子,为当前用户新增一个网络文章浏览的活动,请注意下面的appActivityId、activitySourceHost、activationUrl、visualElements 是必须的。这个例子的意思是指定义了用户这个活动是浏览了 http://www.contoso.com/article?id=12345 这个Url所指向的一篇文章。
{
"appActivityId": "/article?12345",
"activitySourceHost": "https://www.contoso.com",
"userTimezone": "Africa/Casablanca",
"appDisplayName": "Contoso, Ltd.",
"activationUrl": "http://www.contoso.com/article?id=12345",
"contentUrl": "http://www.contoso.com/article?id=12345",
"fallbackUrl": "http://www.contoso.com/article?id=12345",
"contentInfo": {
"@context": "http://schema.org",
"@type": "Article",
"author": "Jennifer Booth",
"name": "How to Tie a Reef Knot"
},
"visualElements": {
"attribution": {
"iconUrl": "http://www.contoso.com/icon",
"alternateText": "Contoso, Ltd.",
"addImageQuery": "false",
},
"description": "How to Tie a Reef Knot. A step-by-step visual guide to the art of nautical knot-tying.",
"backgroundColor": "#ff0000",
"displayText": "Contoso How-To: How to Tie a Reef Knot",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"body":
[{
"type": "TextBlock",
"text": "Contoso MainPage"
}]
}
}
}
在Microsoft Graph Explorer 中用PUT方法,将上述数据,发送到https://graph.microsoft.com/v1.0/me/activities/%2Farticle%3F12345, 同时记得设置Content-Type为application/json
如果一切正常的话,你将收到一个回复,里面包含了在Microsoft Graph中创建的Activity的信息,这里会返回全局唯一的id属性。
请注意,如果要更新,也是使用同样的一个命令。而如果要进行删除,则需要用 DELETE 方法,请参考 https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/projectrome_delete_activity。
如何查询Activity
有两个接口用来查询用户活动(Activity),分别是
- 获取用户活动(可以获取全部,也可以获取指定筛选条件的活动),如果需要同时包含历史信息,则需要添加查询参数 $expand=historyitems。 详细的API说明,请参考 https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/projectrome_get_activities 。
- 获取用户最近的活动。可以理解为上一种的简化版本,Microsoft Graph会查询最近的一个History Items,然后找到它们对应的活动条目。详细的API说明,请参考 https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/projectrome_get_recent_activities。
下面是一个简单的查询例子

结语
这一篇文章带领大家了解了Windows 10最新版本中Timeline这个功能的实现原理,并且用实例演示了如何使用Microsoft Graph来实现自定义的类似应用,我用Microsoft Graph Explorer做了演示,大家可以一目了然地看到接口的调用和返回值。
因为这个功能比较新,Microsoft Graph的SDK中,还没有完全包含这个功能,我还发现.NET SDK中存在一点小问题,已经跟产品团队反馈了。所以,如果你现在开始做实践,建议还使用REST API的方式。
基于Microsoft Graph打造自己的Timeline应用的更多相关文章
- 扩展Microsoft Graph数据结构(开放扩展)
作者:陈希章 发表于 2018年1月2日 前言 Microsoft Graph是一张拥有巨大价值的网络,它定义了包括Office 365在内的资源的实体及其关系,它的价值体现在,随着用户积累的数据越来 ...
- 基于Microsoft Azure、ASP.NET Core和Docker的博客系统
欢迎阅读daxnet的新博客:一个基于Microsoft Azure.ASP.NET Core和Docker的博客系统 2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客 ...
- 在无人值守程序(服务)中调用Microsoft Graph
作者:陈希章 发表于 2017年5月31日 什么是无人值守程序(服务) 我在此前用了几篇文章分别介绍了在桌面应用程序(控制台),Web应用程序(ASP.NET MVC),以及PowerSehll脚本中 ...
- 在PowerShell脚本中集成Microsoft Graph
作者:陈希章 发表于2017年4月23日 我旗帜鲜明地表态,我很喜欢PowerShell,相比较于此前的Cmd Shell,它有一些重大的创新,例如基于.NET的类型系统,以及管道.模块的概念等等.那 ...
- 扩展Microsoft Graph数据结构 - 架构扩展
前言 此前我有一篇 文章 讲解了Microsoft Graph的一种数据扩展技术-- 开发扩展(Open Extensions),它可以实现在支持的对象(例如用户,组等)上面附加任意的数据.但开放扩展 ...
- 基于windows 10打造的kali工具集
基于windows 10打造的kali工具集.iso,适合于习惯使用windows的安全从业者.if you like it,please touch star! 作为安全从业主,Kali都是必备工具 ...
- win10 uwp 使用 Microsoft.Graph 发送邮件
在 2018 年 10 月 13 号参加了 张队长 的 Office 365 训练营 学习如何开发 Office 365 插件和 OAuth 2.0 开发,于是我就使用 UWP 尝试使用 Micros ...
- 如何使用 Azure Active Directory 认证和 Microsoft Graph 构建 Blazor Web 应用
如何使用 Azure Active Directory 认证和 Microsoft Graph 构建 Blazor Web 应用 英文原文:https://developer.microsoft.co ...
- 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)
作者:陈希章 发表于 2017年6月25日 谈一谈.NET 的跨平台 终于要写到这一篇了.跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标.我在前面的文章已经提到过了,Micro ...
随机推荐
- ISLR系列:(3)重采样方法 Cross-Validation & Bootstrap
Resampling Methods 此博文是 An Introduction to Statistical Learning with Applications in R 的系列读书笔记,作为本人的 ...
- 【嵌入式开发】C语言 指针数组 多维数组
. 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21402047 . 1. 地址算数运算示例 指针算数运算 ...
- C++中const的实现机制深入分析
via:http://www.jb51.net/article/32336.htm C语言以及C++语言中的const究竟表示什么?其具体的实现机制又是如何实现的呢?本文将对这两个问题进行一些分析,需 ...
- RHEL6 安装KVM
RHEL6 安装KVM # egrep '^flags.*(vmx|svm)' /proc/cpuinfo 有显示说明CPU支持VT功能 2.在主板BIOS中开启CPU的Virtual Technol ...
- Media Player Classic - HC 源代码分析 7:详细信息选项卡(CPPageFileInfoDetails)
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
- dex分包方案
当一个app的功能越来越复杂,代码量越来越多,也许有一天便会突然遇到下列现象: 1. 生成的apk在2.3以前的机器无法安装,提示INSTALL_FAILED_DEXOPT 2. 方法数量过多,编译时 ...
- 安装docker及配置Android开发环境
安装docker 官方原来的安装docker的脚本https://get.docker.com/已经过时,现在使用的是https://get.docker.com/,命令如下: curl -s htt ...
- 解决Cell重用内容混乱的几种简单方法,有些方法会增加内存
重用实现分析 查看UITableView头文件,会找到NSMutableArray* visiableCells,和NSMutableDictnery* reusableTableCells两个结构 ...
- 面试之路(18)-java的函数参数传递类型之值传递还是引用传递
关于这个问题争论了很久,最近也是偶然发现这个问题 经典名言: O'Reilly's Java in a Nutshell by David Flanagan (see Resources) puts ...
- 快速掌握Oracle异常
自定义例外是指由PL/SQL开发人员所定义的例外.预定义例外和非预定义例外都和Oracle错误有关,并且出现Oracle错误时会隐含的处罚相应例外:而自定义例外与Oracle错误没有任何关联,它是由开 ...