ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

赋予 Android 通知可穿戴特性:创建、语音回复、多页面与堆叠实战指南(android-training-course-in-chinese)

赋予 Android 通知可穿戴特性:创建、语音回复、多页面与堆叠实战指南(android-training-course-in-chinese) 文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载本指南以 android-training-course-in-chinese 仓库中 赋予 Notification 可穿戴特性 一课为核心系统讲解如何让手持设备上的 Notification 以最佳形态呈现在 Android 可穿戴设备上。读完本文你将掌握使用 Support Library 创建可穿戴通知、通过 RemoteInput 接收语音回复、为通知附加多页面以及把相似通知堆叠成一叠的完整实现方案。当一部 Android 手持设备手机或平板与 Android 可穿戴设备连接后手持设备上的 Notification 会被自动共享给可穿戴设备。在可穿戴设备上每条通知都以一张新卡片的形式出现在context stream可穿戴设备的主页卡片流中。如果开发者不加以干预通知只是被动同步而通过为通知添加可穿戴特性才能给用户带来与手表形态匹配的交互体验。图 1.同一条通知同时展示在手持设备与可穿戴设备上手机端是标准的通知栏形态手表端则以卡片形式出现在 context stream 中右上角为应用图标底部带翻页指示器。一、课程体系四步打造可穿戴友好通知本模块共包含四节课程从基础创建到交互增强层层递进全部基于 Android v4 Support Library 实现代码可直接运行于 API level 4 及以上的手持设备课程仓库路径核心知识点创建 Notificationwearables/notifications/creating.mdNotificationCompat.Builder、Action 按钮、Big View、WearableExtender、NotificationManagerCompat在 Notification 中接收语音输入wearables/notifications/voice-input.mdRemoteInput、预设文本反馈、getResultsFromIntent为 Notification 添加页面wearables/notifications/pages.mdaddPage() / addPages() 多页面通知以 Stack 的方式显示 Notificationswearables/notifications/stacks.mdsetGroup()、setSortKey()、setGroupSummary()下文将逐节展开并在关键处补充源码级注意点与可穿戴自定义布局的边界说明后者参见 wearables/apps/layouts.md。二、创建可穿戴设备可用的 Notification使用NotificationCompat.Builder创建的通知无论出现在手持设备还是可穿戴设备上系统都会正确显示。需要注意一个边界使用 RemoteViews 自定义布局的通知会被剥除自定义 layout在可穿戴设备上只显示文本和图标。若想保留自定义布局只能通过运行在可穿戴设备上的应用来创建详见 wearables/apps/layouts.md。2.1 引入依赖与必要类在build.gradle中加入 Support Library v4 依赖compile com.android.support:support-v4:20.0.说明compile是早期 Gradle 依赖写法示例版本20.0.对应 Android Wear 初期的 API level 20 时代在当前新项目中请替换为implementation androidx.core:core:...等对应坐标但NotificationCompat/NotificationManagerCompat/WearableExtender的使用方式一致。随后引入关键类import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.app.NotificationCompat.WearableExtender;v4 Support Library 让开发者能够使用最新的通知特性如 action 按钮、大图标创建通知并兼容 Android 1.6API level 4及以上版本。2.2 通过 Notification Builder 创建通知创建NotificationCompat.Builder实例构建内容 Intent 与 PendingIntent再交给NotificationManagerCompat.notify()发出int notificationId 001; // Build intent for notification content Intent viewIntent new Intent(this, ViewEventActivity.class); viewIntent.putExtra(EXTRA_EVENT_ID, eventId); PendingIntent viewPendingIntent PendingIntent.getActivity(this, 0, viewIntent, 0); NotificationCompat.Builder notificationBuilder new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent); // Get an instance of the NotificationManager service NotificationManagerCompat notificationManager NotificationManagerCompat.from(this); // Build the notification and issues it with notification manager. notificationManager.notify(notificationId, notificationBuilder.build());通知在手持设备上时用户触摸通知即可触发setContentIntent()设置的 PendingIntent在可穿戴设备上时用户向左滑动通知会出现Openaction点击即可激活手持设备上的 Intent——这是可穿戴端打开应用的标准手势。2.3 添加 Action 按钮除了setContentIntent()定义的主要 action还可以把 PendingIntent 传给addAction()添加其他 action。下面的代码创建了一个同前相仿的通知额外添加了在地图上查看事件位置的 action// Build an intent for an action to view a map Intent mapIntent new Intent(Intent.ACTION_VIEW); Uri geoUri Uri.parse(geo:0,0?q Uri.encode(location)); mapIntent.setData(geoUri); PendingIntent mapPendingIntent PendingIntent.getActivity(this, 0, mapIntent, 0); NotificationCompat.Builder notificationBuilder new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent);交互差异如下手持设备上 action 表现为通知上附加的额外按钮可穿戴设备上 action 表现为通知左滑后出现的大按钮。点击 action 时都能触发手持设备上对应的 Intent。提示如果通知包含回复类 action如短信应用可结合语音输入增强体验见 wearables/notifications/voice-input.md。2.4 可穿戴设备专属 Action如果希望可穿戴设备上的 action 与手持设备不同使用WearableExtender.addAction()。一旦通过该方式添加 action可穿戴设备便不会显示任何通过NotificationCompat.Builder.addAction()添加的 action——因为只有WearableExtender.addAction()添加的 action 才仅出现在可穿戴设备上// Create an intent for the reply action Intent actionIntent new Intent(this, ActionActivity.class); PendingIntent actionPendingIntent PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Create the action NotificationCompat.Action action new NotificationCompat.Action.Builder(R.drawable.ic_action, getString(R.string.label, actionPendingIntent)) .build(); // Build the notification and add the action via WearableExtender Notification notification new NotificationCompat.Builder(mContext) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(new WearableExtender().addAction(action)) .build();2.5 添加一个 Big View通过setStyle()传入BigTextStyle或InboxStyle实例可以给通知插入扩展文本。手持设备上用户需要展开通知才能看到 big view可穿戴设备上 big view 内容默认可见因此这是为手表提供长文本的推荐途径。// Specify the big view content to display the long // event description that may not fit the normal content text. BigTextStyle bigStyle new NotificationCompat.BigTextStyle(); bigStyle.bigText(eventDescription); NotificationCompat.Builder notificationBuilder new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_event) .setLargeIcon(BitmapFactory.decodeResource( getResources(), R.drawable.notif_background)) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent) .setStyle(bigStyle);提示原文此处写作BitmapFractory应为BitmapFactoryandroid.graphics.BitmapFactory。此外setLargeIcon()设置的大图标在可穿戴设备上会被放大成背景图片显示效果通常不佳为可穿戴设备专门设置背景图片请用 2.6 小节的WearableExtender.setBackground()。2.6 为通知添加可穿戴特性WearableExtender当需要制定附加内容页、语音输入等可穿戴专属选项时使用NotificationCompat.WearableExtender操作分四步创建WearableExtender实例设置可穿戴设备独有的特性创建NotificationCompat.Builder实例设置常规通知属性调用extend()并把WearableExtender传入应用可穿戴选项调用build()构建最终 Notification。下面的代码调用setHintHideIcon(true)把应用图标从通知卡片上删掉并用setBackground()指定背景图// Create a WearableExtender to add functionality for wearables NotificationCompat.WearableExtender wearableExtender new NotificationCompat.WearableExtender() .setHintHideIcon(true) .setBackground(mBitmap); // Create a NotificationCompat.Builder to build a standard notification // then extend it with the WearableExtender Notification notif new NotificationCompat.Builder(mContext) .setContentTitle(New mail from sender) .setContentText(subject) .setSmallIcon(R.drawable.new_mail) .extend(wearableExtender) .build();setHintHideIcon()与setBackground()只是WearableExtender众多可穿戴新特性的两个例子。位图尺寸有严格要求非滚动背景使用400x400分辨率支持视差滚动的背景使用640x640分辨率位图资源放在res/drawable-nodpi目录其他非位图资源如setContentIcon()用到的放在res/drawable-hdpi目录。如需稍后读取已设置的可穿戴特性使用对应的 get 方法例如getHintHideIcon()NotificationCompat.WearableExtender wearableExtender new NotificationCompat.WearableExtender(notif); boolean hintHideIcon wearableExtender.getHintHideIcon();2.7 传递通知务必使用 NotificationManagerCompat传递通知必须使用NotificationManagerCompat而非 framework 层的NotificationManager// Get an instance of the NotificationManager service NotificationManagerCompat notificationManager NotificationManagerCompat.from(mContext); // Issue the notification with notification manager. notificationManager.notify(notificationId, notif);如果误用 framework 的NotificationManagerNotificationCompat.WearableExtender中的部分特性会失效这是创建可穿戴通知时最容易踩的坑。三、在 Notification 中接收语音输入当手持设备上的通知包含输入文本类 action如回复邮件时在手机端通常会唤起一个 Activity 让用户输入。但可穿戴设备没有键盘因此应该用RemoteInput让用户通过语音反馈或选择预设文本完成回复系统会把转录的文本与通知中指定 action 的 Intent 绑定并发送给手持设备上的应用。注意Android 模拟器不支持语音输入。使用可穿戴设备模拟器时可打开 AVD 设置中的Hardware keyboard present用打字代替语音来调试。3.1 定义语音输入创建RemoteInput.Builder实例并挂到通知的 action 上。构造函数接受一个 String 参数系统把它作为语音输入的 key后面用这个 key 从手持设备收到的文本中取值// Key for the string thats delivered in the actions intent private static final String EXTRA_VOICE_REPLY extra_voice_reply; String replyLabel getResources().getString(R.string.reply_label); RemoteInput remoteInput new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build();setLabel()用于设置提示语音输入的自定义 label会在手表的语音输入界面上展示。3.2 添加预先设定的文本反馈除了语音输入还可以提供最多5 条预设文本反馈用户直接点选即可快速回复。该功能通过setChoices()传入 String 数组实现。用 resource 数组定义这些反馈res/values/strings.xml?xml version1.0 encodingutf-8? resources string-array namereply_choices itemYes/item itemNo/item itemMaybe/item /string-array /resources然后填充 String 数组并加入RemoteInputpublic static final String EXTRA_VOICE_REPLY extra_voice_reply; ... String replyLabel getResources().getString(R.string.reply_label); String[] replyChoices getResources().getStringArray(R.array.reply_choices); RemoteInput remoteInput new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build();说明原文此处EXTRA_VOICE_REPLY缺少类型声明写作public static final EXTRA_VOICE_REPLY ...应补上String类型。带预设选项时手表端会同时显示 Speak now 提示与 Yes/No/Maybe 等快捷回复项。3.3 把语音输入作为 Notification 的 action把RemoteInput对象通过Action.Builder.addRemoteInput()挂到 action 上再将 action 应用进通知// Create an intent for the reply action Intent replyIntent new Intent(this, ReplyActivity.class); PendingIntent replyPendingIntent PendingIntent.getActivity(this, 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Create the reply action and add the remote input NotificationCompat.Action action new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon, getString(R.string.label, replyPendingIntent)) .addRemoteInput(remoteInput) .build(); // Build the notification and add the action via WearableExtender Notification notification new NotificationCompat.Builder(mContext) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(new WearableExtender().addAction(action)) .build(); // Issue the notification NotificationManagerCompat notificationManager NotificationManagerCompat.from(mContext); notificationManager.notify(notificationId, notification);通知发出后用户在可穿戴设备上左滑即可看到 reply 按钮点击后进入语音/预设选项界面说出的内容会实时转成文本显示在手表面。3.4 在手持应用中取出语音文本在 reply action 指定的 Activity 中通过RemoteInput.getResultsFromIntent()拿到用户转录后的消息。该方法返回包含文本反馈的Bundle按 key 查询即可/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private CharSequence getMessageText(Intent intent) { Bundle remoteInput RemoteInput.getResultsFromIntent(intent); if (remoteInput ! null) { return remoteInput.getCharSequence(EXTRA_VOICE_REPLY); } } return null; }重要不要用Intent.getExtras()获取语音输入结果因为语音输入内容存储在ClipData中。getResultsFromIntent()提供了一条便捷通道直接返回字符序列无需自行解析 ClipData。四、为 Notification 添加附加页面当希望在不要求用户打开手机 App 的情况下表达更多信息时可以为可穿戴设备上的通知添加一个或多个页面。附加页面会出现在主通知卡片的右边用户左右滑动即可翻阅——典型场景如日程提醒第一页是10 分钟后与 Rachel 野餐 地点 时间第二页补充带上面包、奶酪和红酒等备注。创建多页面通知只需三步通过NotificationCompat.Builder创建主通知首页按需要在手持设备上呈现通过NotificationCompat.Builder为可穿戴设备创建更多页面通过WearableExtender.addPage()把页面应用到主通知或用addPages()一次添加一个Collection。示例代码为通知添加第二个页面// Create builder for the main notification NotificationCompat.Builder notificationBuilder new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.new_message) .setContentTitle(Page 1) .setContentText(Short message) .setContentIntent(viewPendingIntent); // Create a big text style for the second page BigTextStyle secondPageStyle new NotificationCompat.BigTextStyle(); secondPageStyle.setBigContentTitle(Page 2) .bigText(A lot of text...); // Create second page notification Notification secondPageNotification new NotificationCompat.Builder(this) .setStyle(secondPageStyle) .build(); // Add second page with wearable extender and extend the main notification Notification twoPageNotification new WearableExtender() .addPage(secondPageNotification) .extend(notificationBuilder) .build(); // Issue the notification notificationManager NotificationManagerCompat.from(this); notificationManager.notify(notificationId, twoPageNotification);注意附加页面通常使用BigTextStyle承载长文本手持设备上只会显示主通知附加页面仅存在于可穿戴端。五、把相似通知放成一叠Stack5.1 为什么要堆叠为手持设备创建通知时多个相似通知应当合并成一条概括式通知例如收到多条短信时只显示2 条新消息。但概括式通知在可穿戴设备上并不好用——用户无法直接阅读每条消息的详细内容。因此对可穿戴设备而言正确做法是把各条通知集中放成一叠。这叠通知以一张卡片形式显示用户可以展开它逐条查看详情。通过setGroup()实现堆叠的同时手持设备上依然显示为一条概括式通知两端体验各得其所。5.2 用 setGroup 把每条通知加入群组对每条想要放入 stack 的通知调用setGroup()并指定同一个 group key然后notify()发出final static String GROUP_KEY_EMAILS group_key_emails; // Build the notification, setting the group appropriately Notification notif new NotificationCompat.Builder(mContext) .setContentTitle(New mail from sender1) .setContentText(subject1) .setSmallIcon(R.drawable.new_mail) .setGroup(GROUP_KEY_EMAILS) .build(); // Issue the notification NotificationManagerCompat notificationManager NotificationManagerCompat.from(this); notificationManager.notify(notificationId1, notif);创建第二条通知时指定同样的 group key它就会进入同一个 stack 而非新建卡片Notification notif2 new NotificationCompat.Builder(mContext) .setContentTitle(New mail from sender2) .setContentText(subject2) .setSmallIcon(R.drawable.new_mail) .setGroup(GROUP_KEY_EMAILS) .build(); notificationManager.notify(notificationId2, notif2);说明原文示例中第一、二个代码块在.setSmallIcon(...)后多写了一个分号会导致链式调用语法错误上述代码已修正。默认情况下通知按添加先后排列最近的通知位于最顶端可通过setSortKey()自定义排序。5.3 添加概括式 Notification只出现在手持设备手持设备上提供概括式通知很重要除了把每条单独通知放进同一个 group还要额外创建一条概括式通知并对其调用setGroupSummary(true)。这条概括式通知不会出现在可穿戴设备的 stack 中只显示在手持设备上Bitmap largeIcon BitmapFactory.decodeResource(getResources(), R.drawable.ic_large_icon); // Create an InboxStyle notification Notification summaryNotification new NotificationCompat.Builder(mContext) .setContentTitle(2 new messages) .setSmallIcon(R.drawable.ic_small_icon) .setLargeIcon(largeIcon) .setStyle(new NotificationCompat.InboxStyle() .addLine(Alex Faaborg Check this out) .addLine(Jeff Chang Launch Party) .setBigContentTitle(2 new messages) .setSummaryText(johndoegmail.com)) .setGroup(GROUP_KEY_EMAILS) .setGroupSummary(true) .build(); notificationManager.notify(notificationId3, summaryNotification);这里使用了NotificationCompat.InboxStyle它非常适合创建邮件/短信类通知概括式通知也可以用其他 style 或不使用任何 style。5.4 为整个 Stack 设置背景与 Action概括式通知虽然不显示在可穿戴设备上却可以影响可穿戴设备上的整个 stack在其上使用WearableExtender通过setBackground()或addAction()为整个 stack 统一设置背景或 actionBitmap background BitmapFactory.decodeResource(getResources(), R.drawable.ic_background); NotificationCompat.WearableExtender wearableExtender new NotificationCompat.WearableExtender() .setBackground(background); // Create an InboxStyle notification Notification summaryNotificationWithBackground new NotificationCompat.Builder(mContext) .setContentTitle(2 new messages) ... .extend(wearableExtender) .setGroup(GROUP_KEY_EMAILS) .setGroupSummary(true) .build();如上图所示堆叠后的通知以一张卡片示人底部标注 5 more用户展开后即可逐条阅读对应仓库截图 11_bundles_B.png。六、标准通知的边界何时需要自定义布局本节内容来自 wearables/apps/layouts.md用于澄清标准通知方案的能力边界通常的做法是在手持应用上创建通知让它自动同步到可穿戴设备也包括车载与电视等 Android 衍生形态只需创建一次、多端复用无需为每类设备重新设计。当标准通知风格BigTextStyle、InboxStyle等无法满足需求时可显示一个使用自定义布局的 Activity。自定义通知只能在可穿戴设备上创建并处理系统不会把它们同步回手持设备——这与本文介绍的通知自动同步方向正好相反。在可穿戴设备上创建自定义通知时可以使用标准 Notification APIAPI level 20不需要 Support Library需要为 Activity 声明android:exportedtrue、android:allowEmbeddedtrue、空 task affinity并通过setDisplayIntent()关联 PendingIntent。七、小结可穿戴通知开发核对清单将本指南要点整理为可复用的检查清单依赖与传递使用NotificationCompat.BuilderNotificationManagerCompat不要用 framework 的NotificationManager传递否则WearableExtender特性会失效通用显示setContentIntent()在可穿戴端对应左滑后的 Open actionaddAction()的 action 在手表端是左滑后的大按钮可穿戴专属 action使用WearableExtender.addAction()它会屏蔽 Builder 层添加的其他 action长文本用setStyle(BigTextStyle / InboxStyle)可穿戴端默认可见 big view背景与图标setBackground()位图按 400x400非滚动或 640x640视差滚动准备并放入drawable-nodpisetHintHideIcon(true)可隐藏应用图标语音回复RemoteInput.Builder(key)setLabel()setChoices()最多 5 条预设通过Action.Builder.addRemoteInput()挂载在手持端用RemoteInput.getResultsFromIntent()而非Intent.getExtras()取回文本多页面WearableExtender.addPage() / addPages()把附加页面放到主卡片右侧适合补充详情堆叠相同setGroup(key)使通知成一叠setSortKey()控制排序setGroupSummary(true)的概括式通知只出现在手持端并可用WearableExtender为整个 stack 设置背景与 action模拟器语音输入不可用改用 AVD 的 Hardware keyboard present 打字调试。按此清单实现的通知能在手机、平板与可穿戴设备上同时保持统一信息流与各自适合的交互形态这正是本模块赋予 Notification 可穿戴特性的核心价值所在。赞分享文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载相关推荐OpenSearch 1.3.4 版本发布解析依赖安全升级、ingest-attachment 文档抽取加固与客户端断连崩溃修复OpenSearch 1.3.4 版本发布解析依赖安全升级、ingest attachment 文档抽取加固与客户端断连崩溃修复 本篇技术文章围绕 OpenS文档教程移动开发ts-node 完整选项指南CLI 标志、tsconfig 配置与环境变量的权威参考ts node 完整选项指南CLI 标志、tsconfig 配置与环境变量的权威参考 ts node 是 Node.js 下的 TypeScript 执行与文档教程移动开发Android 可穿戴应用开发实战从 Notification 同步到数据层与表盘android-training-course-in-chineseAndroid 可穿戴应用开发实战从 Notification 同步到数据层与表盘android training course in chinese 本文档教程移动开发上一篇Namo Turn Detector v1 - Korean vs 传统方法为什么97.3%准确率足以颠覆韩语对话系统下一篇pass-js常见问题解决从证书错误到iPhone无法添加的调试技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表