安卓framework学习6:Contacts 联系人 APP 日志

基于香橙派 3B(自编译 Android 11)的 Contacts 联系人 APP 日志添加、编译推送及调试实践

第一篇:Android 基础概念

一、APP 和 Activity 的关系

概念 说明
APP(应用) 多个 Activity 的集合
Activity(页面) APP 中的一个界面
PeopleActivity Contacts APP 的主入口 Activity(类似首页)

打开联系人 APP 流程

  1. 点击桌面图标 → Android 系统启动 Contacts 应用进程
  2. 启动 PeopleActivity → 显示联系人列表主页面

二、Contacts APP 的主要 Activity

Activity 用途
PeopleActivity 主页面 --- 联系人列表、收藏、群组
ContactEditorActivity 编辑/新建联系人
ContactSelectionActivity 选择联系人(发短信时选人)
QuickContactActivity 快速联系人卡片(弹窗)
AccountFilterActivity 按账户过滤联系人列表

三、priv-app 含义

  • priv-app = privileged application(特权应用)
  • 比普通 APP 拥有更高权限,可调用系统级 API
  • Contacts 是核心系统应用,放在 /product/priv-app/Contacts/

四、路径权限对比

路径 类型 权限等级
/product/priv-app/ 特权应用 🔒 最高
/system/app/ 系统应用 较高
/data/app/ 用户安装 APP 普通

五、adb 命令速查表

命令 含义
adb devices 查看连接的设备
adb root 获取 root 权限
adb remount 重新挂载分区为可读写
adb shell 进入设备 shell
adb push 本地 远程 推送文件到设备
adb pull 远程 本地 从设备拉取文件
adb logcat 查看设备运行日志
adb logcat -v time 带时间戳输出日志
adb logcat -s TAG 只过滤指定 TAG 的日志
adb logcat -c 清空日志缓冲区
adb shell am force-stop 包名 强制停止 APP
adb shell am start -n 包名/Activity名 启动指定 Activity
adb shell pm path 包名 查看 APP 安装路径

第二篇:MainActivity 核心解析

一、onCreate() --- 第一个执行的方法

java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    // 【核心步骤 1】:绑定界面布局
    setContentView(R.layout.activity_main); 
    
    // 【核心步骤 2】:绑定组件(按钮、文本框等)
    // Button myButton = findViewById(R.id.button1);
}

⚠️ 注意encrypt 是听误,正确的词是 onCreate(创建)

二、Log 日志打印

java 复制代码
Log.e("MyTag", "这是我的日志信息");

参数解析

参数 作用
第一个参数(Tag/标签) 过滤日志用,相当于给这句话贴标签
第二个参数(Msg/消息) 你想看的具体内容

Log 级别对照表

方法 级别 颜色 用途
Log.v() Verbose(啰嗦) 黑色 最详细的日志
Log.d() Debug(调试) 蓝色 调试信息
Log.i() Info(信息) 绿色 一般信息
Log.w() Warning(警告) 橙色 警告信息
Log.e() Error(错误) 🔴 红色 错误信息(新手推荐)

💡 小白技巧 :刚开始学习用 Log.e(),红色日志一眼就能看到。

三、极简 MainActivity 模板

java 复制代码
package com.example.myapp;

import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Log.e("小白测试", "我的第一个 App 成功启动啦!");
    }
}

第三篇:源码分析方法

一、源码分析的两大核心方式

方式 定义 适用场景 特点
主动分析(正向追踪) 顺着代码逻辑向下追溯 研究完整生命周期或初始化流程 逻辑连贯,但容易迷失
调用分析(逆向追踪) 从具体 API 出发,跳转到定义 了解某个方法的底层原理 目的性强,效率高

二、无法跳转的函数的解决方案

痛点onCreateonDestroy 等生命周期方法无法跳转。

解决方案:打印方法调用堆栈(Trace)

java 复制代码
Log.e("SourceAnalysis", "Log Triggered Here!", new Throwable());

三个参数解析

参数 说明
参数1(Tag) 日志标签,用于过滤
参数2(Msg) 提示信息
参数3(Throwable) 关键:创建异常对象,自动捕捉当前线程堆栈

输出示例

php 复制代码
E/SourceAnalysis: Log Triggered Here!
    java.lang.Throwable
        at com.example.app.MainActivity.onCreate(MainActivity.java:15)
        at android.app.Activity.performCreate(Activity.java:8051)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3600)

分析方法:根据日志中的类名和行号,全局搜索跳转到对应源码。

第四篇:Android 系统调试方法

一、Logcat 日志调试(最常用)

| 命令 | 用途 |
|----------------------|-----------------|---------------|
| adb logcat | 实时查看所有日志 |
| adb logcat -v time | 带时间戳输出(推荐) |
| adb logcat *:E | 仅显示 Error 级别及以上 |
| `adb logcat | grep "关键字"` | 过滤特定日志(Linux) |

二、UART 串口调试(硬件调试)

适用场景:U-Boot 阶段、Kernel 崩溃、驱动加载失败、ADB 无法连接时。

使用步骤

  1. USB 转 TTL 模块连接香橙派 Debug UART 引脚(TX→RX,RX→TX)
  2. 电脑端设置波特率为 1500000(Rockchip 标准)
  3. 串口控制台输入 dmesg 查看内核日志,输入 logcat 查看 Android 日志

三、ADB Shell 系统状态审查

命令 用途
adb shell dumpsys activity 查看当前 Activity 状态
adb shell dumpsys window 查看窗口层级和焦点
adb shell bugreport 生成全面体检报告
adb shell top 查看 CPU 占用
adb shell procrank 查看内存占用

四、Native 层调试(C/C++ 崩溃)

Tombstone(墓碑日志)

  • Native 进程崩溃时,系统在 /data/tombstones/ 生成日志文件
  • adb pull /data/tombstones/ 拉取后配合 ndk-stack 定位代码行

第五篇:Contacts 联系人 APP 日志添加与编译推送

一、修改文件位置

bash 复制代码
packages/apps/Contacts/src/com/android/contacts/activities/PeopleActivity.java

二、添加的中文日志代码

java 复制代码
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: super.onCreate 完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 账户类型管理器和过滤器控制器初始化完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 运行时权限检查完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: Intent 处理完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 联系人列表过滤器验证完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 设置内容视图 contacts_drawer_activity 完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 操作栏设置完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 抽屉导航设置完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 注册监听器完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: 创建视图和 Fragment 完成");
Log.d(Constants.PERFORMANCE_TAG, "PeopleActivity: onCreate 全部完成");

关键说明

  • Constants.PERFORMANCE_TAG = "ContactsPerf"(在 Constants.java 中定义)
  • 使用 Log.d()(DEBUG 级别)
  • ⚠️ Constants 类中没有 TAG 字段,只有 PERFORMANCE_TAG

三、onCreate 执行流程(启动顺序)

顺序 步骤
1 设置主题(在 super.onCreate 之前)
2 super.onCreate --- Android 框架初始化
3 初始化管理器(AccountTypeManager、ContactListFilterController)
4 检查运行时权限
5 处理 Intent(无效则结束 Activity)
6 过滤器验证
7 设置布局(R.layout.contacts_drawer_activity)
8 设置 ActionBar
9 设置抽屉导航(汉堡按钮)
10 恢复导航模式(默认 ALL_CONTACTS)
11 注册监听器
12 记录是否重建实例
13 创建视图和 Fragment
14 释放窗口背景

四、编译 Contacts APK

环境准备(必须在同一终端)

bash 复制代码
cd ~/aosp/RK3566_Android_Source_Code/RK356X_Android11
source build/envsetup.sh
lunch 51          # 选择 rk3566_r-userdebug

编译命令

bash 复制代码
# 只编译 Contacts 主模块(推荐)
mmm packages/apps/Contacts:Contacts

# 或编译 Contacts 及测试模块
mmm packages/apps/Contacts

编译产物路径

bash 复制代码
out/target/product/rk3566_r/product/priv-app/Contacts/Contacts.apk

五、推送 APK 到设备

完整流程

bash 复制代码
# 1. 确认设备连接
adb devices

# 2. 获取 root 权限并 remount
adb root && adb remount

# 3. 推送 APK(注意正确路径!)
adb push out/target/product/rk3566_r/product/priv-app/Contacts/Contacts.apk /product/priv-app/Contacts/Contacts.apk

# 4. 确认路径正确
adb shell pm path com.android.contacts
# 输出应为:package:/product/priv-app/Contacts/Contacts.apk

# 5. 强制停止 APP 并重启
adb shell am force-stop com.android.contacts
adb shell am start -n com.android.contacts/.activities.PeopleActivity

六、为什么系统应用可以直接替换 APK?

对比项 普通应用 系统应用
安装位置 /data/app/ /product/priv-app//system/app/
安装方式 adb install 直接替换 APK 文件
生效条件 需要安装流程 重启 APP 即可

原理

  1. 安装位置不同 :系统应用在 /system 等只读分区,系统启动时扫描目录生成应用列表,不依赖复杂的数据库注册机制
  2. 加载方式不同 :重启 APP 时,系统直接重新读取磁盘上的 APK 文件,没有额外的安装状态需要同步

七、日志查看命令

bash 复制代码
# 只看 ContactsPerf 标签的日志(推荐)
adb logcat -v time -s ContactsPerf

# 清空旧日志再看
adb logcat -c && adb logcat -v time -s ContactsPerf

# 直接启动 APP
adb shell am start -n com.android.contacts/.activities.PeopleActivity

八、常见问题排查

问题 解决方案
看不到中文日志 adb shell setprop log.tag.ContactsPerf DEBUG
APP 没更新 检查是否推对了路径(/product/ 不是 /system/
推完还是旧代码 adb shell am force-stop com.android.contacts 强杀再重启
不知道 APK 路径 adb shell pm path com.android.contacts

附录:控制台快捷键

快捷键 作用
Tab 自动补全命令或路径
Ctrl + C 终止当前命令
Ctrl + D 退出 shell
/ 浏览历史命令

js 复制代码
05-28 07:05:09.474 D/ContactsPerf( 2117): ContactsApplication.onCreate start
05-28 07:05:09.476 D/ContactsPerf( 2117): ContactsApplication.onCreate finish
05-28 07:05:09.623 D/ContactsPerf( 2117): PeopleActivity.onCreate start
05-28 07:05:09.623 D/ContactsPerf( 2117): PeopleActivity: 调用堆栈
05-28 07:05:09.623 D/ContactsPerf( 2117): java.lang.Throwable: stack trace
05-28 07:05:09.623 D/ContactsPerf( 2117):       at com.android.contacts.activities.PeopleActivity.onCreate(PeopleActivity.java:348)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.Activity.performCreate(Activity.java:8022)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.Activity.performCreate(Activity.java:8006)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3404)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3595)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.os.Handler.dispatchMessage(Handler.java:106)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.os.Looper.loop(Looper.java:223)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at android.app.ActivityThread.main(ActivityThread.java:7664)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at java.lang.reflect.Method.invoke(Native Method)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
05-28 07:05:09.623 D/ContactsPerf( 2117):       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
05-28 07:05:09.665 D/ContactsPerf( 2117): PeopleActivity: super.onCreate 完成
05-28 07:05:09.708 D/ContactsPerf( 2117): PeopleActivity: 账户类型管理器和过滤器控制器初始化完成
05-28 07:05:09.713 D/ContactsPerf( 2117): PeopleActivity: 运行时权限检查完成
05-28 07:05:09.714 D/ContactsPerf( 2117): PeopleActivity: Intent 处理完成
05-28 07:05:09.714 D/ContactsPerf( 2117): PeopleActivity: 联系人列表过滤器验证完成
05-28 07:05:09.808 D/ContactsPerf( 2117): PeopleActivity: 设置内容视图 contacts_drawer_activity 完成
05-28 07:05:09.837 D/ContactsPerf( 2117): PeopleActivity: 操作栏设置完成
05-28 07:05:09.846 D/ContactsPerf( 2117): PeopleActivity: 抽屉导航设置完成
05-28 07:05:09.847 D/ContactsPerf( 2117): PeopleActivity: 设置默认导航模式,当前视图=ALL_CONTACTS
05-28 07:05:09.847 D/ContactsPerf( 2117): PeopleActivity: 注册监听器完成
05-28 07:05:09.847 D/ContactsPerf( 2117): PeopleActivity: 是否为重建实例=false
05-28 07:05:09.928 D/ContactsPerf( 2117): PeopleActivity: 创建视图和 Fragment 完成
05-28 07:05:09.928 D/ContactsPerf( 2117): PeopleActivity.onCreate finish
05-28 07:05:09.929 D/ContactsPerf( 2117): PeopleActivity: onCreate 全部完成

📊 日志分析

一、(2117) 是什么?

每次启动 APP 都会不一样。

项目 说明
2117 进程 ID(PID)
含义 Android 系统为每个运行的 APP 进程分配的唯一编号
变化规律 每次 APP 冷启动(完全退出后重启),PID 都会变化
同一进程内 PID 保持不变,可用于判断日志是否来自同一次启动

示例对比

ini 复制代码
第一次启动:D/ContactsPerf( 2117)  ← PID=2117
第二次启动:D/ContactsPerf( 2513)  ← PID=2513(变化了)
第三次启动:D/ContactsPerf( 1892)  ← PID=1892(又变了)

实际应用

  • 同一 PID 的所有日志 → 同一次启动过程
  • PID 变了 → APP 被完全杀死后重新启动了

二、堆栈信息解读

堆栈日志从下往上读,最下面是最早的调用,最上面是当前执行位置。

scss 复制代码
堆栈内容(从下往上倒序):
│
├─ ZygoteInit.main()                    ← 【最底层】系统启动进程
│
├─ RuntimeInit.main()                   ← 运行时初始化
│
├─ ActivityThread.main()                ← 主线程入口
│
├─ Looper.loop()                        ← 消息循环开始
│
├─ Handler.dispatchMessage()            ← 分发消息
│
├─ ActivityThread$H.handleMessage()     ← 处理 Activity 启动消息
│
├─ TransactionExecutor.execute()        ← 执行事务
│
├─ LaunchActivityItem.execute()         ← 执行启动 Activity 的具体操作
│
├─ ActivityThread.handleLaunchActivity() ← 处理启动 Activity
│
├─ ActivityThread.performLaunchActivity() ← 执行启动 Activity
│
├─ Instrumentation.callActivityOnCreate() ← 通过 Instrumentation 调用 onCreate
│
├─ Activity.performCreate()             ← Activity 执行创建
│
└─ PeopleActivity.onCreate()            ← 【最顶层】我们加的日志位置

三、关键调用链(核心路径)

从堆栈中提取的关键调用路径

scss 复制代码
# 起点:系统进程启动
ZygoteInit.main()
    ↓
# Activity 主线程入口
ActivityThread.main()
    ↓
# 消息循环
Looper.loop()
    ↓
# 收到启动 Activity 的消息
ActivityThread$H.handleMessage()
    ↓
# 执行启动事务
TransactionExecutor.execute()
    ↓
LaunchActivityItem.execute()
    ↓
# 创建 Activity 实例
ActivityThread.performLaunchActivity()
    ↓
# 调用生命周期
Instrumentation.callActivityOnCreate()
    ↓
Activity.performCreate()
    ↓
# 🎯 我们代码执行的地方
PeopleActivity.onCreate()

四、日志时间线分析

时间 事件 耗时
07:05:09.474 ContactsApplication.onCreate start -
07:05:09.476 ContactsApplication.onCreate finish 2ms
07:05:09.623 PeopleActivity.onCreate start 147ms 后
07:05:09.623 打印堆栈 -
07:05:09.665 super.onCreate 完成 42ms
07:05:09.708 初始化管理器完成 43ms
07:05:09.713 权限检查完成 5ms
07:05:09.714 Intent 处理完成 1ms
07:05:09.808 设置布局完成 94ms
07:05:09.837 操作栏设置完成 29ms
07:05:09.846 抽屉导航设置完成 9ms
07:05:09.847 注册监听器完成 1ms
07:05:09.928 创建视图和 Fragment 完成 81ms
07:05:09.928 PeopleActivity.onCreate finish -

总耗时 :PeopleActivity.onCreate 从 09.623 到 09.928 ≈ 305ms

耗时最长的步骤

  1. 设置布局:94ms
  2. 创建视图和 Fragment:81ms
  3. super.onCreate:42ms + 初始化管理器:43ms = 85ms

五、堆栈分析的实际用途

场景 如何使用堆栈
找不到方法调用者 打印堆栈,直接从下往上找到谁调用了你
理解系统调用流程 堆栈天然展示了完整的调用链
定位崩溃根源 崩溃日志中的堆栈直接指向出错代码行
学习源码架构 通过堆栈了解 Android 系统的层层调用关系

六、核心知识点总结

知识点 结论
PID(进程 ID) 每次冷启动都不同,同一进程内不变,用于区分不同启动
堆栈读法 从下往上读,最下面是调用源头,最上面是当前位置
PeopleActivity 启动入口 ActivityThread.performLaunchActivity 进入
生命周期管控 InstrumentationActivityThread 配合完成
性能瓶颈 布局加载和 Fragment 创建是最耗时的环节
相关推荐
Jinkxs2 小时前
Python基础 - 初识内置函数 Python自带的便捷工具
android·java·python
私人珍藏库3 小时前
【Android】VLLO-韩国热门手机剪辑APP
android·app·工具·软件·多功能
Cloud_Shy6183 小时前
解读《Effective Python 3rd Edition》:从练气到老魔(第六章 Item 40 - 43)
android·开发语言·人工智能·笔记·python·学习方法
AFinalStone4 小时前
Android12 U盘插拔链路源码全解析(五):Framework层(下) StorageManagerService
android·frameworks
林九生5 小时前
【实用技巧】MySQL 绿色版一键路径更新脚本详解 —— update_path.bat 深度解析
android·数据库·mysql
故渊at7 小时前
第十三板块:Android 综合架构与未来演进 | 第三十一篇:Android 架构演进与 Fuchsia OS 的挑战
android·架构·宏内核·微内核·fuchsia·ipc 性能博弈
aqi007 小时前
一文速览 HarmonyOS 6.1.1 推出的十个新特性
android·华为·harmonyos·鸿蒙·harmony
matrixmind17 小时前
aiomysql:异步场景下的 MySQL 驱动
android·数据库·mysql·其他
随遇丿而安7 小时前
第8周:弹窗 / 提示组件全功能与弹窗优化
android
zh_xuan7 小时前
诡异Bug:输入框删除字符,却越删越多
android·bug