首页 文章 精选 留言 我的

精选列表

搜索[android],共10000篇文章
优秀的个人博客,低调大师

Mac系统下利用ADB命令连接android手机并进行文件操作

1 获取序列号:adb get-serialno 2 查看连接计算机的设备:adb devices 3 重启机器:adb reboot 4 重启到bootloader,即刷机模式:adb reboot bootloader 5 重启到recovery,即恢复模式:adb reboot recovery 6 查看log:adb logcat 7 终止adb服务进程:adb kill-server 8 重启adb服务进程:adb start-server 9 获取机器MAC地址:adb shell cat /sys/class/net/wlan0/address 10 获取CPU序列号:adb shell cat /proc/cpuinfo 11 安装APK:adb install <apkfile> //比如:adb install baidu.apk 12 保留数据和缓存文件,重新安装apk:adb install -r <apkfile> //比如:adb install -r baidu.apk 13 安装apk到sd卡:adb install -s <apkfile> // 比如:adb install -s baidu.apk 14 卸载APK:adb uninstall <package> //比如:adb uninstall com.baidu.search 15 卸载app但保留数据和缓存文件:adb uninstall -k <package> //比如:adb uninstall -k com.baidu.search 16 启动应用:adb shell am start -n <package_name>/.<activity_class_name> 17 查看设备cpu和内存占用情况:adb shell top 18 查看占用内存前6的app:adb shell top -m 6 19 刷新一次内存信息,然后返回:adb shell top -n 1 20 查询各进程内存使用情况:adb shell procrank 21 杀死一个进程:adb shell kill [pid] 22 查看进程列表:adb shell ps 23 查看指定进程状态:adb shell ps -x [PID] 24 查看后台services信息:adb shell service list 25 查看当前内存占用:adb shell cat /proc/meminfo 26 查看IO内存分区:adb shell cat /proc/iomem 27 将system分区重新挂载为可读写分区:adb remount 28 从本地复制文件到设备:adb push <local> <remote> 29 从设备复制文件到本地:adb pull <remote> <local> 30 列出目录下的文件和文件夹,等同于dos中的dir命令:adb shell ls 31 进入文件夹,等同于dos中的cd 命令:adb shell cd <folder> 32 重命名文件:adb shell rename path/oldfilename path/newfilename 33 删除system/avi.apk:adb shell rm /system/avi.apk 34 删除文件夹及其下面所有文件:adb shell rm -r <folder> 35 移动文件:adb shell mv path/file newpath/file 36 设置文件权限:adb shell chmod 777 /system/fonts/DroidSansFallback.ttf 37 新建文件夹:adb shell mkdir path/foldelname 38 查看文件内容:adb shell cat <file> 39 查看wifi密码:adb shell cat /data/misc/wifi/*.conf 40 清除log缓存:adb logcat -c 41 查看bug报告:adb bugreport 42 获取设备名称:adb shell cat /system/build.prop 43 查看ADB帮助:adb help 44 跑monkey:adb shell monkey -v -p your.package.name 500

优秀的个人博客,低调大师

Android后台任务可靠性排查:从WorkManager 观测到失败重试闭环

后台同步最难处理的部分,往往不是把任务提交给 WorkManager,而是回答“它为什么没有按预期完成”。本文以一个离线优先的资料同步任务为例,梳理约束条件、任务状态、失败分类、重试策略和幂等落库,建立一条可以在本地与线上复用的排查闭环。 ## 先定义任务的完成语义 “同步成功”不能只等同于接口返回 HTTP 200。一个完整任务至少要明确四个结果: - 服务端数据已经拉取并通过基本校验。 - 本地事务已经提交,下一次读取能够看到新数据。 - 当前任务不会因为重复执行产生重复记录或错误覆盖。 - 失败时能够判断是应该重试、等待约束满足,还是直接结束。 如果这些语义没有先定义,排查时看到 `SUCCEEDED` 也可能只是“请求成功”,并不代表本地数据可用。 ## 约束决定任务何时有机会运行 WorkManager 会综合网络、电量、充电和存储等约束决定任务是否可以启动。约束不满足时,任务通常停留在 `ENQUEUED`,这不是执行失败。 ``` val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .setRequiresBatteryNotLow(true) .build() val request = OneTimeWorkRequestBuilder() .setConstraints(constraints) .setBackoffCriteria( BackoffPolicy.EXPONENTIAL, 30, TimeUnit.SECONDS ) .setInputData(workDataOf("reason" to "manual_refresh")) .addTag("profile-sync") .build() WorkManager.getInstance(context).enqueueUniqueWork( "profile-sync", ExistingWorkPolicy.KEEP, request ) ``` 这里有三个容易被忽略的点: - `CONNECTED` 只表示存在网络连接,不保证接口可达,也不保证服务端健康。 - 指数退避的最短间隔会受到 WorkManager 限制,不能把它当作精确的定时器。 - `KEEP` 会保留已经存在的唯一任务。用户点击刷新后没有新任务,不一定是提交失败,可能是旧任务仍在队列中。 ## 用唯一任务和标签保留可观测性 任务名适合表达业务上的唯一工作,标签适合按业务维度查询。不要只保存 `WorkRequest` 对象,因为进程重启后它不会替你保留诊断上下文。 ``` suspend fun observeSync(workManager: WorkManager): SyncSnapshot { val work = workManager .getWorkInfosForUniqueWork("profile-sync") .firstOrNull() return when { work == null -> SyncSnapshot.NotScheduled work.state == WorkInfo.State.RUNNING -> SyncSnapshot.Running work.state == WorkInfo.State.ENQUEUED -> SyncSnapshot.Waiting(work.runAttemptCount, work.constraints) work.state == WorkInfo.State.SUCCEEDED -> SyncSnapshot.Success work.state == WorkInfo.State.FAILED -> SyncSnapshot.Failed(work.outputData.getString("error")) else -> SyncSnapshot.Cancelled } } ``` 真实项目中建议把以下信息写入日志或本地诊断表:任务唯一名、请求原因、创建时间、开始时间、结束时间、运行次数、最后一次错误类型和数据版本。日志中不要写入 token、完整用户资料或接口响应原文。 ## 正确区分失败和重试 `CoroutineWorker.doWork()` 返回 `Result.retry()` 时,WorkManager 会按照退避策略重新调度;返回 `Result.failure()` 则表示任务终止。判断标准应该是错误是否具有临时性,而不是简单地“所有异常都重试”。 ``` class SyncWorker( appContext: Context, params: WorkerParameters, private val repository: SyncRepository ) : CoroutineWorker(appContext, params) { override suspend fun doWork(): Result { return try { repository.syncOnce() Result.success() } catch (e: IOException) { Result.retry() } catch (e: HttpException) { if (e.code() == 408 || e.code() == 429 || e.code() >= 500) { Result.retry() } else { Result.failure(workDataOf("error" to "http_${e.code()}")) } } catch (e: InvalidPayloadException) { Result.failure(workDataOf("error" to "invalid_payload")) } } } ``` 常见分类可以这样处理:网络断开、连接超时、服务端 5xx 和限流通常适合重试;鉴权失效、参数错误和无法解析的协议变更应该失败并触发业务告警。对于重试次数,还要考虑服务端是否支持幂等,以及任务是否会被系统重启后再次执行。 ## 重试必须建立在幂等之上 假设同步接口返回同一条资料两次,直接 `insert` 可能造成重复数据。更稳妥的做法是让服务端对象携带稳定主键,在 Room 中使用唯一索引,并在一个事务中完成版本判断与写入。 ``` @Entity( tableName = "profile", indices = [Index(value = ["remoteId"], unique = true)] ) data class ProfileEntity( @PrimaryKey(autoGenerate = true) val localId: Long = 0, val remoteId: String, val version: Long, val name: String ) @Transaction suspend fun replaceIfNewer(items: List) { items.forEach { item -> val old = profileDao.findByRemoteId(item.remoteId) if (old == null || item.version > old.version) { profileDao.upsert(item) } } } ``` 如果接口支持增量同步,建议把服务端游标和资料更新放到同一个本地事务中。只有资料写入成功后才推进游标,避免游标先前移、数据却没有落库,最终造成不可恢复的漏同步。 ## 从状态反推故障位置 排查可以按下面顺序进行: 1. 先查询唯一任务是否存在,确认是没有提交、被 `KEEP` 合并,还是已经完成。 2. 如果状态是 `ENQUEUED`,查看约束、初始延迟、重试次数和是否被暂停。 3. 如果状态是 `RUNNING`,检查 Worker 是否卡在网络、数据库事务或锁等待。 4. 如果状态是 `FAILED`,读取受控的错误码,并关联最近一次运行日志。 5. 如果状态是 `SUCCEEDED`,直接查询本地数据和同步游标,不要只看任务状态。 6. 检查任务是否被取消,以及取消来源是用户操作、应用登出还是系统策略。 可以在调试页面展示脱敏后的任务快照,给测试和客服一个稳定的证据入口。线上则将任务名、错误码、运行次数和耗时接入统一日志,不依赖开发者手工复现。 ## 常见误区 ### 把 WorkManager 当作实时执行器 它适合可延迟、可保证最终执行的后台工作,不适合秒级刷新、持续音频处理或必须立即完成的交互。实时场景应选择前台服务、推送或应用内主动请求等更匹配的机制。 ### 在 Worker 中无限等待 网络请求、互斥锁和数据库操作都应该有超时边界。无限挂起会让任务长期处于 `RUNNING`,同时占用系统调度资源,最终让后续诊断失去方向。 ### 只在 UI 层观察任务 UI 进程可能被销毁,界面观察也可能因为页面离开而停止。任务诊断应沉淀在 repository 或诊断表,UI 只是读取快照并展示。 ## 小结 可靠的后台任务不是“提交一个 Worker”这么简单,而是一套可解释的系统:约束说明何时执行,唯一任务说明如何合并,状态和日志说明发生了什么,错误分类决定是否重试,幂等事务保证重复执行不会破坏数据。把这些信息串起来后,后台同步从“偶尔失效”变成可以定位、修复和验证的工程问题。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册