当前位置:   article > 正文

深度解读 Android 14 重要的 8 个新特性~_安卓14

安卓14

一年一度的 Android 升级永不缺席,今年的代号叫 Upside Down Cake,倒置蛋糕,简称 U,对外版本为 Android 14

一般来说,升级任务分为 ROM 角度和 App 角度,前者比较关心系统内部实现的变化,后者则更加关心对外的 New FeaturesBehavior Changes。本文主要聚焦在 App 角度,即作为 3rd Party App 如何去看待 14 系统升级。由于升级内容过于庞杂,本次先介绍 New Features 部分,原因是作为 New Features、很容易被大家忽略,实则更重要。

理由是 New Features 不像 Behavior Changes:OS 升级之后如果运行上出了问题,调查下文档就知道 14 变更了什么、如何改。而 New Features 作为新的功能、API,并不会影响 App 原来的逻辑,但实实在在地解决了痛点、优化了体验、提供了一个又一个特色能力,从长远来讲是更有价值的

如果开发者总是忽略 New Features 部分,那么 App 难免停留在旧的实现上、旧的方案上,OSV 工作也变成了改一改、能跑就行的被动升级。建议大家在关注 Behavior Changes 以外多留意下 New Features 是否可以改善现有的方案,优化产品体验。

14 推出的新 API,大部分我都试过,并开源了 DEMO。本文将从设计的理由、使用解读等角度,带大家切实感受这重要的 8 个新特性:

  1. ScreenShot Detection,截屏感知
  2. TextView Highlight,文本高亮
  3. New System Back Design,全新的系统返回设计
  4. Custom Action on Share Sheet,支持自定义操作的系统分享
  5. Locale Preferences,区域偏好
  6. Grammar Gender,语法性别
  7. Path Iterator,路径迭代器
  8. Package Installer improvement,安装改善

1.ScreenShot Detection

部分 App 常常需要监听用户的截屏操作,进行发送反馈的提醒等,往常是使用哪些手段来实现呢?

一般来说,开发者会通过监听存放截屏文件的媒体目录的变化来迂回实现,这往往需要 Runtime 级别的读写权限,而且稍有不慎还可能牵扯到隐私问题。

那么 Android 14 为了规范这种开发需求,推出了专用 API,即 ScreenShotCallback。它无需 Runtime 级别的读写权限,申明专用权限即可,在 App 安装的时候即被授予:

xml
复制代码
 <uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
  • 1
  • 2
  • 3

使用的方式来说,以 Activity 为单位进行注册和注销截屏 ScreenCaptureCallback。并且建议在 onStart() 里注册、onStop() 里注销。

kotlin
复制代码
 class ScreenShotActivity : AppCompatActivity() {
      private val screenCaptureCallback = ScreenCaptureCallback {
          // 提醒用户等操作
          AlertDialog.Builder(this).show()
      }
 ​
      override fun onStart() {
          super.onStart()
          registerScreenCaptureCallback(mainExecutor, screenCaptureCallback)
      }
 ​
      override fun onStop() {
          super.onStop()
          unregisterScreenCaptureCallback(screenCaptureCallback)
      }         
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

如下的截图可以看到,利用该 API 成功地监听到了截屏操作,并执行了预期的 Dialog 提醒。

需要注意的是,该 API 只能监听电源键方式发起的截屏时机,无法监听到 adb、代码等方式发起的截屏,毕竟它不算是用户的操作。而且不会将截图带过来,App 如果需要图片数据的话,仍需要去读取。

相关文章推荐:Android 14 新 API:直接监听截屏操作,不用再观察媒体文件了~

2.TextView Highlight

HighLights API

对于做 Mail、SMS、Note 类的 App 难免遇到设置文本 Highlight 的需求,而传统的实现办法无非是 Spannable。但这种方式的代码稍显复杂、而且无法方便地更新高亮。

那么 14 里针对这个痛点提供了专门的 API 即 HighLights,提供了更加简单、灵活的实现。

首先,支持静态设置高亮:

1. 通过 Highlights.Builder 构建 HighLights 对象

2. 通过 addRange() 设置 Paint 和对应 Range 数组即可

3. 通过 TextView 新方法 setHighLights() 反映高亮

其次,支持动态设置高亮:

  1. 调用新方法 getHighLights() 获取已有 HighLights 实例
  2. 更改其 Paint Range 属性
  3. 调用 invalidate 动态更新高亮

通过如下的代码进行黄色和绿色的静态高亮设置,以及点击 Button 之后动态更新绿色高亮为深蓝色高亮:

kotlin
复制代码
  class MainActivity : AppCompatActivity() {
      ...
      override fun onCreate(savedInstanceState: Bundle?) {
          ...
          val greenPaint = Paint().apply {
              color = Color.GREEN
          }
 ​
          with(binding.textview1) {
              text = TEXT
              val builder = Highlights.Builder()
                  .addRange(yellowPaint, 0, 3)
                  .addRange(greenPaint, 14, 24)
                  .addRange(greenPaint, 25, 32)
              highlights = builder.build()
          }
 ​
          binding.changeHighlights.setOnClickListener {
              Log.d("HighLights", "changeHighlights tapped & change highlights")
              textView1Highlights?.apply {
                  // Change color
                  getPaint(1).color = Color.BLUE
                  // Change ranges
                  getRanges(1)[0] -= 3
                  getRanges(1)[1] += 1
  
                  for (i in 0 until size) {
                      Log.d("HighLights", "textView1Highlights'" +
                              " paint:${getPaint(i).color.toColorString()}")
                      val range = getRanges(i)
                      for (j in range.indices) {
                          Log.d("HighLights", "ranges:${range[j]}")
                      }
                  }
              }
  
              binding.textview1.invalidate()
          }
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

下图可以看到,通过 HighLights API 成功地设置了黄色和绿色的高亮。并且在点击 CHANGE button 之后,动态更改了上面 TextView HighLights 的颜色为蓝色。

可能有人会问这个 HighLights API 能自适应多语言吗?

答案是 NO,事实上 HighLights API 和多语言无关,不同语言下要自行处理目标高亮的 range。

相关文章推荐:Android 14 新功能之 HighLights:快速实现文本高亮~

Search Highlight

除了一般的高亮以外,Android 14 还推出了针对搜索的高亮 API,主要是使用如下 TextView 的相关新方法:

  1. searchResultHighlightColor 设置搜索匹配到的高亮

  2. focusedSearchResultHighlightColor 设置聚焦到的高亮

  3. setSearchResultHighlights 设置搜索到的文字 range

  4. focusedSearchResultIndex 针对搜索焦点高亮和移动,index 常量:

    • -1:没有开始搜索/搜索不到结果
    • 0:匹配到搜索结果
    • 1:聚焦到某个搜索结果

如下代码设置匹配到搜索关键字的高亮为水蓝色,聚焦到该匹配的高亮是灰色,并用 search button 模拟匹配到的文字 range、forward button 模拟搜索焦点的移动。

kotlin
复制代码
  class TextViewActivity : AppCompatActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
          ...
          with(binding.textview2) {
              searchResultHighlightColor = Color.CYAN
              focusedSearchResultHighlightColor = Color.GRAY
          }
 ​
          // 模拟搜索按钮
          binding.startSearch.setOnClickListener {
              binding.textview2.run {
                  Log.d("HighLights", "startSearch tapped" +
                          " and current search Color:${searchResultHighlightColor.toColorString()}"
                  )
                  // set searching ranges
                  setSearchResultHighlights(4, 11, 25, 32)
              }
          }
 ​
          binding.changeSearchIndex.setOnClickListener {
              binding.textview2.run {
                  // Set index to first or second
                  val newSearchIndex = when (focusedSearchResultIndex) {
                      TextView.FOCUSED_SEARCH_RESULT_INDEX_NONE, 1 -> 0
                      0 -> 1
                      else -> TextView.FOCUSED_SEARCH_RESULT_INDEX_NONE
                  }
  
                  binding.textview2.focusedSearchResultIndex = newSearchIndex
              }
          }
      }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

如下的 GIF 可以看到,匹配到搜索的时候,文本颜色变成了水蓝色,当聚焦到该匹配之后变成灰色,默认情况下这是无高亮。

相关文章推荐:Android 14 新功能之 TextView 搜索结果高亮和焦点移动~

3.New System Back Design

随着屏幕越来越大,交互方式的愈加多元、灵活,传统的 Back 按键、虚拟键显得越来越冗余。那么如何简化返回操作、统一返回的开发就显得尤为重要。

New Back Arrow

事实上,自 Android 13 开始即针对 Back 事件的处理进行了统一,想要使用该新特性的好,首先需要做两个设置:

  1. Manifest 中开启 enableOnBackInvokedCallback
  2. 注册实现 Back 逻辑的 OnBackInvokedCallback 到 Activity 中

Android 14 针对系统的 Back 效果进行了进一步的升级,第一块则是优化 arrow,包括:

  1. 增加了 Arrow 边框、背景,更加明显
  2. 自适应系统 Material Design 主题,theme 改变的同时 Arrow 的背景色跟着刷新:

如下的对比,可以看到 14 的系统返回 Arrow 相对 13 更加协调、清晰。

Screenshot 2023-06-28 at 23.43.15.png

Predictive Back Preview

第二块就是添加返回预览,让用户可以提前查看目标界面,决定取消或继续返回操作。而这块功能尚在完善当中,需要体验首先得在开发者选项中手动开启。

  • 设置 > 系统 > 开发者选项 > 预测性返回手势动画(Predictive back animation)

如下 GIF 即可以看到 Back 手势触发后,App 整体缩小、背面画面展示的预览效果。

相关文章推荐:Android 14 之返回界面升级:预览目标界面 + 全新返回箭头

4.Custom Action on Share Sheet

如今 App 生态越来越丰富,数据分享也变得极为需要。一般来说,分享界面的呈现由 App 的适配以及系统的调度有关。可是很多更加细节、具体的操作,系统或 App 可能无法及时 cover,这时候支持自定义的分享操作就显得十分必要。

Android 14 里新增了 ChooserAction 类,当用 Android ShareSheet 创建标准的分享界面时,可以用该 Class展示的自定义操作和信息,来提供更丰富的分享菜单:

  1. 使用 ChooserAction.Builder 创建自定义 ChooserAction

    • 指定 Icon
    • 指定 title
    • 指定分享菜单点击后目标的 PendingIntent 类型的 Action
  2. 使用 Intent#createChooser() 创建标准的 Chooser Intent

  3. 放置 ChooserAction 实例到 key 为 EXTRA_CHOOSER_CUSTOM_ACTIONS 的 Bundle 中

    • 注意,此处的入参是 ChooserAction 数组,因为可以一次支持多个自定义操作

如下的代码展示了设置自定义分享的标准写法:

kotlin
复制代码
 class ShareSheetActivity : AppCompatActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
         ...
         val pendingIntent: PendingIntent =PendingIntent.getActivity(
             this@ShareSheetActivity,
             0,
             Intent(Intent.ACTION_WEB_SEARCH).apply {
                 putExtra(SearchManager.QUERY, "Search on web 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/856356
推荐阅读
相关标签