基于 Azure Bot Service 的 Microsoft Teams Bot 开发上手指南

这篇文章本不必要,可惜无论是 Teams Developer platform 还是 Azure Bot Service 的官方文档都不够清晰易懂,容易走弯路。因此无奈在这里做简单小结,帮助读者更快上手。

Bot 的主要目的是接收并理解用户输入的文字信息或指令,并采取行动给予回应。在一些场景下,Bot 能够节省时间,提高效率,或提供更好的使用体验。在 Bot 不擅长的场景,开发并应用 Bot 则可能得不偿失。如非出于学习与研究目的,最好首先全面考察开发维护 Bot 的成本及相应的收益。

Azure Bot Service

Azure Bot Service 是 Microsoft Azure 提供的通用 Bot 服务。它不与特定消息平台频道(Channel)绑定,提供了包括语义理解、图像识别、知识库文档和通用搜索等功能。借助 Azure Bot Service 开发的 Bot 可以介入 Teams、Telegram、Line、WeChat、Facebook 等各种频道。

Microsoft Teams 是一款可扩展的通信平台,支持安装第三方应用。一款 Teams App 可以提供 tabs、bots、connector 和 messaging extension 这四大类功能。这里仅涉及 bot 部分。

两者的文档都提供了大量说明和范例,然而文章组织混乱,不少细节描述不够清晰,快速上手指南也在本地测试后戛然而止,而未作后续说明,对新手反而可能造成误导。这里简单整理。

用 Azure Bot Service 创建一个 Bot,往往意味着创建包含包括 App Service Plan、App Service、Bot Channels Registration/ App Bot 等在内的一系列资源。这些资源会被 Azure Bot Service 一同创建。如果选择 Bot 模板,则 App Service 创建之初就能提供模板描述的 Bot 功能,可以在 Bot Channels Registration/ App Bot 的 Test in Web Chat 菜单中实际体验。例如,选择 Echo Bot 模板,则数分钟后就能在 Test in Web Chat 中与该 Bot 对话并得到复述回答。

Azure Bot Framework ComposorAzure Bot Framework SDK 用于为 Azure Bot Service 开发复杂的 Bot 逻辑并发布。可惜的是 Azure Bot Framework Composor 无论是文档还是工具本身的易用性还都有待改善。创建完成的 Bot 将被发布至相应的 App Service 中。开发者也可以手动发布。如果是基于 NodeJs 的 Bot,直接通过 App Service 的 Editor 编辑 .js 文件,同样可以更改 Bot 的逻辑。基于 .NET 的 Bot 则需要在更改代码后进行编译。

Bot Channels Registration/ App Bot 之所以能够连接到 App Service 并与 Bot 交互,是因为它的配置菜单中提供了 App Service 的 messages API。要运行 Teams 连接至该 Bot,只要在其 Channels 菜单中添加 Teams 频道即可。

此外,除了上述由 Azure Bot Service 创建的 Bot Channels Registration/ App Bot,Azure Bot Framework 也提供了功能相似的替代品,能够创建 Bot 定义、连接频道,并访问由 messages API URL 指定的 Bot 服务。

以上是 Azure Bot Service 的部分。

Microsoft Teams Bot

另一方面,Teams App Bot 这边不提供实际的 Bot 逻辑。从 Teams 的角度来看,只有 App 这个概念,App 可以提供 Bot 功能。因此在 Teams 这边需要做的只有定义 App,更确切地说,准备一个包含了 manifest.json 、 color.png、outline.png 这三个文件的 Zip 文档。该文档可以被用于提交至 Teams 公开 App Store组织内部的 App Center,或者用户自己在自己的 Teams 客户端中上传安装(需要得到 IT 管理员许可才能使用该功能)。上述两个不同用途的图标文件按下不表,在 manifest 文档中会定义该 Teams App 的 Id、名称、描述、Bot 的 Id、范围和支持的命令等信息。

名为 App Studio 的 Teams App 和 Visual Studio Code 扩展 Microsoft Teams Toolkit能够帮助开发者快速创建和准备 Teams App 所需的信息(如 manifest 等)并打包或发布。

Teams Toolkit 能快速创建 Bot 的定义并生成基本的 Bot 模板。被创建的 Bot 模板可以在之后发布到服务器作为 Bot 的实际逻辑。同时,Teams Toolkit 还能直接访问 Azure Bot Framework,读取已创建的 Bot 定义,并更新 messages API 的 URL。

即使没有 App Studio,根据文档手动创建 App 的 manifest 也并不麻烦。但 App Studio 提供了更方便的管理功能,推荐使用。

即使没有 Teams Toolkit,也可以直接访问 Azure Bot Framework 站点并登录,在网站上创建 Bot 定义,并更新各类信息,或添加频道支持。Toolkit 自动生成的 Bot 逻辑也可以通过 Azure Bot Service 自动创建。

小结

综上,为了让 Teams 能够安装一个提供了 Bot 功能的 App,需要完成以下工作:

  • 准备 manifest.json 、 color.png、outline.png 并打包成 Zip 文档(可借助 App Studio )
  • 创建 Bot 定义(经有 Azure Bot Service 或者 Azure Bot Framework),并将 Bot Id 填入 App manifest (可借助 Teams Toolkit)。Bot 定义中的 messaging api 需要指向一个实际可用的服务,如本文介绍的 Azure Bot Service 提供 App Service 的 messages API 接口

需要注意,Teams Bot 和 Azure Bot Service 的 Bot 功能有若干差异,在阅读文档时需要注意辨别。Bot Serivce 中的功能有时不一定能在 Teams 中正常工作。

以上便是基于 Azure Bot Service 的 Microsoft Teams Bot 开发上手指南。想必还没有实际开始,就能感受到这套框架的设计有多么地复杂与含糊。愿本文可以帮助对 Bot 开发感兴趣地读者节省一些时间,更愉快地开发出自己的第一个 Bot。

Die Seltene

No. 18

构图为左手拿着手机按快门,右手比 V 字手势自拍的模样。屏幕界面是 Xperia 1 II 特色的 Photo Pro 相机应用

_

这次的主题是使用手机后置摄像头自拍的瞬间。如今会用后置摄像头自拍的人恐怕已经绝迹,大多数人都使用前置摄像头,以便在屏幕上实时确认位置与动作,再加上或强或弱的美颜效果。然而在十多年前,手机前置摄像头还不那么先进的时代,用后置摄像头自拍才是主流。摆好姿势和表情,不断拍摄、确认、重试,最后得到满意的照片。当时不少手机的后盖都有直径数毫米的反光金属片作为自拍镜,帮助自拍者确定自己是否在摄像头的取景范围之内。索尼爱立信的手机侧面大多都配备有独立的实体快门键,不用看到手机屏幕依然可以准确按下快门拍照,因此用后置摄像头自拍一直不是一件难事。现代的智能手机已经看不到后盖自拍镜的设计,不过 Xperia 1 II 后盖本来就是镜面设计,硬件上传承了两段式自动对焦快门,软件上有人脸识别与人眼对焦确保自拍效果,F1.7 的大光圈蔡司镜头搭配成像素质佳的摄像头传感器,让这种世纪初流行的自拍方式再次成为可能。每次画自己手边爱用的设备,总是别有乐趣。

2020 年是不寻常的一年,如同所有人都知道的那样。

然而,相对来说,大部分人依然是幸运的。对自己而言,在过去半年,人生已被彻底改变。前所未有的,罕见至极的,未曾料想的,难以避免的打击迎面而来,把二十多年的人生观碾得粉碎。心力憔悴。整个人仿佛落入深渊,至今仍未从中爬出。

迷茫、彷徨、绝望、无助,数不清的日与夜,被看不见希望的昏暗的未来图景笼罩,被不知从什么角落源源不断散发出的悲伤与苦楚包围。即使确实得到了一些支持,收到了一些慰藉,却依旧感到孤立无援。能够提供帮助的人其实并不多,而且也终究只能是言语上的精神支持。它们都很宝贵,只是相比自己的处境,再多的援助都好似只会是杯水车薪,也许能解一时燃眉之急,却无法真正解决问题。这点自己当然也是知道的。自己显然也做不到无休无止地向身边的人传播消极与悲观,甚至时常担心或许总有一天这会超过一般人能承受的限度,而让他们不得不选择退避三舍,以维持乐观心境。

人生的意义,活着的意义,这些本就没有正确答案的问题,在这几个月里被翻来覆去地思考。很多时候,答案都不令人满意。有时就会进入死胡同,感到一切仿佛都并没有什么意义。已经记不清每次都是怎样逃离那种危险的状态,或许是幸好自己还有树洞,尽管总觉得它有珍贵的使用次数限制而舍不得轻易使用。或许是想到有人曾为自己加油鼓励,就算那更多也许只是社交辞令,出于善意。但这些对原本就会记得各种细节琐事的自己来说,无疑是一种救赎,提醒自己人生依然还有值得。也许,自己也要比想象中更加勇敢和坚强。

即便如此,也很难说自己已经走出了最黑暗的时期。在可见的未来,困难只会越来越明显、越来越接近、越来越真实。那些罕见的事。

_

Keep thinking about life, of which the meaning I feel
Keep questioning to myself, is that the fate to thank
So weary my soul, drifting in the mist without you
Though day and night, the sun and moon rise in the east
Just lost in searching you, and wait there in the silence

Until awhile with me, you come and sit
The moutains I can stand on, as I up raised by you
The stormy seas to walk on, as I up raised by you
The way I would pass through, as I up raised by you
To more than I can be, as I up raised by you

搜索正在耳边播放的曲子,即兴改写几句歌词,释放了一些胸口难以名状的沉重,似乎人生也变得轻松一些。然而这不会是结束。可以预料,未来还会有更多的不确定性。怎样应对,现在还是一个问号。

啊。所以说。

如何才能继续前进。

Viel Glück, hast gesagt du.

_

_

And, again…

Ver. Disneyland

Java 运行时发生 NoClassDefFoundError: Could not initialize class 的解决方法

最近遇到了如下问题:

在编译时没有异常的程序,在运行时抛出异常称 NoClassDefFoundError: Could not initialize class {类名}

根据 Java 官方文档,NoClassDefFoundError 是由于 JVM 或 ClassLoader 实例为了调用某个类的方法或 new 类的新的实例,而试图加载该类的定义时,却无法找到其定义,而抛出的异常。需要注意,对于抛出该异常的情况,试图找到的类的定义在编译时存在,只是在运行时不知所踪。

NoClassDefFoundError 总的来讲有两种情况,类文件不存在,或是类初始化错误。它们的错误信息不同。

  • 如果无法找到类文件,错误信息为 java.lang.NoClassDefFoundError: com/example/Foo
  • 如果类文件初始化错误,错误信息则如前文所提,为 NoClassDefFoundError: Could not initialize class {类名}。这通常由类的静态成员或静态初始化语句块引起。诸如 private static final MyClass val = new MyClass(); 或直接执行于 static {} 代码块中的语句抛出异常,都可能会引发 NoClassDefFoundError。针对第二种这种情况,可以在类的 static initializer 中增加 try catch 语句来捕获异常并输出日志,来了解具体错误内容。

此外还有一种相似但不同的错误,ClassNotFoundException。它通常由 Java 运行时在无法找到仅在运行过程中才需要加载的类时抛出。

可以从 Wikipedia 的 Java Classloader 条目进一步了解 classloader 的行为。

致爱好者 —— 索尼(Sony)Xperia 1 II 简单使用感想

受 Covid-19 疫情影响,今年很多事情都不同以往。在2月底发布之后三个多月,Xperia 1 II 才终于在部分市场以软件未完成的形式上市,大陆行货则至今仍遥遥无期。从6月首发入手港版 Xperia 1 II 至今也有近两个月,在此简单聊聊使用感想。

时隔多年,再次选择了白色机身的 Xperia

本文基于在香港地区销售的 Xperia 1 II 写成,型号 XQ-AT52。本机支持中国移动联通电信的 4G 网络。理论上仅能完美支持中国联通的 5G 网络。这两年 5G 是一个热点话题,Xperia 1 II 又是索尼的第一台 5G 智能手机,在此多讲几句。个人认为目前 5G 网络能提供的性能提升还不能抵消额外的费用与耗电问题,尤其是自己日常生活中99%的场景不是不需要高速移动网络(如开车时),就是有更加稳定高速的 WLAN 环境,因此对港版型号不支持 5G 并不在意。事实上,因为不用手机打游戏,也不需要高速下载大量文件,LTE+ 上百兆比特的速率对自己的需求来讲已经绰绰有余。即使没有费用因素,5G 以更高能耗换来的性能提升对自己也不是必须。即使在一线城市,5G 信号要达到目前 4G 的水准恐怕也还需要时日,费用问题和芯片功耗也不见得会在短时间改善。再考虑到手机升级换代的频率不会太低,忽略 Xperia 1 II 在大陆的 5G 网络问题符合自己的实际情况。据称由于网络制式问题,这次行货型号可能会在硬件上有改动,无法通过软件通刷港版硬件。如果 5G 网络是刚需,或担心之后几年 4G 网络的通信质量被限制,建议等待几个月后上市能更完整支持国内 5G 网络的行货型号。

本文内容基于2020年8月提供的软件版本 58.0.A.3.88。出于兴趣写了近十年的业余“测评”,如今网络上专业的不专业的,客观的不客观的测评越来越多,更重要的是智能手机在十多年飞速发展后已经彻底进入了瓶颈期,每年写的文字越来越公式化,乐趣越来越少。于是从这次开始,更多会分享主观的使用感受,站在一个见证 Xperia 10年发展衰弱,试行错误的爱好者的角度,提供一些个人的看法和评论。

顺便一提,官方产品名发音为 Xperia One Mark Two。虽说符合相机部门的命名传统,如 Alpha Seven Mark Two 或 RX-100 Mark Five,但距离大众接受流行渐行渐远。就算这次中文用户能省略 Xperia 1 这一品牌与型号名,单独施以爱称“马克兔”,明年的 Mark Three 又会如何呢(估计会和相机一样,被称为 X1M3 或 1M3 吧,笑)。

2020/10/17 更新

Xperia 1 II 和 Xperia 5 II 的大陆行货版本在比其他地区晚了5个月后终于姗姗来迟。型号为 XQ-AT72 的新版 Xperia 1 II 硬件上内存从8GB增加至12GB,新增镜面绿色。网络上国行 Xpeira 1 II 完整支持中国大陆三大运营商的 5G 网络并支持 5G/4G 双待(Xperia 5 II 支持除了中移动 NSA 外的其他 5G 网络)。系统上,国行新增了对微信指纹支付的支持。虽然从生态上来看这不是一件好事,但确实可以增加一些潜在的国内销量吧。港台版本的 Xperia 1 II 也同时新增了 12GB 内存的高性能版和镜面绿色配色。

致爱好者

智能手机已经进入了发展瓶颈。一边,价格亲民的中低端机型已经能很好的满足普通人基本的通信与娱乐需求,Andriod 发展初期低端机性能明显不足的问题已经改善。另一边,在屏幕与相机等方面积极采用高规格硬件的高端型号价格不断攀升,与中低端机型拉开更大差距。由于多种原因,在全球销量一路断崖式下跌的索尼移动,在几次失败的尝试后,最终从去年开始选择了主打高端型号,以满足小众发烧友和品牌粉丝的发展路线,推出 Xperia 1。今年的 Xperia 1 II 是该路线的延续,不但彻底解决前代大量体验问题,更进一步加大力度讨好目标用户。

先说结论。作为目标用户,不得不说,Xperia 1 II 深得我意。Xperia 1 II 是迄今为止 Xperia 系列最高峰,历代体验标杆。

致静态摄影爱好者——源于 Alpha 相机团队的多项软硬件技术,搭配蔡司镜头与 T* 镀膜,提供独一无二的拍摄性能和体验,以及系列传统二段式独立相机快门键

致电影录制爱好者——增强的 Cinema Pro 软件提供更好的电影拍摄与剪辑体验

致电影鉴赏爱好者——显示效果业界一流的 21:9 4K HDR OLED 显示屏,且支持创作家模式以呈现作品原本风格

致音乐欣赏爱好者——LDAC 高解析度蓝牙音频技术,以及业界少见的 3.5mm 耳机接口(笑)

致手机游戏爱好者——游戏模式增加包括电力直供模式等多项新功能,提高重度玩家的游戏体验

致 Xperia 爱好者——最新型旗舰处理器与高速闪存、识别迅速准确的侧面指纹、在高端机型中高于平均的续航能力、支持电池寿命保护与无线充电、精致的做工与外形设计、相近规格产品中轻薄的尺寸与重量、稳定无广告且少有海外软件兼容问题的系统、完整 Google 服务支持

Xperia 1 II 并非完美无缺,但对于能够接受 Xperia 系列一贯的精简系统,不依赖很多国产手机厂商额外定制的本土化软件功能的老用户来说,Xperia 1 II 出色地实现了设计目标,提供了综合水准很高的使用体验。

致静态摄影爱好者

在一些市场,Xperia 1 II 最大的产品亮点是“口袋中的 Alpha 相机”。Xperia 1 II 最具代表性且不可替代的特长确实在这套软硬结合的相机系统上。

Xperia 1 II 与 Alpha 系列旗舰型号 Alpha 9 的合成照片是相机功能的官方宣传亮点——即使两者性能有天壤之别

硬件上,Xperia 1 II 延续了去年 Xperia 1 才姗姗来迟的三摄像头组合,提供了三颗12.2MP的摄像头和一颗帮助对焦的 3D iToF 红外测距传感器。与一些厂商为了背景虚化而采用 ToF 传感器不同,Xperia 1 II 的 ToF 传感器为对焦而设计,以实现弱光场景下0.03秒的高速对焦性能。这是 Xperia 1 II 为了对焦性能而作的独特设计。

标准镜头比 Xperia 1 更广角,长焦镜头则更望远。除超广角镜头外,另两颗都支持光学数字混合防抖

传感器方面,和 Xperia 1 不同,参照35mm下大三元的焦段,这次三颗镜头的焦段分别为 16mm(F2.2)、24mm(F1.7) 和 70mm(F2.4)。镜头则首次采用了蔡司(ZEISS)镜头和蔡司减少光线反射的 T* 镀膜,以提供有蔡司风格的色彩与虚化风格。其中标准镜头和长焦镜头支持光学与电子混合防抖。

首次采用来自 ZEISS 的高性能镜头与 T* 镀膜,看来索尼自己也认为 Z 系列时自家的 G 镜头并没有宣传效果

这次 24mm 主摄传感器为 1/1.7” 大尺寸,相比 Xperia 1 的 1/2.6” 大幅提升,像素尺寸高达1.8μm(Xperia 1 为 1.4μm)。除了华为在 P40 系列上使用的惊人的 1/1.28” 50MP Ultra Vision 主摄传感器,能够在4像素合一时提供2.44μm 的像素尺寸(单像素1.22μm),Xperia 1 II 的主摄像素尺寸与三星 Galaxy S20 系列的一致,并高于 iPhone 11 Pro 系列的1.4μm。此外,主摄 F1.7 的明亮镜头则小幅领先同级对手的 F1.9 或 F1.8,入光量更大。尽管像素尺寸和镜头光圈并非一切,Xperia 1 II 这次至少在规格上没有明显短板。

配合 BIONZ™ X for mobile,Xperia 1 II 最终实现了相比 Xperia 1 约1.5倍的感光性能。Exmor™ RS 或许因为不再有独特优势,宣传上被弱化

Xperia 1 II 在相机软件方面也积极引入源自 Alpha 的技术。

  • 运用 AI 技术,世界首创每秒60帧的 AF/AE 自动对焦/自动曝光计算,并实现最终每秒20张的 AF/AE 连拍,为拍摄运动物体提供了业界顶级的对焦与连拍能力。实际使用中,Xperia 1 II 的连续对焦连拍效果非常震撼,使抓拍精彩瞬间有了更多可能(顺便,连快门音都和 Alpha 相近,笑)
  • 高精度实时人眼/动物眼 AF,帮助时刻准确对焦拍摄对象(仅支持 24mm 主摄)
眼部对焦相当于是人脸对焦的更精准版本,但似乎并没有概念上的突破,一直以来都觉得更像是以趣味性而非功能性为卖点
  • 双重相片二极管对焦
  • 覆盖率70%的247点相位对焦。为 Xperia 1 的4倍
  • 增强的摄影后期工作流程:通过 Imaging Edge Mobile 软件遥控相机,以 5G 或 WiFi 6 传输作品、并以 D50 / D55 照片印刷色彩标准在 Xperia 1 II 的 4K HDR OLED 屏幕上回放
Alpha 在屏幕方面规格不激进的原因找到了

不过, Xperia 1 II 最让自己心动的软件功能当属 Photography Pro(下称 Photo Pro)。

Xperia 摄影新乐趣,兼具专业手动设置,以及,仪式感

简言之,PhotoPro 提供了与 Alpha 或 RX-100 相机类似的手动设置界面,以及专为触摸屏优化的设置菜单。近期发布的首次搭载触摸屏的 Alpha 7s III 也使用了这套新菜单。

Photo Pro 允许用户在不离开取景界面的同时修改各类拍摄参数,还支持 Alpha 相机上的 AF-ON 与 AEL 等高级功能,让摄影师和摄影爱好者能最大程度发挥自己的创作灵感。

Photo Pro 大体提供了以下功能:

  • 拍摄模式
    • Auto 自动模式(全自动调节参数)
    • P 编程自动模式(自动设定快门速度与 ISO)
    • S 快门速度优先模式(手动设置快门速度,自动设置 ISO)
    • M 手动曝光模式(手动设置快门速度与 ISO 以控制曝光,用于烟火或星空等特殊场景
  • 对焦功能
    • AF-C/S
    • 手动对焦
    • AF-ON
    • 人脸/眼部 AF ON / OFF
    • 对焦提示音
    • 对焦区域可视化
  • 白平衡
    • 自定义白平衡
    • 白平衡微调
    • AEL
    • DRO/ HDR
  • 其他
    • 低速/高速连拍与延迟拍摄
    • 3:2 照片比例
    • RAW 格式保存(单张照片约24MB,无法与连拍/HDR 同时启用)
    • 界面显示选项
    • 直方图
    • 水准仪等

熟悉索尼相机的用户相比可以很快上手,充分利用 Photo Pro 的各项功能。把 Photo Pro 设置为实体相机快门键长按启动的默认相机或许是个不错的主意。而半按快门 AEL 则是其他厂商无法提供的便捷功能。

Photo Pro 之所以令人满意,是因为它不但提供了丰富的手动拍摄选项,还维持了高水准的性能。配合 Xperia 1 II 的高通骁龙 865 处理器,以及 UFS3.0 高速闪存,以及更好的软硬件搭配,无论何时,Photo Pro 都保证了小于一秒的冷启动速度、JPEG + DRO 模式下数百张无压力的连拍能力、可以忽略不计的照片保存时间。在忍受了 Xperia 1 时而需要数秒冷启动且保存速度堪忧的相机软件后,Xperia 1 II 总算做到了一款旗舰产品应有的拍照体验。在手机上用 Lightroom 编辑 RAW 格式照片并同步到 Adobe Creative Cloud 则让 RAW 后期处理列入拍摄设备的能力范围,即使没有 PC 也能在拍摄作品后立即对原片做复杂的调整和修复。

最后简单谈谈画质,虽然这反而或许是手机摄影相对不那么关键的部分。毕竟真的亟需优质画质的场合,手机绝不是最佳选项。对于 24mm 的标准镜头,在光线充足时,Xperia 1 II 的成像没有比前代明显提升,主要是 Photo Pro 的 HDR 模式明显改善了光线对比强烈时的曝光效果。在弱光环境下,Xperia 1 II 体现出了硬件优势,画面明显干净很多。作为卖点的蔡司镜头仍然会在画面边缘存在一定畸变和画质下降,不过畸变在没有参照物时并不容易被察觉,画质下降也只有在需要局部裁剪放大时才会成为一个问题。总的来讲,这颗主摄的成像效果对得起它的宣传,是 Xperia 相机画质的正常进步。

Xperia 1 II 的广角与长焦镜头则比较平庸,与标准镜头的画质差距明显,在弱光环境下画质下降严重,与动辄高倍光学变焦的竞争对手相比甚至变焦能力也无法同台竞争,只能说是聊胜于无。或许其他两颗镜头的画质会成为明年 Mark III 的重点提升方向吧。不知何日才能重新看到十多年前索尼爱立信曾经在手机上使用过的光学变焦镜头。

ISO250 – 1/250 主摄像头。仅压缩。色彩还原自然一直是 Xperia 系列的特征。不过新的主摄镜头比过去更容易背景虚化,有时反而蛇足
ISO64 – 1/60 主摄像头。仅压缩。在需要虚化的时候,更大光圈带来的虚化也比较自然
ISO320 – 1/15 主摄像头。原尺寸约1/16区域局部裁剪。Lightroom RAW 格式后期。一方面,更高素质的主传感器和 RAW 格式保存,后期的余地明显增加。在光线不足时 Xperia 1 II 的表现比去年更上一层。另一方面,12MP 像素在裁剪时力不从心的问题也被暴露
ISO64 – 1/1000 主摄像头。仅压缩。也许是心理作用,也许是配合蔡司镜头做了调整,Xperia 1 II 拍摄的照片的色调和以往机型相比总有种说不出的微妙差异

致电影录制爱好者

Xperia 1 II 的另一项特色软件是从前代延续的 Cinematography Pro(下称 Cinema Pro)。

Cinema Pro 允许用户以 CineAlta 独有的 Look(滤镜,分别为 VENICE CS ・Opaque/Blue60Yellow60 ・Bright/Blue20Yellow60 ・Warm/Yellow80 ・Strong/Blue100 ・Cool/Blue60・Soft/Yellow40 ・Soft Monochrome)来录制 4K HDR 10bit 视频,或 2K 10bit HDR 120帧高帧率视频,并提供了水准仪与手动对焦等多种高级功能。

Xperia 1 II 除了软件功能优化,还专门对风噪抑制做了加强。

实话说,电影录制爱好者或许会因为 CineAlta 的名声,在使用 Cinema Pro 拍摄24帧的 21:9 电影时感到额外的乐趣。作为对此无感的普通人,很怀疑这个软件能够在 Xperia 上存在多久。目前看来,它更像是产品设计理念的一种象征罢了。

致电影鉴赏爱好者

和去年一样,Xperia 1 II 继续搭载了一块赏心悦目的高品质屏幕。

适合观影的 21:9 CinemaWide 屏幕比例、业界最高分辨率的 4K HDR OLED、X1™ for mobile 图像处理引擎、4K SDR 内容升格都是保留项目。这次就不再赘述。

新增的 90Hz 软件高刷新率在减少残影方面的效果比较微妙,它通过改进屏幕响应速度并调节像素亮度来模拟更高刷新率。效果有时能感知,有时则不能。主要在网页滚动等场景下会有一些差异。这或许是软件实现的极限,毕竟屏幕的硬件刷新率依然是 60Hz。虽然高刷新率屏幕如今成了高端产品竞相宣传的特性,但它确实不属于人人都有的需求,而且会带来耗电增加的副作用。比较好的做法也许是在后续产品中硬件支持高刷,但默认软件启用普通刷新率,让对刷新率有要求的用户可以各取所需。

创作家模式在 Xperia 1 II 上健在。引用之前的描述,在应用支持时,Xperia 1 II 能够以 HDR 高动态亮度范围、BT.2020 色域、D65 白平衡点、10bit 色深(软件模拟 8bit 硬件至近似 10bit 效果)的规格播放内容,还原电影导演在拍摄影片时的原始视觉效果,直接感受创作者想要传递的情感。对于优秀的作品,每一个场景都融入了创作者有意识的设计,强行用算法调整画面效果绝非最佳做法,甚至可能损害作品的完整性。Xperia 1 的创作家模式则为解决这一问题而生。目前,创作家模式会在 Netflex 与 CineaPro 两个应用中自动启用,用户也可手动选择切换。

创作家模式以索尼专有算法来表现以专业规格制作的视频内容,呈现更贴近创作者理念的视觉效果

从硬件上来看,Xperia 1 II 与 Xperia 1 使用了相同规格的屏幕。但或许是得益于软件改进,Xperia 1 II 无论是日常使用时屏幕显示的通透感和色彩表现力,都明显优于 Xperia 1,令人甚至怀疑这是否是因为 Xperia 1 使用一年多的屏幕自然老化才造成了如此差距。另,Xperia 1 II 的白平衡默认仍使用冷色调,算是遵从了所谓部分用户更偏好冷色调的说法来设置出厂白平衡。

由于硬件没有改变,Xperia 1 II 的最高亮度依然平庸,在室外亮度增强模式下也只有约650尼特的亮度,在阳光直射时可视性依然一般,如果长期在剧烈阳光下室外活动,需要多评估一下对屏幕最高亮度的需求。

主观上来讲,和以往一样,Xperia 1 II 的屏幕显示效果远好于其它一些厂家的高端机,色彩方面 OLED 容易出现的味精感,或是特殊像素排列造成的模糊感,在 Xperia 1 II 上都很难发现。如果追求屏幕效果,Xperia 依然是和 iPhone、Galaxy 同级的少数选项之一。更何况,没有刘海和挖孔的屏幕,才不会在观看宽屏电影时不可避免地缺失一块画面,不是吗?

致音乐欣赏爱好者

Xperia 1 II 搭载了极为罕见而先进的 3.5mm 耳机插孔(笑)。

Xperia 高端机型在取消耳机孔数代后,又把它改了回来。声道干扰比上代减少90%,仅为 20dB。过去的数字音频升格技术 DSEE HX 结合 AI 算法,改名为 DSEE Ultimate,在使用有线耳机时,能更好地将各类音源的码率提升至 HiRes 水准。尽管自己是蓝牙耳机支持者,但不得不承认 Xperia 1 II 和有线耳机 XBA-N3 的搭配,比支持 LDAC 高解析度蓝牙音频的同价位蓝牙耳机,有更好的主观听感,并且,无需充电。除了 LDAC,Xperia 1 II 的蓝牙新支持 aptX Adaptive,延迟较以往更低。

据访谈介绍,Xperia 1 II 的音响调教继续得到索尼音乐的专业支持。屡获殊荣的资深调教工程师 Mark Wilder 两次参与 Xperia 1 II 的音频调教研讨会并提出建议,最后对其音质表现表示肯定。

此外,支持 Dolby Atmos 的正面双扬声器位置得到改善,下方扬声器也能从屏幕正面发声。驱动单元则重新开发,推力和低音表现都比上代提升。不过对于很少使用外放的人来讲,这是无关紧要的改进。

致手机游戏爱好者

Xperia 1 II 虽然不是游戏手机,但也有专门的游戏模式,并联手堡垒之夜或 Call of Duty:Mobile 等游戏对其 21:9 的屏幕比例做了优化,能显示更广阔的视野。

Xperia 的游戏增强模式主要做了以下几方面的工作:性能优化、游戏录制、免干扰、防误触、直接供电。

虽然不用手机玩游戏,但已经听说直接供电模式下,由于不会对电池充电,手机的温度会较通常更低,不容易触及软件设置的温度墙而降频处理器来保护设备。该功能不但可以减少游戏因处理器性能受限而引发卡顿,还能减少电池因高温导致的寿命缩减,如果需要高负荷长时间使用非游戏类应用,想必也能发挥效果。

致 Xperia 爱好者

Xperia 1 II 的基础功能是 Xperia 系列的新高峰。

最新的高通骁龙 865 芯片组、8G内存、256GB UFS 3 高速闪存的组合使运行任何程序都流畅快速。支持最大1.7Gbps的 4G 下行速率与 3.4Gbps 的 5G 下行速率。没有减去 IP58 防水能力和 MicroSD 卡扩展,增加无线充电的情况下,机身重量还能控制在同级较轻的 181g + 7.9mm 厚,宽度也仅有72mm。看着这两年竞争对手频繁推出重量超过200g的产品,为当年索尼因 Xperia XZ2 Premium 而在网络上背负半斤骂名感到可惜。

一个可喜的改善是,Xperia 1 因专利问题而使用的与电源分离的小尺寸侧面指纹模块终于被替换回了过去的整合式指纹开关,识别率也恢复到了 Xperia XZ Premium 的水平,在绝大多数时候都能迅速识别解锁。Xperia 1 底部略有些割手的 USB 口问题也因为新的边框倒角设计而被解决。

4000mAh 的系列高端机型最大电池容量,提供100小时的 4G 待机时间和85小时的 5G 待机时间。支持 21W PD 快充,能在30分钟内充电50%。同时系列传统的电池长寿技术能智能学习用户的充电习惯,避免过充,让电池性能在两年内不会显著衰减。索尼与苹果三星一样,似乎对快充技术从不激进,峰值充电功率距离国产厂商越来越远。所幸自己这么多年来哪怕一次也没有遇到过需要手机短时间充电的情况,所以对快充需求实在无感。

一个多月的实际使用来看,4000mAh 电池按个人使用习惯(白天约2小时蓝牙音乐、一小时通信与一小时网页浏览等亮屏操作,大部分时间 WiFi 连接),可以在工作日下班时剩余70%左右的电量,即使手机使用较多,通常也不会低于50%。这一数字比之前容量不到 3500mAh 的机型有可感知的差距。仅针对自己来讲,电池焦虑恐怕很难再会出现。

外形设计方面,传承当年 Xperia Z2 神韵的具有高级感的边框设计,相比 Xperia 1,Xperia 1 II 更充满了 Xperia 的个性,每次拿起手中,都会满心欢喜。索尼没有在 Xperia XZ2/XZ3 设计语言的不归路上越走越远,总算做到了至少取悦了 Xperia 的爱好者们。

就这样,Xperia 1 II 几乎全方位地改进了上一代存在的或严重或细节的问题,无论任何一个方面来看,体验都可谓系列最佳。可以说,Xperia 1 II 是一台能让 Xperia 爱好者重燃希望的机型,或许会和 Xperia XZ Premium 一样成为一代名机。

2020/10/17 更新

使用四个月后的初步结论是,Xperia 1 II 在系统稳定性、发热与续航控制、相机性能等影响使用体验的重点方面做得很不错,在 Xperia 系列历史上应该可以位列第一。中等强度使用下也不会有续航不足一天的焦虑、相机的启动、对焦、保存速度在使用一段时间后依然在比较理想的状态。即使类原生 Android 系统在国内软件生态下难免水土不服,Xperia 1 II 也靠电池和性能的升级,总算是一定程度上缓解了问题。

2021/01/26 更新

今天 Xperia 1 II 港版系统推送了 Android 11 大版本更新。安装程序大小约1.1GB,在网络条件允许时大约需要三分钟下载,及约十分钟安装,并重启。除了 Android 11 本身对权限控制和隐私保护等方面的增强以及安全补丁外,在这次更新更新后,Cinematography Pro 新增 4K HDR 120 慢动作摄像。Photography Pro 新增照片纵横比快捷设置按钮、MR 模式,及连拍反馈。新增支持通过 HDMI-UVC 与 Alpha 无反相机连接作为其外部监视器。侧感触控易用性增强,支持浮窗快捷方式。游戏增强器新增游戏图标收纳功能。电池保养功能支持常时80/90% 充电限制。内建屏幕录制、增强媒体播放控制、Nearby Share 文件共享功能。长按电源键的界面等细节也跟随 Android 11 改变。

Xperia 1 II 也并非没有缺憾。在网络上有见到说白色机型后盖内部可能发生掉漆(这台还没发现)、非居中的摄像头突起导致在桌面上平方时不稳(虽然目前绝大多数手机都如此设计)、耳机孔和 USB 孔或许会在长期使用后接触不良(Xperia 的通病,暂时不对 Xperia 1 II 能彻底解决这个问题乐观)、Xperia 自带的特色软件继续被去除(Movie Creator 可以通过 APK 安装、相册不再被支持只能使用性能功能都更强但缺乏特色的 Google Photo、LifeLog 结束服务,等等)、在原生 Android 系统基础上做的增强过少,一些用户喜爱的其他厂商早已默认提供的定制功能不得不自己安装额外的软件才能拥有,甚至最终无法实现、一些软件,尤其是游戏,至今没有对 21:9 屏幕比例进行优化,等。

今后使用过程中发现更多的问题,会持续更新和补充。

【图文内容不定期更新】

本文相关图片版权属于各版权所有人

解决 HTML Canvas 元素在高像素密度/高分辨率屏幕上显示模糊的问题

最近在使用 HTML Canvas 元素时发现通过 fillText() 绘制的文字明显发虚,像是以低分辨率渲染后放大所致,再仔细一检查,发现事实上包括 fillRect() 在内的其他图案也都存在相同的问题。

初步推测和显示设备使用了较高的 DPI 有关,随进行了一番搜索,在 Stackoverflow 、Medium 等站点都有一些提问和回答。然而意外的是,自己能找到的一些解答,至少在自己这边并不能解决问题。

经过摸索,找到了能够解决自己问题的办法,分享于此,以便后人。

以下为 Angular component 代码片段,语言为 TypeScript。

@ViewChild('canvas', { static: true }) canvas: ElementRef; // Canvas 元素
@ViewChild('canvasDiv', { static: true }) canvasDiv: ElementRef; // Canvas 元素的父元素,一个 div
private ctx: CanvasRenderingContext2D; // Canvas context

private dpiRatio: number; // DPI 缩放比例
private canvasDivWidth: number;  // 父元素宽度

……

this.dpiRatio = window.devicePixelRatio;

this.canvasDivWidth = this.canvasDiv.nativeElement.offsetWidth;

// 分别设置 canvas 的宽度和样式宽度,canvas 的显示尺寸将会减半
this.ctx = this.canvas.nativeElement.getContext('2d');
this.ctx.canvas.width = this.canvasWidth * this.dpiRatio;
this.ctx.canvas.style.width = this.canvasWidth + 'px';

// 在绘制时考虑缩放因素
this.ctx.font = 12 * this.dpiRatio + 'px Roboto';
this.ctx.fillText('HIDPI文字', x  * this.dpiRatio, y * this.dpiRatio);

一个悬而未决的问题是,canvas context 本身的 transfer 函数似乎不能做到整体的放大,因此这里作为临时方案暂时在绘制每一个图形时都乘以了缩放倍率。这里应该有更好的办法,不过限于时间,暂且搁置。

Angular 9+ 升级小记 —— 应付 MSAL-Angular 与 ngx-restangular 的兼容性问题

之前几次升级 Angular 版本的经历总体还算顺利,因此原本对 Angular 8 升级到 9 的过程也比较乐观。虽然 Angular 9 开始将默认启动新的 Angular Ivy,但考虑到已经正式发布数月,甚至 Android 10 都已问世,自己的项目又没有用特别冷门的依赖,依然没有担心会遇到问题。可惜墨菲定律无处不在,最后还是花了比想象中更多的时间完成升级。

为此,本文简单介绍自己在从 Angular 8 升级到 9 最终到 10 时遇到的问题及相应的解决方法,仅供参考。

首先,Angular 官方文档提供了详细的升级说明,建议在升级项目前首先通览相关文档,了解可能存在的问题。可以从下面的链接找到升级到 Angular 10 的最新信息。

https://angular.io/guide/updating-to-version-10

下面是自己在升级时实际操作的几个主要步骤:

  • 更新 Angular 8 相关依赖至最新版
    • ng update @angular/core@8 @angular/cli@8
    • ng build –prod –aot
    • 确认变更
  • 更新 @azure/msal-angular 至最新版 1.0.0
    • 安装 1.0.0 版并为新版的接口变化修改代码(1)
    • ng build –prod –aot
    • 确认变更
  • 升级至 Angular 9,检查并乎略一些依赖版本问题
    • ng update @angular/core@9 @angular/cli@9 –force(2)
    • ng build –prod –aot
    • 确认变更
    • 升级 Angular Material
      • ng update @angular/material@9
      • 检查 Angular Material 引用问题(3)
    • 增加 ngcc 作为 postinstall 脚本(4)
    • ng build –prod –aot
    • 确认变更
    • ng add @angular/localize (5)
    • ng serve –ssl 启动并检查应用基本功能
  • 升级至 Angular 10,检查并乎略一些依赖版本问题
    • ng update @angular/core @angular/cli –force
    • 临时手段解决 ngx-restangular 编译问题(6)
    • ng build –prod –aot
    • 确认变更
    • ng update @angular/material
    • ng build –prod –aot
    • 确认变更
    • ng serve –ssl 启动并检查应用基本功能
  • 大功告成

以下具体说明上述步骤中的一些关键操作。

(1)MSAL Angular 代码更改

在升级 Angular 9 之前,自己的项目使用 MSAL Angular 0.1.4 实现对 Microsoft 账户或 ADD 的验证。当时该库的文档和范例代码质量就差强人意,缺少说明和链接失效比比皆是。更重要的是,该库并不兼容 Angular Ivy,这也是没有更早升级 Angular 9 的原因之一。等着 MSAL Angular 花了几个月的时间终于正式发布 1.0.0 版本才开始升级,依然遇到几个问题:

  • 方法接口变化,getUser() 改为 getAccount(),displayableId 成员取消
  • 服务初始化方式变化,结构虽然较过去清晰,但文档和示例代码不足,甚至还有语法拼写错误
  • 请求验证成功后返回的 payload 格式发生变化,token 变量改为 rawIdToken
  • loginRedirect() 似乎不再正常工作,仍需进一步排查原因

无论如何,能够兼容 Angular 9 已经不易,总比 ngx-restangular 那样根本无法成功编译要好些。MSAL Angular 已经两个月没有新版本发布,不知今后的更新是否能解决一些问题。

(2)升级至 Angular 9

这步本身没有什么问题,不过需要检查一些报警的依赖版本冲突。自己的项目中主要是 tslib 已经到了 2.0 而 Angular 9 要求 1.10.0,以及 Angular http 停在了大版本7。确认没有问题后就以 –force 参数强制升级。

(3)检查 Angular Material 引用问题

新版本 Angular Material 要求每个引用都明确指定具体组件,如:

 import { MatSpinner } from '@angular/material/progress-spinner';

而不允许在一句引用中同时引入多个组件,如:

import { MatSpinner, MatSnackBar } from '@angular/material';

正常情况下 ng update 会自动更正代码,不过自己在操作时似乎遇到一些问题,没有顺利完成,只好收到批量做了一些处理。

(4)增加 ngcc 作为 postinstall 脚本

在 package.json 中增加 “postinstall”: “ngcc” 有助于避免可能的库兼容问题。参见 ngcc 的和 ModuleWithProviders 迁移的相关说明。

(5)增加 @angular/localize

如果项目中使用了 Angular 自带的 i18n 功能,可能需要执行 ng add @angular/localize 添加必要的依赖。不过这并非必要步骤,可以在遇到提示时才采取行动。

(6)解决 ngx-restangular 5.0.0 编译问题

很可惜,ngcc 不是银弹。至少,它无法解决 ngx-restangular 的兼容问题。

ngx-restangular 是自己项目中使用的主要第三方库之一,帮助使用 REST API 的使用。这个项目本身算不上太活跃,但基本功能还算充分。可惜的是,半年没有更新的它,果然无法在 Ivy 下正确编译,报错如下:

ERROR in node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts:8:97 - error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).

static forRoot(providers?: any[], configFunction?: (provider: any, ...arg: any[]) => void): ModuleWithProviders;

搜索尝试一些方法无果后,不得已手动修改库文件,增加类型 <RestangularModule> 在 node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts 第八行末尾:

static forRoot(providers?: any[], configFunction?: (provider: any, ...arg: any[]) => void): ModuleWithProviders<RestangularModule>;

在 CI 管道中,则暂时每次都在 ng build 之前以 sed 命令完成代码更改:

sed -i 's/ModuleWithProviders;/ModuleWithProviders<RestangularModule>;/g' node_modules/ngx-restangular/lib/ngx-restangular.module.d.ts

于是,暂时绕过了编译错误。ngx-restangular 的功能本身倒似乎没有问题,可以正常工作。

经过功能确认和测试后,一个 Angular 8 应用终于顺利升级为了 Angular 10 应用。尽管并非一帆风顺,但 Ivy 确实明显提升了编译性能并减小了体积,总管没有白费功夫。如有需要,还可以参考 AngularGo GitHub 地址),了解升级过程中的配置与代码更改。

Die Alltägliche

No. 17

这次的构想是居家办公途中听到呼喊而回头望向后方的瞬间

_

又是一年。于是今年也再度拿起画笔,趁着悬而未立,趁着多少还能确保一些能够自己支配的业余时间,再随着自己的性子去做些什么,留下些什么。画画有意思的地方在于可以随心所欲,暂时享受造物主的特权。

回想起来,上次把笔记本电脑作为道具画在画里竟然已经是九年之前。这次也算是回归初心。Surface Laptop 2 的宣传语是 A touch above ordinary,倒也恰好与标题契合。画的另一个小道具 Xperia 1 是最近一年的主力机,爱不释手。

过去一年是神奇的一年。非要说的话,或许是在过去很多年里,在今后很多年内,都很不寻常。为一些坏的情况做了准备,但最坏的情况最终竟也没有发生。对一些好的结果有所期望,但最好的结果似乎也不会实现。失望、希望、踌躇、前进。既然总有些事无法克服,那就只好尽量与之和平共处。不知不觉中,可能已经习惯了这样的状态。

迄今为止都在拼命地向前冲刺,告诉自己说,要做的更好,要变得更好。但怎样才算是更好,又怎样才能界定呢。是世俗意义的成功,还是想象中的自我实现?年初的时候还跟朋友聊到说,仍以为自己不是特别普通。实际又如何呢。也许,更多是一种相信,一份期待吧。对幻想中的美好。

嗯。加油。

要再厉害一点。

Du bist besonders.

_

_

_

One more thing…

Ver. Hoodie

Angular on Azure Web App Service (IIS)

部署于 Azure App Service 的 Web App 事实上运行于 IIS (Internet Information Services),因此也可以通过 web.config 文件来配置它的行为。

由于 Angular 是一种 SPA Web 框架,需要对 IIS 做一些额外的 URL Rewrite 配置,才能在浏览器刷新页面时依然成功载入内容,参见以下代码。

规则 Index Rule 的作用是把所有匹配的 HTTP 请求全都重定向至 “/” 路径,之后 Angular 自己的路由(Routes)将会继续工作,完成内容的载入和跳转。可以参考此处了解如何实现 lazy loading 。

staticContent 节点则定义了允许的 mimeType,否则直接访问 contentType 为 application/json 等类型的请求将返回 404 Not Found。

复旦大学校歌

刘大白 词
丰子恺 曲

歌词:
复旦复旦旦复旦,巍巍学府文章焕,
学术独立思想自由,政罗教网无羁绊,
无羁绊前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。
复旦复旦旦复旦,师生一德精神贯,
巩固学校维护国家,先忧后乐交相勉,
交相勉前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。
复旦复旦旦复旦,沪滨屹立东南冠,
作育国士恢廓学风,震欧铄美声名满,
声名满前程远,向前,向前,向前进展。
复旦复旦旦复旦,日月光华同灿烂。

AngularGo —— 一个开源 Angular SPA 模板

在接触 Angular 后,这些年工作业余也用 Angular 做了若干实际项目。不过,由于 Angular 在国内的流行度不高,各种原创内容和参考资料也相对较少。虽然网络上也能找到各种各样的技术文章,官方的文档也很全面,但总的来讲,信息还是有些分散。

很惭愧,几年里没有做什么特别有技术含量的工作。 只是提炼出一个很基础的模板,帮助开发者快速创建一个 SPA(Single Page Application)站点,或是供对 Android 感兴趣的读者了解 Android 的语法和基本的框架机制。该模板先分享于此 —— AngularGo on GitHub

该模板基于目前最新的 Angular 8,且会持续跟进更新。在 Angular CLI 自动创建的范例项目的基础上,目前版本的 AngularGo 还包含以下内容:

  • Angular 8 以及相关依赖的最新版本配置
  • 一种可能的源文件结构示例
  • 一种与 Cordova 共享代码库的可能方式
  • 基础 Angular 组件及依赖注入的使用范例
  • 基础 Angular Material 控件的使用范例
  • 支持桌面和移动设备的抽屉式侧滑菜单
  • 支持 lazy loading 的 app-routing 全局路由
  • 支持 authentication guard 的模块路由
  • 支持 bearer token 验证的 Restangular 初始化及 service 用例
  • 基于 HttpClient 的用户注册与登录 API 调用
  • 基于 scss 的 Angular Material 样式(尚未采用 BEM 命名规则)
  • Azure Application Insights 集成
  • 适用于 Windows server/ Azure App Service 的 web.config 配置

AngularGo 还很初步,很多细节因水平有限和时间限制写得也比较粗糙,想必会有其他优秀的开源模板提供了更好的实现。从某种意义上来讲,该模板一方面是对自己经验得一个整理,同时期望能起到一个抛砖引玉的作用。希望对读者有帮助,也欢迎批评指教。