Android 14 彻底终结大厂流氓应用?

hi 大家好,我是 DHL。大厂程序员,就职于美团、快手、小米。公众号:ByteCode,分享技术干货和编程知识点

在某些大厂内部通常都会有一个神秘的团队,他们的工作内容就是专门研究系统,而的事情就是如何让自家应用在后台存活的更久,达到永生的目的。

其中有个别公司,甚者利用公开漏洞,达到远程操控用户手机的目的,做更多他们想做的事,可以随意获取用户的隐私,而且一旦安装,普通用户很难删除,之前写了一些揭露他们的文章,但是现在已经被全部删除了,就连评论区抨击他们的内容也全都被删除了。

而 Android 14 的出现,可以说是暂时性的彻底终结了这些流氓软件,想在后台通过保活的方式,让应用在后台达到永生的目的基本不可能了。

为什么这是暂时性的呢,因为没有完美的系统,新的系统虽然修复了公开漏洞,终结了现有的保活的方式,但是新系统可能存在新的漏洞,还是会给某些大厂可乘之机。

我们一起来看一下 Android 工程副总裁 Dave Burke 都介绍 Andorid 14 在性能、隐私、安全性方面做了那些改进,这篇文章是对之前的文章 适配 Android 14,你的应用受影响了吗Android 14 新增权限 的补充。

  • 冻结缓存应用,增强杀进程能力
  • 应用启动更快
  • 减少内存占用
  • 屏幕截图检查
  • 显示全屏系统通知
  • 精确闹钟权限
  • 提供了对照片和视频的部分访问权限
  • 最小 targetSdkVersion 限制
  • 返回手势

本文只会介绍我认为 Android 14 上最大的变化,关于 Android 14 的所有变更,可以前往查看变更developer.android.com/about/versi...

冻结缓存应用,增强杀进程能力

在 Android 11 以上支持冻结已缓存的应用,当应用切换到后台并且没有其他活动时,系统会在一定时间内通过状态判断,是否冻结该应用,如果一个应用被冻结住了,将完全被 "暂停",不再消耗任何 CPU 资源,可以减少应用在后台消耗的 CPU 资源,从而达到节电的目的。

被冻结已缓存的应用并不会执行终止该应用,冻结的作用只是暂时挂起进程,消耗 CPU 的资源为 0,它有助于提高系统性能和稳定性,同时最大限度地节省设备的资源和电量的消耗,一旦应用再次切换到前台时,系统会将该应用的进程解冻,实现快速启动。

如果你的手机支持冻结已缓存的应用,在开发者选项里会显示 「暂停执行已缓存的应用」设置项。

冻结已缓存应用,在内核层面使用的是 cgroup v2 freezer,相对于使用信号 SIGSTOP 与 SIGCONT 实现的挂起与恢复,cgroup v2 freezer 无法被拦截,也就无法被开发者 Hook,从而彻底终结大厂想在这个基础上做一些事情。

当然 Google 也对 cgroup 进行了封装,提供了 Java API,在上层我们也可以调用对应的方法实现 CPU、内存资源的控制。

kotlin 复制代码
public static final native void setProcessFrozen(int pid, int uid, boolean frozen);
public static final native void enableFreezer(boolean enable);

经过测试 Android 14 相比于 Android 13,缓存进程的 CPU 使用量降低了高达 50%,因此,除了传统的 Android 应用生命周期 API,如前台服务、JobScheduler 或 WorkManager,后台工作将受到限制。

另外在 Android 14 上系统在杀进程之前,首先会将应用所有的进程进行 cgroup v2 freezer,被冻结的应用 cpu 资源占用为 0,然后在挨个杀掉进程,想通过进程互相拉取进程的方式,不断的想通过 fork 出子进程,达到应用永生的目的,在 Android 14 以上已经不可能了,这些黑科技都要告别历史的舞台了。

应用启动更快

在 Android 14 上对缓存应用进行优化,增加了缓存应用的最大数量的限制,从而减少了冷启动应用的次数。

而应用的最大缓存数量不是固定的,可以根据设备的内存容量进行调整,Android 测试团队在 8GB 设备上,发现冷启动应用的数量减少了 20%,而在 12GB 设备上减少了超过 30%,冷启动相对于热启动来说速度较慢,而且在电量消耗方面成本较高,这一工作有效地改善了电量使用和整体应用启动时间。

减少内存占用

代码大小是我们关注的关键指标之一,代码量越大虚拟内存占用越高,减少生成的代码大小,对内存(包括 RAM 和存储空间)的影响就越小。

在 Android 14 中,改进 Android 运行时(ART)对 Android 用户体验,ART 包含了优化措施,将代码大小平均减少了 9.3%,而不会影响性能。

屏幕截图检查

在 Android 14 中新增了一个特殊的 API,截取屏幕截图后会有个 ScreenCaptureCallback 的回调,当用户正在使用截取屏幕截图时,将会调用这些回调函数。

要使 API 正常工作,需要在 AndroidManifest 中添加 DETECT_SCREEN_CAPTURE 权限,然后在 onStart() 方法中注册回调,需要在 onStop() 中取消注册。

kotlin 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
</manifest>


class MainActivity : Activity() {

    private val mainExecutor = MainEcxector()
    
    private val screenshotCallback = ScreenCaptureCallback {
        // A screenshot was taken
    }

    override fun onStart() {
        super.onStart()
        registerScreenCaptureCallback(mainExecutor, screenshotCallback)
    }

    override fun onStop() {
        super.onStop()
        unregisterScreenCaptureCallback(screenshotCallback)
    }
}

显示全屏系统通知

Android 11 引入了全屏通知,当全屏应用程序运行时,这些通知将在锁屏屏幕上显示,任何应用都可以在手机处于锁定状态时使用 Notification. Builder. setFullScreenIntent 发送全屏 Intent,不过需要在 AndroidManifest 中声明 USE_FULL_SCREEN_INTENT 权限,在应用安装时自动授予此权限。

从 Android 14 开始,使用此权限的应用仅限于提供通话和闹钟的应用。对于不适合此情况的任何应用,Google Play 商店会撤消其默认的 USE_FULL_SCREEN_INTENT 权限。

在用户更新到 Android 14 之前,在手机上已经安装的应用仍拥有此权限,但是用户可以开启和关闭此权限,所以您可以使用新 API NotificationManager.canUseFullScreenIntent 检查应用是否具有该权限。

如果想在 Android 14 上使用这个权限,我们可以提示用户手动打开授权,通过 Intent(ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT) 来跳转到设置界面。

kotlin 复制代码
if(NotificationManager.canUseFullScreenIntent()){
    startActivity(Intent(ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT))
}

精确闹钟权限

在 Andorid 12 之前我们可以直接调用 setAlarmClock()setExact() setExactAndAllowWhileIdle() 等等方法设置精确闹钟时间,

但是在 Android 12 上 Google 引入了一个新的权限 SCHEDULE_EXACT_ALARM,如果想调用 setAlarmClock()setExact() setExactAndAllowWhileIdle() 等等方法设置精确闹钟时间, 需要在 manifest 中申明 android.permission.SCHEDULE_EXACT_ALARM 权限。

所以运行在 Android 12 ~ Android 13 系统上,我们只需要声明一下权限就可以使用了,但是从 Android 14 开始 SCHEDULE_EXACT_ALARM 权限默认被禁止使用了。

如果你还想在 Andorid 14 以上使用精准闹钟的 API,我们可以提示用户手动打开授权,通过 Intent (ACTION_REQUEST_SCHEDULE_EXACT_ALARM) 来跳转到设置界面,代码如下。

kotlin 复制代码
val alarmManager: AlarmManager = context.getSystemService<AlarmManager>()!!
when {
   // If permission is granted, proceed with scheduling exact alarms.
   alarmManager.canScheduleExactAlarms() -> {
       alarmManager.setExact(...)
   }
   else -> {
       // Ask users to go to exact alarm page in system settings.
       startActivity(Intent(ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
   }
}

提供了对照片和视频的部分访问权限

这个限制和 iOS 相似,Android 14 提供了对照片和视频的部分访问权限。当您访问媒体数据时,用户将看到一个对话框,提示用户授予对所有媒体的访问、或者授予单个照片/视频的访问权限,该新功能将适用于 Android 14 上所有应用程序,无论其 targetSdkVersion 是多少。

在 Android 13 上已经引入了单独的照片访问和视频访问权限,但是在 Android 14 上新增了新的权限 READ_MEDIA_VISUAL_USER_SELECTED

xml 复制代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />

    <!-- Devices running Android 13 (API level 33) or higher -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

    <!-- To handle the reselection within the app on Android 14 -->
    <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />

</manifest>

如果没有声明新的权限,当应用程序进入后台或用户终止应用程序时,单独的照片访问和视频访问权限将立即撤销,不会保存 READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 权限的状态,每次都需要检查。

最小 targetSdkVersion 限制

Android 14 当中有一个比较大的变化就是,无法安装 targetSdk <= 23 的应用程序 (Android 6.0),不要将它与 minSdk 混淆。

在 Android 开发中有两个比较重要的版本号:

  • compileSdkVersion :用于编译当前项目的 Android 系统版本
  • targetSdkVersion :App 已经适配好的系统版本,系统会根据这个版本号,来决定是否可以使用新的特性

这个最小 targetSdkVersion 限制,主要是出于安全考虑,在 Android 6.0 中引入了运行时权限机制,App 想要使用一些敏感权限时,必须先弹窗询问用户,用户点击允许之后才能使用相应的权限。

但是一些 App 为了利用权限方便获取到用户的信息,通过不去升级 targetSdk 的版本号的方式,在安装过程中获得所有权限,以最低成本的方式,绕过运行时权限机制。

如果之前已经安装了的 App,就算升级到 Android 14 也会去保留,系统不能代表用户去删除某个应用,其实我在想,为什么不针对这些已经安装好的低版本的 App,Google 给出一些警告提示,让用户可以感知到呢

返回手势

在 Android 13 的时候,Google 已经预示我们在下一个版本中,返回手势将会有一些更新,并以预览屏幕的形式呈现动画,效果如下图所示。

我们来演示一下使用后退导航的动画。

在 Android 14 增加了在 App 中创建过渡动画的功能,比如在 OnBackPressedCallback 接口中添加了一个方法 handleonbackprogress() ,这个方法在返回手势执行过程中被调用,我们可以在这个方法中增加一些过渡动画。

OnBackPressedCallback 接口中还提供了两个方法 handleOnBackPressed()handleOnBackCancelled() 分别在动画完成和取消动画时调用,我们来看看在代码中如何使用。

kotlin 复制代码
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        val box = findViewById<View>(R.id.box)
        val screenWidth = 
            Resources.getSystem().displayMetrics.widthPixels
        val maxXShift = (screenWidth / 20)

        val callback = object : OnBackPressedCallback(
            enabled = true
        ) {

            override fun handleOnBackProgressed(
                backEvent: BackEvent
            ) {
                when (backEvent.swipeEdge) {
                    BackEvent.EDGE_LEFT ->
                        box.translationX = backEvent.progress *     
                            maxXShift
                    BackEvent.EDGE_RIGHT ->
                        box.translationX = -(backEvent.progress * 
                            maxXShift)
                }
                box.scaleX = 1F - (0.1F * backEvent.progress)
                box.scaleY = 1F - (0.1F * backEvent.progress)
            }

            override fun handleOnBackPressed() {
                // Back Gesture competed
            }

            
            override fun handleOnBackCancelled() {
                // Back Gesture cancelled 
                // Reset animation objects to initial state
            }
        }
        this.onBackPressedDispatcher.addCallback(callback)
    }
}

API 被废弃

在 Android 中使用 overidePendingTransition () 方法实现进入和退出动画,但是在 Android 14 上提供了新的 overrideActivityTransition () 方法,而 overidePendingTransition () 方法已被标记为弃用。

kotlin 复制代码
// New API
overrideActivityTransition(
    enterAnim = R.anim.open_trans,
    exitAnim = R.anim.exit_trans,
    backgroundColor = R.color.bgr_color
)

// deprecated
overridePendingTransition(R.anim.open_trans, R.anim.exit_trans)

全文到这里就结束了,感谢你的阅读,坚持原创不易,欢迎在看、点赞、分享给身边的小伙伴,我会持续分享原创干货!!!


我开了一个云同步编译工具(SyncKit),主要用于本地写代码,同步到远程设备,在远程设备上进行编译,最后将编译的结果同步到本地,代码已经上传到 Github,欢迎前往仓库 hi-dhl/SyncKit 查看。


Hi 大家好,我是 DHL,就职于美团、快手、小米。公众号:ByteCode ,分享有用、有趣的硬核原创内容,Kotlin、Jetpack、性能优化、系统源码、算法及数据结构、动画、大厂面经,真诚推荐你关注我。


最新文章

开源新项目

  • 云同步编译工具(SyncKit),本地写代码,远程编译,欢迎前去查看 SyncKit

  • KtKit 小巧而实用,用 Kotlin 语言编写的工具库,欢迎前去查看 KtKit

  • 最全、最新的 AndroidX Jetpack 相关组件的实战项目以及相关组件原理分析文章,正在逐渐增加 Jetpack 新成员,仓库持续更新,欢迎前去查看 AndroidX-Jetpack-Practice

  • LeetCode / 剑指 offer,包含多种解题思路、时间复杂度、空间复杂度分析,在线阅读

相关推荐
太空漫步112 小时前
android社畜模拟器
android
海绵宝宝_5 小时前
【HarmonyOS NEXT】获取正式应用签名证书的签名信息
android·前端·华为·harmonyos·鸿蒙·鸿蒙应用开发
凯文的内存6 小时前
android 定制mtp连接外设的设备名称
android·media·mtp·mtpserver
天若子7 小时前
Android今日头条的屏幕适配方案
android
林的快手8 小时前
伪类选择器
android·前端·css·chrome·ajax·html·json
望佑8 小时前
Tmp detached view should be removed from RecyclerView before it can be recycled
android
无限大69 小时前
算法精讲--动态规划四步法则
java·算法·程序员
xvch11 小时前
Kotlin 2.1.0 入门教程(二十四)泛型、泛型约束、绝对非空类型、下划线运算符
android·kotlin
人民的石头14 小时前
Android系统开发 给system/app传包报错
android
yujunlong391915 小时前
android,flutter 混合开发,通信,传参
android·flutter·混合开发·enginegroup