Android Jetpack(四) 行为

media-compat 库

media-compat 库包含可帮助您构建音频和视频应用的类。这些类与运行 Android 2.3(API 级别 9)及更高版本的设备兼容。它们还可与其他 Android 功能配合使用,以打造舒适亲切的 Android 体验。

媒体会话和媒体控制器的建议实现方式是 MediaSessionCompatMediaControllerCompat 类,它们在 media-compat 支持库中定义。它们取代了 Android 5.0(API 级别 21)中引入的早期版本的 MediaSessionMediaController 类。compat 类提供相同的功能,但可让您更轻松地开发应用,因为您只需写入一个 API。该库通过将媒体会话方法转换为更低版本平台上的等效方法(可用时)来保证向后兼容性。

如果您已经有使用旧类的实际应用,我们建议更新到 compat 类

衡量性能

在 Android 8.0(API 级别 26)及更高版本中,getMetrics() 方法可用于某些媒体类。它会返回一个包含配置和性能信息的 PersistableBundle 对象(表示为属性和值的对应关系)。可以为这些媒体类定义 getMetrics() 方法:

4、通知 - 提供向后兼容的通知 API,支持 Wear 和 Auto


通知的设计由系统模板决定,您的应用只需定义模板各部分的内容。通知的某些详细信息仅在展开视图中显示。

image

图 7. 包含基本详情的通知

图 7 展示了通知最常见的部分,具体如下所示:

  1. 小图标:此为必要图标,通过 setSmallIcon() 设置。

  2. 应用名称:此由系统提供。

  3. 时间戳:此由系统提供,不过您可以通过 setWhen() 进行替换,或使用 setShowWhen(false) 将其隐藏。

  4. 大图标:此为可选图标(通常仅用于联系人照片;请勿将其用于应用图标),通过 setLargeIcon() 设置。

  5. 标题:此为可选内容,通过 setContentTitle() 设置。

  6. 文本:此为可选内容,通过 setContentText()设置。

版本差异

从 Android 7.0(API 级别 24)开始,您可以添加操作来回复消息,或者直接从通知中输入其他文本。

从 Android 10(API 级别 29)开始,平台可以自动生成操作按钮,此类按钮包含基于 Intent 的建议操作。

在 Android 8.0 及更高版本上,用户可以更改每个渠道的重要性

可能的重要性级别如下:

紧急:发出声音并以浮动通知的形式显示。

高:发出声音。

中:不发出声音。

低:不发出声音,也不在状态栏中显示。

以下是最明显的 Android 通知行为变化的摘要。

Android 4.1(API 级别 16)

引入了展开式通知模板(称为通知样式),可以提供较大的通知内容区域来显示信息。用户可以使用单指向上/向下滑动的手势来展开通知。

还支持以按钮形式向通知添加其他操作。

允许用户在设置中按应用关闭通知。

Android 4.4(API 级别 19 和 20)

向 API 中添加了通知侦听器服务

API 级别 20 中添加了对 Android Wear(现称为 Wear OS)的支持。

Android 5.0(API 级别 21)

引入了锁定屏幕和浮动通知。

用户现在可以将手机设置为“请勿打扰”模式,并配置当设备处于“仅限优先事项”模式时,哪些通知可以打扰他们。

向 API 集添加了通知是否在锁定屏幕上显示的方法 (setVisibility()),以及指定通知文本的“公开”版本的方法。

添加了 setPriority() 方法,告知系统该通知应具有的“干扰性”(例如,将其设置为“高”,可使该通知以浮动通知的形式显示)。

Android Wear(现称为 Wear OS)设备添加了通知堆栈支持。使用 setGroup() 将通知放入堆栈。请注意,平板电脑和手机尚不支持通知堆栈。通知堆栈以后会称为组或 Bundle。

Android 7.0(API 级别 24)

重新设计了通知模板的样式,以强调主打图像和头像。

添加了三个通知模板:一个用于消息应用,另外两个用于使用可扩展选项和其他系统装饰来装饰自定义内容视图。

向手持设备(手机和平板电脑)添加了对通知组的支持。使用与 Android 5.0(API 级别 21)中引入的 Android Wear(现称为 Wear OS)通知堆栈相同的 API。

用户可以使用内联回复直接在通知内回复(用户可以输入文本,然后将其发送给通知的父级应用)。

Android 8.0(API 级别 26)

现在必须将单个通知放入特定渠道中。

用户现在可以按渠道关闭通知,而不是关闭应用的所有通知。

包含活动通知的应用会在主屏幕/启动器屏幕上的应用图标上方显示通知“标志”。

现在,用户可以暂停抽屉式通知栏中的通知。您可以为通知设置自动超时。

您还可以设置通知的背景颜色。

与通知行为相关的部分 API 已从 Notification 移至 NotificationChannel。例如,对 Android 8.0 及更高版本使用 NotificationChannel.setImportance(),而不是 NotificationCompat.Builder.setPriority()。

创建通知

dependencies {

implementation “com.android.support:support-compat:28.0.0”

}

设置通知内容 ,

//CHANNEL_ID:渠道 ID

var builder = NotificationCompat.Builder(this, CHANNEL_ID)

//小图标

.setSmallIcon(R.drawable.notification_icon)

//标题

.setContentTitle(textTitle)

//正文

.setContentText(textContent)

//更长的可展开的通知

//创建包含可展开详情的通知(https://developer.android.google.cn/training/notify-user/expanded)。

.setStyle(NotificationCompat.BigTextStyle()

.bigText(“Much longer text that cannot fit one line…”))

//优先级

.setPriority(NotificationCompat.PRIORITY_DEFAULT)

创建渠道并设置重要性

private fun createNotificationChannel() {

// Create the NotificationChannel, but only on API 26+ because

// the NotificationChannel class is new and not in the support library

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

val name = getString(R.string.channel_name)

val descriptionText = getString(R.string.channel_description)

val importance = NotificationManager.IMPORTANCE_DEFAULT

val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {

description = descriptionText

}

// Register the channel with the system

val notificationManager: NotificationManager =

getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

notificationManager.createNotificationChannel(channel)

}

}

设置通知的点按操作

// Create an explicit intent for an Activity in your app

val intent = Intent(this, AlertDetails::class.java).apply {

flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK

}

val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)

.setSmallIcon(R.drawable.notification_icon)

.setContentTitle(“My notification”)

.setContentText(“Hello World!”)

.setPriority(NotificationCompat.PRIORITY_DEFAULT)

// Set the intent that will fire when the user taps the notification

.setContentIntent(pendingIntent)

.setAutoCancel(true)

请注意,该代码会调用 setAutoCancel(),它会在用户点按通知后自动移除通知

显示通知

要显示通知,请调用 NotificationManagerCompat.notify(),并将通知的唯一 ID 和 NotificationCompat.Builder.build()的结果传递给它。例如:

with(NotificationManagerCompat.from(this)) {

// notificationId is a unique int for each notification that you must define

notify(notificationId, builder.build())

}

添加操作按钮

要添加操作按钮,请将 PendingIntent 传递给 addAction() 方法。这就像是设置通知的默认点按操作,不同的是不会启动 Activity,而是可以完成各种其他任务

例如启动在后台执行作业的 BroadcastReceiver,这样该操作就不会干扰已经打开的应用。

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {

action = ACTION_SNOOZE

putExtra(EXTRA_NOTIFICATION_ID, 0)

}

val snoozePendingIntent: PendingIntent =

PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)

.setSmallIcon(R.drawable.notification_icon)

.setContentTitle(“My notification”)

.setContentText(“Hello World!”)

.setPriority(NotificationCompat.PRIORITY_DEFAULT)

.setContentIntent(pendingIntent)

.addAction(R.drawable.ic_snooze, getString(R.string.snooze),

snoozePendingIntent)

添加直接回复操作

Android 7.0(API 级别 24)中引入的直接回复操作允许用户直接在通知中输入文本,然后会直接提交给应用

1、创建 RemoteInput.Builder 的实例以便您添加到通知操作

// Key for the string that’s delivered in the action’s intent.

private val KEY_TEXT_REPLY = “key_text_reply”

var replyLabel: String = resources.getString(R.string.reply_label)

var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {

setLabel(replyLabel)

build()

}

2、为回复操作创建 PendingIntent

// Build a PendingIntent for the reply action to trigger.

var replyPendingIntent: PendingIntent =

PendingIntent.getBroadcast(applicationContext,

conversation.getConversationId(),

getMessageReplyIntent(conversation.getConversationId()),

PendingIntent.FLAG_UPDATE_CURRENT)

3、使用 addRemoteInput() 将 RemoteInput 对象附加到操作。

// Create the reply action and add the remote input.

var action: NotificationCompat.Action =

NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,

getString(R.string.label), replyPendingIntent)

.addRemoteInput(remoteInput)

.build()

4、对通知应用操作并发出通知。

// Build the notification and add the action.

val newMessageNotification = Notification.Builder(context, CHANNEL_ID)

.setSmallIcon(R.drawable.ic_message)

.setContentTitle(getString(R.string.title))

.setContentText(getString(R.string.content))

.addAction(action)

.build()

// Issue the notification.

with(NotificationManagerCompat.from(this)) {

notificationManager.notify(notificationId, newMessageNotification)

}

要从通知回复界面接收用户输入,请调用 RemoteInput.getResultsFromIntent() 并将 BroadcastReceiver 收到的 Intent 传递给它:

private fun getMessageText(intent: Intent): CharSequence? {

return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)

}

处理完文本后,必须使用相同的 ID 和标记(如果使用)调用 NotificationManagerCompat.notify() 来更新通知。若要隐藏直接回复界面并向用户确认他们的回复已收到并得到正确处理,则必须完成该操作。

// Build a new notification, which informs the user that the system

// handled their interaction with the previous notification.

val repliedNotification = Notification.Builder(context, CHANNEL_ID)

.setSmallIcon(R.drawable.ic_message)

.setContentText(getString(R.string.replied))

.build()

// Issue the new notification.

NotificationManagerCompat.from(this).apply {

notificationManager.notify(notificationId, repliedNotification)

}

在处理这个新通知时,请使用传递给接收者的 onReceive() 方法的上下文。

您还应通过调用 setRemoteInputHistory() 将回复附加到通知底部。但如果要构建消息应用,应创建消息式通知,并在会话中附加新消息。

有关来自消息应用的通知的更多建议,请参阅消息应用的最佳做法

添加进度条

image.png

通过调用 setProgress(max, progress, false) 使用指示器。

第一个参数是“完成”值(如 100);第二个参数是当前完成的进度,最后一个参数表明这是一个确定性进度条。

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {

setContentTitle(“Picture Download”)

setContentText(“Download in progress”)

setSmallIcon(R.drawable.ic_notification)

setPriority(NotificationCompat.PRIORITY_LOW

}

val PROGRESS_MAX = 100

val PROGRESS_CURRENT = 0

NotificationManagerCompat.from(this).apply {

// Issue the initial notification with zero progress

builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)

notify(notificationId, builder.build())

// Do the job here that tracks the progress.

// Usually, this should be in a

// worker thread

// To show progress, update PROGRESS_CURRENT and update the notification with:

// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);

// notificationManager.notify(notificationId, builder.build());

// When done, update the notification one more time to remove the progress bar

builder.setContentText(“Download complete”)

.setProgress(0, 0, false)

notify(notificationId, builder.build())

}

操作结束时,progress 应等于 max。您可以在操作完成后仍保留显示进度条,也可以将其移除。要移除进度条,请调用 setProgress(0, 0, false)

要显示不确定性进度条(不指示完成百分比的进度条),请调用 setProgress(0, 0, true)

结果会产生一个与上述进度条样式相同的指示器,区别是这个进度条是一个持续动画,不指示完成情况。

在您调用 setProgress(0, 0, false) 之前,进度动画会一直运行,调用后系统会更新通知以移除 Activity 指示器。

设置系统范围的类别

如果您的通知属于 NotificationCompat 中定义的预定义通知类别之一

(例如 CATEGORY_ALARM、CATEGORY_REMINDER、CATEGORY_EVENT 或 CATEGORY_CALL),

您应通过将相应类别传递到 setCategory() 来进行声明。

var builder = NotificationCompat.Builder(this, CHANNEL_ID)

.setSmallIcon(R.drawable.notification_icon)

.setContentTitle(“My notification”)

.setContentText(“Hello World!”)

.setPriority(NotificationCompat.PRIORITY_DEFAULT)

.setCategory(NotificationCompat.CATEGORY_MESSAGE)

显示紧急消息

注意:如果应用的目标平台是 Android 10(API 级别 29)或更高版本,必须在应用清单文件中请求 USE_FULL_SCREEN_INTENT 权限,以便系统启动与时效性通知关联的全屏 Activity。

以下代码段展示了如何将通知与全屏 Intent 关联:

val fullScreenIntent = Intent(this, ImportantActivity::class.java)

val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,

fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)

.setSmallIcon(R.drawable.notification_icon)

.setContentTitle(“My notification”)

.setContentText(“Hello World!”)

.setPriority(NotificationCompat.PRIORITY_DEFAULT)

.setFullScreenIntent(fullScreenPendingIntent, true)

设置锁定屏幕公开范围

要控制锁定屏幕中通知的可见详情级别,请调用 setVisibility() 并指定以下值之一:

更新通知

要在发出此通知后对其进行更新,请再次调用 NotificationManagerCompat.notify(),并将之前使用的具有同一 ID 的通知传递给该方法。如果之前的通知已被关闭,则系统会创建一个新通知。

您可以选择性调用 setOnlyAlertOnce(),这样通知只会在通知首次出现时打断用户(通过声音、振动或视觉提示),而之后更新则不会再打断用户。

有关消息应用的最佳做法

从 Android 7.0(API 级别 24)起,Android 提供了专用于消息内容的通知样式模板。使用 NotificationCompat.MessagingStyle 类,您可以更改在通知中显示的多个标签,包括会话标题、其他消息和通知的内容视图。

以下代码段展示了如何使用 MessagingStyle 类自定义通知的样式。

var notification = NotificationCompat.Builder(this, CHANNEL_ID)

.setStyle(NotificationCompat.MessagingStyle(“Me”)

.setConversationTitle(“Team lunch”)

.addMessage(“Hi”, timestamp1, null) // Pass in null for user.

.addMessage(“What’s up?”, timestamp2, “Coworker”)

.addMessage(“Not much”, timestamp3, null)

.addMessage(“How about lunch?”, timestamp4, “Coworker”))

.build()

从 Android 8.0(API 级别 26)起,使用 NotificationCompat.MessagingStyle 类的通知会在采用折叠形式时显示更多内容

5、权限 - 用于检查和请求应用权限的兼容性 API


6、偏好设置 - 创建交互式设置屏幕


**注意:**本指南介绍如何使用 AndroidX Preference Library。自 Android 10 开始,系统已弃用 android.preference 库平台。

创建层次结构

<PreferenceScreen

xmlns:app=“http://schemas.android.com/apk/res-auto”>

<SwitchPreferenceCompat

app:key=“notifications”

app:title=“Enable message notifications”/>

<Preference

app:key=“feedback”

app:title=“Send feedback”

app:summary=“Report technical issues or suggest new features”/>

扩充层次结构

class MySettingsFragment : PreferenceFragmentCompat() {

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {

setPreferencesFromResource(R.xml.preferences, rootKey)

}

}

然后,与您对其他 Fragment 进行的操作一样,您可以将此 Fragment 添加到您的 Activity:

class MySettingsActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

supportFragmentManager

.beginTransaction()

.replace(R.id.settings_container, MySettingsFragment())

.commit()

}

}

7、共享 - 提供适合应用操作栏的共享操作


Android 应用的一大优点是它们能够互相通信和集成。如果某一功能并非应用的核心,而且已存在于另一个应用中,为何要重新开发它?

本节说明如何借助 Intent对象使用 Android Sharesheet 和 Intent Resolver 在不同应用之间发送和接收简单数据(如文本、图像和文件)的一些常用方法。

1、将简单的数据发送给其他应用

Android 为用户提供了两种在应用之间分享数据的方式:

  • Android Sharesheet 主要用于将内容发送到应用外部和/或直接发送给其他用户。例如,将网址分享给朋友。

  • Android intent 解析器最适合将数据传递到明确定义的任务的下一个阶段。例如,从应用中打开 PDF,并让用户挑选他们首选的查看器。

发送文本内容

val sendIntent: Intent = Intent().apply {

action = Intent.ACTION_SEND

putExtra(Intent.EXTRA_TEXT, “This is my text to send.”)

type = “text/plain”

}

val shareIntent = Intent.createChooser(sendIntent, null)

startActivity(shareIntent)

发送二进制内容

val shareIntent: Intent = Intent().apply {

action = Intent.ACTION_SEND

putExtra(Intent.EXTRA_STREAM, uriToImage)

type = “image/jpeg”

}

startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记。

  • 330页PDF Android学习核心笔记(内含上面8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT部分大厂面试题(有解析)

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

tent)

发送二进制内容

val shareIntent: Intent = Intent().apply {

action = Intent.ACTION_SEND

putExtra(Intent.EXTRA_STREAM, uriToImage)

type = “image/jpeg”

}

startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记。

  • 330页PDF Android学习核心笔记(内含上面8大板块)

[外链图片转存中…(img-O5pm3mIe-1714282094298)]

[外链图片转存中…(img-wnTrIIvB-1714282094299)]

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

[外链图片转存中…(img-ORJfa4Ef-1714282094299)]

  • Android BAT部分大厂面试题(有解析)

[外链图片转存中…(img-GuSRRSzf-1714282094300)]

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值