Android14 适配之——现有 App 安装到 Android14 手机上需要注意些什么?

好久不见~ 最近几个月变化挺大的,不论是自己的家庭还是社会环境,把我们能做的做好,慢慢适应新的变化,这也是一种不可或缺的能力吧!

Android14 即将正式发布,作为开发者需要注意哪些内容?长话短说,一起来看看吧~

主要分为两部分:
一是影响所有的 Android 应用,这些改动会影响所有的 App,只要你的 App 安装在了 Android14 的设备上,都会受到这些影响;
二是当 targetSdkVersion 升级到 34 后,我们的 App 所受到的影响。这一篇先来说说第一部分的内容,即现有 App 安装到 Android14 手机上,会有哪些影响

1. SCHEDULE_EXACT_ALARM 权限默认关闭

这个权限的全称是 android.permission.SCHEDULE_EXACT_ALARM,用于是否开启设置精确闹钟的权限。精确的闹钟适用于用户指定时间的通知,或是在确切的时间需要执行的操作。

如果 App 的 targetSdkVersion 设置的是 33(Android13)或更高,在 Android14 的设备上运行时,这个权限就是默认关闭的。所以,当 App 中有用到精确闹钟,需要在确切的时间点去做操作,那么就需要在 Manifest 文件中显式地申请这个权限并需要在使用时动态向用户获取该权限。

具体地说就是,当使用 AlarmManager 中的
setExact(int type, long triggerAtMillis, PendingIntent operation)
setExactAndAllowWhileIdle(int type, long triggerAtMillis, PendingIntent operation)
setAlarmClock(AlarmManager.AlarmClockInfo info, PendingIntent operation)
这三个函数时,如果 targetSdkVersion >= 33,且在 Android14 设备上没有显式申请该权限,则会抛出一个 SecurityException 异常。

特殊情况:
1)如果用户通过“备份与恢复”功能将 App 传输到一个 Android14 的设备上,则此 App 的该权限默认仍是关闭的;
2)如果一个 App 已经开启了该权限,当设备升级到 Android14 后,此 App 的该权限是开启的状态;
3)当精确闹钟是通过 OnAlarmListener 设置的,则无需申请该权限。例如:setExact(int type, long triggerAtMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler) 这个方法就无需申请。

用的比较多的 API:
1)boolean canScheduleExactAlarms() 判断是否可以设置精确闹钟(API >= 31 才有此判断方法);
2)AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED 广播消息常用来监听用户开启或关闭该权限的回调(API >= 31 才有此广播消息类型)。

不建议的使用场景:
1)如果 App 在生命周期内安排重复性的操作,可以使用 Handler 中的 postAtTime 等来替代。相反,如果是要设置 30min 后或者明天下午 2 点的操作,则建议使用;
2)安排在后台进行的一些操作,例如:下载更新App或者上传日志等。建议使用 WorkManager 而不是精确闹钟;
3)当系统处于空闲时,在大概的时间点处理事务,则可以调用非精确闹钟的一些 API 处理,例如使用 setAndAllowWhileIdle() 而不是 setExactAndAllowWhileIdle() 方法;
4)用户指定的在大概特定时间点发生的,或者在一个时间窗口内发生的事务;

适配流程:
1)调用 alarmManager.canScheduleExactAlarms() 检查是否有该权限;
2)如果没有权限,则需要通过 Intent,设置 ActionACTION_REQUEST_SCHEDULE_EXACT_ALARM 并加上应用包名调起设置页面,让用户赋予权限,返回后在 onResume 回调中判断是否权限是否已申请。

下面是一个例子:

// code 1
// MyFragment.kt 中的代码
    private val ALARM_REQUEST_CODE = 123
    private var getExactSchedulePermission = false
    @RequiresApi(Build.VERSION_CODES.S)
    private fun scheduleAlarm() {
        // 创建一个 Intent,用于指定定时任务触发时要执行的操作
        val intent = Intent(requireContext(), AlarmReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            requireContext(),
            ALARM_REQUEST_CODE,
            intent,
            PendingIntent.FLAG_IMMUTABLE
        )

        // 获取 AlarmManager 实例
        val alarmManager = requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager

        // 触发时间(这里使用相对时间)
        val triggerTime = SystemClock.elapsedRealtime() + 5000 // 5秒后触发

        // 设置定时任务
        if (alarmManager.canScheduleExactAlarms()) {
            alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime, pendingIntent)
        } else {
            // 如果没有权限则打开设置页,让用户授予该 App 的精确闹钟权限
            startActivity(Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM))
            getExactSchedulePermission = true
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    override fun onResume() {
        super.onResume()
        if (getExactSchedulePermission) {
            scheduleAlarm()
            getExactSchedulePermission = false
        }
    }

// AlarmReceiver.kt
class AlarmReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Toast.makeText(context, "Alarm triggered!", Toast.LENGTH_SHORT).show()
    }
}

当运行 scheduleAlarm() 方法后,过 5 秒就会有 Toast 出现~

日历或闹钟应用需要在应用停止运行时发送日历提醒、唤醒闹钟或提醒。这些应用可以请求 USE_EXACT_ALARM 常规权限。系统将在安装时授予 USE_EXACT_ALARM 权限,拥有此权限的应用将能够像具有 SCHEDULE_EXACT_ALARM 权限的应用一样设置精确闹钟。

小结:能不用就不用。如果之前已用到精确闹钟,则需要新增权限获取逻辑。

2. 动态广播当 App 进入缓存态时将会入队保存

在 Android14 中,我们使用 Context 上下文注册的动态广播接收器,可以在 App 进入缓存状态时,将已发送还未接收的广播放入到一个队列中保存。当 App 离开缓存状态(比如进入前台),则系统会传递所有已加入队列的广播。某些广播的多个实例可以合并为一个广播。

而在 Manifest 文件中注册的静态广播接收器,则不能进入队列,它们会在 App 从缓存状态中被移除销毁时,进行广播传递。

什么是缓存状态下的 App?简单理解就是在后台的 App,目前不在前台的进程,因此,如果系统其他地方需要内存,系统可以根据需要自由地终止这些进程。当然终止的顺序是最老未使用的最先被终止。

3. App 只能终止自己的后台进程

从 Android14 开始,调用 killBackgroundProcesses() 时,只能终止自己应用的后台进程。如果传入另一个应用的软件包名称,此方法对该应用的后台进程没有影响,并且 Logcat 中会显示以下消息:

Invalid packageName: com.example.anotherapp

官方给出的解释是:

您的应用不应使用 killBackgroundProcesses() API,也不得以其他方式尝试影响其他应用的进程生命周期,即使在旧版操作系统上也是如此。Android 旨在让缓存应用在后台运行,并在系统需要内存时自动终止它们。如果您的应用不必要地终止其他应用,则由于之后需要完全重启这些应用,因此可能会降低系统性能并增加耗电量,这比恢复现有缓存应用所消耗的资源要多得多。

该 API 是 ActivityManager 提供的,完整的方法声明:

// code 2
public void killBackgroundProcesses (String packageName)

此外,使用它还需要在 Manifest 文件中申请权限 Manifest.permission.KILL_BACKGROUND_PROCESSES.

经测试,我发现这个 API 有点奇怪:被杀死的后台进程马上又会重启,额。。。这是什么操作??

测试代码比较简单,就是在另外一个进程中开启一个 Service,然后调用 killBackgroundProcesses 方法即可,根据打印的 Service 生命周期可看出,该 Service 确实先被杀死然后又走了一次 onCreateonStartCommand 生命周期,代码和结果如下所示:

// code 3
// Manifest 文件声明 Service 在另一个进程中启动
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<service
    android:name=".MyService"
    android:process="com.secondProcess" />

// 启动 Service
startService(Intent(requireContext(), MyService::class.java))
// 杀死后台进程
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
activityManager.killBackgroundProcesses(context.packageName)

log 打印结果:
图 1
从图上可知,在 Android14 的设备上,调用 killBackgroundProcesses 方法可以杀死自己 App 的后台进程,但会立即重新启动。在源码中也找到了下面的代码,虽然已被废弃:

// code 3
    @Deprecated
    public void restartPackage(String packageName) {
        killBackgroundProcesses(packageName);
    }

看来这个 API 就是用来重启 App 的后台进程的?

试了下在 Android14 设备上的 A App 中调用此 API 去杀死 B App 的后台进程,确实没有任何作用;但如果是在 Android14 以下的设备上调用,确实可以杀死 B App 的后台进程。感兴趣的同学也可试一试。

小结:killBackgroundProcesses API 并没有什么卵用~(欢迎大佬指点)

4. 安全方面

在 Android14 系统手机上,将无法安装 targetSdkVersion < 23(低于Android6.0)的 App。

媒体包名称在 Android14 上可能会被隐藏。目前媒体库支持按照 OWNER_PACKAGE_NAME 列查询某包名下的所有媒体文件,一个应用存储的媒体文件是带有它自己的包名信息的。这些信息将在 Android14上被隐藏,除非满足以下条件之一:
1)存储媒体文件的应用包名称始终对其他应用可见(自己开放给所有其他 App);
2)查询媒体库的应用获得了 QUERY_ALL_PACKAGES 权限(其他 App 向用户申请获得了权限)。

举个栗子:
当一个应用存储了一个媒体文件(例如一张照片或一个视频),它会在媒体库中记录该文件的信息,包括该文件的所有者包名。其他应用可以查询媒体库以获取这些信息,以便在自己的应用中显示该文件或与之交互。

在 Android14 及以后的版本中,如果存储媒体文件的应用的包名不是始终对其他应用程序可见的,则在查询媒体库时,所有者包名将被隐藏或替换为匿名值。例如,如果一个应用包名为“com.example.app”,它存储了一个媒体文件,但它的包名被隐藏了,那么在查询媒体库时,所有者包名可能会被替换为“com.android.providers.media”。

但是,如果存储媒体文件的应用具有始终对其他应用可见的包名,或者查询媒体库的应用程序具有QUERY_ALL_PACKAGES 权限,则可以看到媒体库中的完整所有者包名。例如,一个应用名为“com.example.app”,它存储了一个媒体文件,并且它的包名始终对其他应用程序可见,那么在查询媒体库时,所有者包名将显示为“com.example.app”。

5. 用户体验方面

5.1 可单独对照片和视频访问权限进行授权

如果你的 App 以 Android13 或更高版本为目标平台(即 targetSdkVersion >= 33),且在 Android14 的设备上运行时,用户可以授予对其照片和视频的部分访问权限,即单独设置 READ_MEDIA_IMAGESREAD_MEDIA_VIDEO

即申请 READ_MEDIA_IMAGES 权限时,仅会显示手机上所有图片给用户进行选择;申请 READ_MEDIA_VIDEO 权限时,仅会显示手机上所有的视频给用户进行选择。用户可以更加细致地选择将哪些照片或视频授权给 App 读取使用。

新的系统对话框长这样:
图 2 READ_MEDIA_IMAGES 或 READ_MEDIA_VIDEO 权限弹窗

1)选择照片和视频: Android14 中的新功能。用户选择希望提供给应用的具体照片和视频。
2)全部允许:用户授予对设备上的所有照片和视频的完整访问权限。
3)不允许:用户拒绝授予所有访问权限。

注意:
1)当应用已经在使用系统的 照片选择器,则无需执行任何操作即可支持此变更;
2)READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 仅在 Android13 或以上的版本才能使用;

新增了一个 READ_MEDIA_VISUAL_USER_SELECTED 权限,属于 Dangerous 级别。用于在用户点击自定义的照片选择器需要申请访问照片和视频的权限时使用,这样就不用去申请 READ_MEDIA_IMAGESREAD_MEDIA_VIDEO 这两个权限了。

小结:开发者不用管,新的权限很鸡肋,暂时用不上,之前读取照片和视频的相关逻辑也不用改。

5.2 更安全的全屏通知展示

在 Android11(API level 30)上就可以调用 Notification.Builder.setFullScreenIntent 方法在锁屏上展示一些全屏的通知了,不过得在 Manifest 文件中申请 USE_FULL_SCREEN_INTENT 权限。

全屏通知是为了让用户立即注意到的高优先级通知而设计的,例如来电或用户配置的闹钟,在展示全全屏通知时,用户只能上滑退出,如下图所示的系统提示。

![图3 全屏通知退出指南](https://img-blog.csdnimg.cn/4b112a31b11f4661b319619bff2eee85.png#pic_center width=300x)

从 Android14 开始,允许使用此权限的应用程序仅限于那些只提供通话和警报的应用。对于其他应用,Google Play 商店会撤销它们默认的 USE_FULL_SCREEN_INTENT 权限。

可以使用新的 API NotificationManager.canUseFullScreenIntent() 检查应用是否有权限;如果没有,可以用新的 ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT 来启动用户可以授予该权限的设置页面。

奇怪的是我在 Android14 官方的虚拟机上并没有打开通知成功,更不用说打开全屏通知了。不过确实可以打开设置全屏通知权限开关的页面,如下是全屏通知权限设置图及主要相关代码:

![图4 打开全屏通知权限设置页](https://img-blog.csdnimg.cn/10ae26cedf7d4a55b3395dac746df695.png#pic_center width=300x)

// code 4
val notificationBuilder = NotificationCompat.Builder(requireContext())
    .setSmallIcon(R.drawable.ic_lock_idle_alarm)
    .setContentTitle("Notification Title")
    .setContentText("Notification text")
// 创建一个PendingIntent,点击Notification时打开指定页面
val intent = Intent(context, NotificationFullActivity::class.java)
val fullScreenIntent =
    PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_MUTABLE)
	notificationBuilder.setFullScreenIntent(fullScreenIntent, true)  // 打开全屏通知
//            notificationBuilder.setContentIntent(fullScreenIntent)  // 打开普通页面

val notificationManager =
    requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Android 8.0 Oreo以上需要设置通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val channelId = "your_channel_id"
    val channelName: CharSequence = "Your Channel Name"
    val importance = NotificationManager.IMPORTANCE_HIGH
    val channel = NotificationChannel(channelId, channelName, importance)
    channel.description = "Channel description"
    notificationManager.createNotificationChannel(channel)
    notificationBuilder.setChannelId(channelId)
}
notificationManager.notify(5, notificationBuilder.build())
if (notificationManager.canUseFullScreenIntent()) {
    notificationManager.notify(5, notificationBuilder.build())
} else {
    // 打开设置页
    val intent = Intent(Settings.ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT)
    intent.data = Uri.fromParts("package", requireActivity().packageName, null)
    startActivity(intent)
}

如果哪位大佬在 Android14 设备上成功地打开了全屏通知,麻烦交流一下,谢谢。

小结:大部分 App 用不上这个全屏通知功能,个人觉得并不是很重要。。。

5.3 关于不可关闭通知用户体验方式的变更

如果应用向用户显示不可关闭的前台通知的话需要注意:Android14 中允许用户关闭此类通知。即之前通过 Notification.Builder#setOngoing(true)NotificationCompat.Builder#setOngoing(true) 设置 Notification.FLAG_ONGOING_EVENT 来阻止用户关闭前台通知的应用要小心了。FLAG_ONGOING_EVENT 的行为已发生变化,用户在 Android14 上可以关闭此类通知。

以下情况,此类通知仍不可关闭:
1)当手机处于锁定状态时;
2)如果用户选择全部清除通知操作(有助于防止意外关闭);

此外,下列的几种情况并没有变更:
1)使用 CallStyle 创建的通知,即来电通知的样式;
2)设备策略控制器(DPC)和针对企业的支持包;

小结:Android 的通知管理只会越来越严格,早就应该管管了。其实就算 Android14 手机上没有这个功能,目前绝大多数手机厂商已经都可以禁止 App 弹出通知了,所以这个也没啥。。。

以上就是本篇的所有内容,主要根据官方文档自己实践操作了一番,可以看出,现有的 App 如果直接安装到 Android14 的手机上,并不会有太多的问题,许多东西其实并不用另外处理,当然建议还是根据本篇内容查漏补缺比较好。如果还想了解 targetSdkVersion 升级到 34(Android14)还需要注意哪些内容,欢迎关注我,咱们下篇见!

更多内容,欢迎关注公众号:修之竹
或者查看 修之竹的 Android 专辑

赞人玫瑰,手留余香!欢迎点赞、转发~ 转发请注明出处~

参考文献

  1. Android 14 官方文档 https://developer.android.com/about/versions/14
  2. https://developer.android.google.cn/about/versions/14/behavior-changes-all?hl=zh-cn
  3. https://developer.android.google.cn/about/versions/14/changes/schedule-exact-alarms?hl=zh-cn
  4. https://developer.android.google.cn/guide/components/activities/process-lifecycle?hl=zh-cn
  5. https://developer.android.google.cn/about/versions/14/behavior-changes-14
  6. Android 14 快速适配要点; 恋猫de小郭; https://juejin.cn/post/7231835495557890106?searchId=202307240025039D8229C74EA62159077B
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录: 结构如下,非常详细 第1章 android系统概述 1 1.1 基础知识 1 1.1.1 android开发系统的由来 1 1.1.2 移动电话系统开发模式 2 1.1.3 未来移动电话的功能及android的优势 4 1.2 android的开发工作 6 1.2.1 android移植开发 6 1.2.2 android应用开发 8 1.2.3 android系统开发 9 1.3 android的sdk与源代码 10 1.3.1 基于sdk的android开发 10 1.3.2 基于源代码sdk android开发 11 第2章 android系统开发综述 13 2.1 android的系统架构 13 2.1.1 软件结构 13 2.1.2 android的工具 16 2.2 android源代码的开发环境 18 2.2.1 android源代码的获取和提交 18 2.2.2 android源代码结构 21 2.2.3 编译 24 .2.2.4 系统的运行 25 2.3 android sdk的开发环境 32 2.3.1 sdk的结构 32 2.3.2 windows环境sdk开发 33 2.3.3 linux环境sdk开发 42 第3章 android的linux内核与驱动程序 44 3.1 linux核心与驱动 44 3.2 android专用驱动 45 3.2.1 ashmem 45 3.2.2 binder 45 3.2.3 logger 46 3.3 android使用的设备驱动 46 3.3.1 framebuffer显示驱动 46 3.3.2 event输入设备驱动 48 3.3.3 v4l2摄像头——视频驱动 50 3.3.4 oss音频驱动 53 3.3.5 alsa音频驱动 54 3.3.6 mtd驱动 56 3.3.7 蓝牙驱动 57 3.3.8 wlan驱动 58 第4章 android的底层库和程序 60 4.1 底层库和程序的结构 60 4.1.1 本地实现的基本结构 60 4.1.2 增加本地程序和库的方法 61 4.2 标准c/c++库bionic 64 4.3 c语言工具库libcutils 65 4.4 init可执行程序 66 4.5 shell工具 72 4.6 c++工具库libutils 75 4.6.1 libutils的基本内容 75 4.6.2 binder 76 4.6.3 libutils中的其他内容 82 4.7 android的系统进程 85 4.7.1 servicemanager 85 4.7.2 zygote 87 第5章 android的java虚拟机和java环境 88 5.1 dalvik虚拟机和核心库 88 5.1.1 dex工具库和虚拟机的实现 89 5.1.2 核心库 90 5.1.3 nativehelper库 91 5.2 android的java程序环境 91 5.2.1 java类的层次结构 91 5.2.2 android java类的代码 92 5.2.3 android系统api 92 5.3 jni的使用 96 5.3.1 jni的架构和实现方式 97 5.3.2 jni的实现方式 97 5.3.3 在应用程序中使用jni 99 5.4 系统服务的java部分 101 5.4.1 binder 102 5.4.2 servicemanager 103 5.4.3 系统进程 103 第6章 android的gui系统 106 6.1 android gui系统综述 106 6.2 pixelflinger和libui库 108 6.2.1 pixelflinger 108 6.2.2 libui 108 6.2.3 输出/输入与硬件的接口 109 6.3 surface系统 113 6.3.1 surface系统本地接口 113 6.3.2 surfaceflinger本地代码 115 6.3.3 surface的java和jni代码 119 6.4 skia和2d图形系统 121 6.4.1 skia底层库 121 6.4.2 android图形系统的jni接口 124 6.4.3 android的图形包(graphics) 125 6.5 android的opengl系统与3d图形系统 125 6.5.1 opengl的本地代码 125 6.5.2 opengl的jni代码 130 6.5.3 opengl的java类 130 第7章 android的audio系统 132 7.1 audio系统综述 132 7.2 audio系统和上层接口 134 7.2.1 audio系统的各个层次 134 7.2.2 media库
### 回答1: 在 Python 中使用异步功能给 Android 手机安装 app 需要使用一个第三方库,例如 adb(Android Debug Bridge)。使用 adb 库可以通过命令行控制 Android 设备,包括安装和卸载 app。下面是一个简单的示例,展示了如何使用 adb 库的 asyncio 支持异步安装 app: ``` import asyncio import adb async def install_app(device, app_path): await device.install(app_path) async def main(): adb_server = adb.ADB() devices = await adb_server.devices() if len(devices) == 0: print("No device found.") return device = devices[0] app_path = '/path/to/app.apk' await install_app(device, app_path) print("App installed.") asyncio.run(main()) ``` 在上面的代码中,我们首先使用 adb 库的 `ADB` 类连接到 adb 服务器,然后使用 `devices` 方法检索连接的设备列表。然后我们可以使用 `install` 方法安装 app注意,这些方法都是异步的,因此我们需要使用 `await` 关键字来等待它们完成。 希望这个示例能帮助你开始使用 adb 库实现异步安装 app 的功能。 ### 回答2: 使用Python异步给Android手机安装app的方法如下: 首先,我们需要确保Android手机已经连接到计算机上,并且已经启用了USB调试模式。接下来,我们可以借助于第三方库adb-python来实现。 adb-python是一个基于Python的adb(Android Debug Bridge)的封装库,它允许我们通过Python代码执行adb命令。 在我们开始之前,我们需要确保已经安装了adb-python库。可以通过在终端中执行以下命令进行安装: ``` pip install adb ``` 安装完成后,我们可以在Python脚本中导入adb模块,并使用其中的函数来执行adb命令。 以下是一个示例代码,展示了如何使用Python异步给Android手机安装app: ```python import asyncio import adb async def install_app(package_path): result = await adb.run("install", package_path) print(result) async def main(): package_path = "/path/to/app.apk" await install_app(package_path) if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(main()) loop.close() ``` 在上面的代码中,我们定义了一个async函数install_app,用于执行adb命令进行app安装。我们通过await关键字来等待adb.run函数的结果,并在函数中打印出结果。 在main函数中,我们调用了install_app函数,并通过asyncio模块的get_event_loop函数来获取事件循环,然后使用run_until_complete方法来运行异步函数main。 运行上述代码,就可以异步地给Android手机安装app了。在实际使用中,可以根据需要进行修改和扩展,以满足具体的需求。 ### 回答3: Python异步给Android手机安装App的主要步骤包括以下几个方面: 1. 获取Android设备的连接:首先需要通过adb命令或者第三方库(如ADB-Android Debug Bridge)来获取已经连接的Android设备,并确保设备处于开发者模式下。 2. 下载要安装App:使用Python的异步网络请求库例如aiohttp来从指定的服务器或者应用市场下载要安装App,将App下载到本地。 3. 安装App:使用adb命令来执行安装App的操作,可以使用subprocess库来在Python代码中执行adb命令。需要注意的是,执行adb命令时需要确保adb路径被添加到系统的环境变量中,并且设备已经通过USB与计算机连接。 4. 检查安装状态:可以使用adb命令来查询App安装状态,确认是否安装成功。也可以通过检查设备上已安装的应用列表来验证是否成功安装。 5. 清理:在安装完成后,可以使用adb命令卸载不再需要App或者清除安装时产生的临时文件。 需要注意的是,由于Python是一门解释型语言,其在执行adb命令时可能会因为需要等待adb命令的执行结果而产生阻塞。为了实现异步操作,可以使用Python的异步编程库如asyncio结合协程来优化执行效率,或者使用第三方库如scrcpy来在Python中控制设备并进行异步操作。 以上是Python异步给Android手机安装App的简要步骤。具体实现时需要根据具体的需求和环境进行适配和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值