• Android 源码 <package> 了解 [4]


    在这里插入图片描述

    Read The Fucking Source Code. —— Linus

    站在’巨人’的肩膀上开始自己的旅途。—— 佚名

    愉快的周末,从打开💻开始,到骑行归来结束。—— 佚名

    忙忙碌碌又一周,城市的快节奏似乎是时间的轮盘上了润滑剂比以往转得更快,早上进入地铁看天空还是那么明亮,晚上踏出地铁口已是昏暗。

    工作日确实忙绿,然而周末呢?

    上午还在养精蓄锐 (懒床)
    中午便是一天的开始
    下午又能干嘛 (摆烂一下午)
    晚上呢 (继续摆烂)
    你说这一周能过得不快吗 🤔

    文章系列

    注: 本系列文章源码基于 Android 11-r21 master 分支

    Warm-up

    源码阅读可是一项耗时、费力的‘大工程’,对于大多数人来说可能是多么的枯燥无味,为了消除枯燥感,尝试接触新鲜事物可是一个良好的治疗药方,前三篇都是在看 Android 启动,现在不妨在下一次开始之前看看别的东西 ——— package,看看这里面都是些什么?

    package

    对于系统应用就就不过多展开,这种更适合当前从事应用开发的同学,我们就挑拣几个感兴趣的模块稍微展开。

    packages 
        —— apps           系统应用
            —— basicSmsReceiver
                1.1 注册一个广播接收器 sms reciever,接受回调中通过解析 intent -> bundle -> puts 获得短信数据
                1.2 收到的每一条短信都需要一个唯一的通知ID,notificationId(先猜测这是通知渠道ID),通知点击事件将通过 pendingIntent 跳转到短信内容页面
                1.3 这个通知ID使用 SP 存储,下一次接收到通知时候自增,最大值不能超过最大阈值 32765(超过将重置)
    
            —— bluetooth 
                1.1 蓝牙实现还是比较底层的,最终会接触到硬件设备,那么这里需要 jni 调用,此前需要初始化 native
                1.2 蓝牙数据使用 room 框架做数据的 CURD 操作,主要数据是蓝牙地址、上一次激活时间
                1.3 设备管理,负责监听设备和蓝牙之间的连接、断开事件
                1.4 蓝牙服务是由多个子服务、通讯规范整合形成的,比如我们知道的有:蓝牙音频传输协议服务(A2PD)、音量控制服务、音视频远程控制规范(AVRCP)等等
                1.5 蓝牙是如何通讯的?a2dp —— a2dpshink 简单理解是 C——S 通讯(物联网应该接触到比较多,我们就略过吧)
                1.6 关键代码还是在 jni,这里就不展开了
    
            —— browser2
                1.1 【略】一个用于测试的 webview,构建生产环境使用的浏览器请参考链接;浏览器可又是一个大型项目——Chromium
    
            —— calendar
                1.1 好家伙,此模块用 kotlin 写,差点看不懂了 kt 的语法了解的还是太少,不影响我们粗略阅读
                1.2 日历除了看日期基本功能,还有其他的附加功能,比如闹钟提醒需要 AlarmScheduler,事件通知需要 notification
                1.3 日历在此前是我们遇到的第一个 UI 界面比较多的应用,对于应用开发者来说看看官方如何实现‘日历’可有一定参考;如何巧用列表控件、数据适配器。
     
            —— camera2
                1.1 相机主要的是图片,图片到底就是像素——一个多维的字节数组,对图片的处理最终既是对每一个像素的处理、转变,实际处理还是在 native
                1.2 【略】主要涉及对图片和音频的处理,如果当前从事相关开发我觉得可以继续往下看看,目前先略过(主要是代码不少啊😭)
    
            —— car
            —— carrierConfig
            —— cellBroadcastReceiver
            —— certInstaller
            —— contacts
            —— deskClock
            —— DevCamera
            —— dialer
            —— documentUI
            —— emergencyInfo
            —— Gallery2
            —— Gallery
            —— HTMLViewer
            —— keyChain
            —— Launcher3 【重点!重点!重点!】
                1.1 桌面应用,不就是我们看到的手机桌面嘛!看名称是 Launcher3 这个是原声系统的,如果你在友商手机看,这个名字可能是 ******.Launcher;
                    原生的桌面应用可能太丑了,厂商通常都会开发自己的桌面应用程序,美化桌面,吸引用户————爱美之心。
                1.2 看 Androidmanifest 只有一个activity,便是桌面程序的主界面 com.android.launcher3.Launcher,这是一个可以拖拽的、有状态的 activity
                1.3 UI 界面我们不关心如何,关注的是应用数据 AppInfo 来源,数据是如何获取到的?数据都包含了哪些内容(应用程序直接找 model 模块——MVC、MVVM、MVP)?
                    ——【ItemInfo】 
                        ID:每一条数据在数据库的ID  
                        type:应用程序、文件夹、部件、自定义部件、快捷方式
                        screenID:桌面ID,比如应用在桌面快速启动可以通过这个ID找到对应的应用程序启动数据
                        cellX/Y:坐标(桌面可以看作是一个二维网格)
                        title:最明显的应用图标或者文件夹名称、文件名称(桌面程序不仅仅是我们理解的那个只有只用应用图标的桌面)
                        componentName:这个就比较重要了,通常携带目标界面的启动类和必要数据
                        userHandle:通过 framework/base/core/java/android/os/Process 的 myUserHandle 方法赋值;
                                    userHandle —— 当前进程的用户句柄,系统缓存的实例,是在 zygote 进程中被创建。
                                    user 即是用户,这里的用户划分是什么:系统用户、所有用户、当前活动用户(大概意思就是根据 uid 获取特定的当前进程合适的 handle 来发送消息)
    
                        ——【FloderInfo】
                            lableState:标签
                            workspaceItemInfo:工作目录下可启动的应用程序(父类是 ItemInfoWithIcon)
    
                        ——【LauncherAppWidgetInfo】
                            intent:
                            compotentName:能够启动的,基本都包含着两个
    
                        ——【ItemInfoWithIcon】 
                            bitmap:作为应用程序,应用图标必不可少
                            process:应用下载进度,最大 100
                            ——【AppInfo】
                                intent:启动程序的常规方式就是通过 intent
                            ——【PackageItemInfo】
                                packagename:应用层开发者也知道 Android 在应用层有提供通过包名启动程序的接口
                  
                1.4 说到底,数据从那里来?【重点!这才是本次真正关注的点】
                    packages/apps/Launcher3/src/com/android/launcher3/model/LoaderTask.java 就是线程需要执行的任务;直接看 run 方法,加载任务大概做了这些事:
                    1.4.1 loadWorkspace:默认从当前应用收藏夹 favorites uri 通过 contentResolve 解析数据(数据解析部分有点复杂不展开了)
                    1.4.2 loadAllApps:需要的数据是 LauncherActivityInfo,实际获取数据的转到了 frameworks/base/core/java/android/content/pm/LauncherApps.java;
                          这是一个 AIDL 接口,ILauncherApps.aidl 实现类是 LauncherAppsService;获取到的事 resolveInfo 再通过 convertToActivitList 获得最终数据
                         (流程比较长点到为止,其实就是查询应用信息在组装转换为最后需要的)
    		1.4.3 loadDeepShortcuts: shortcut 快捷方式;通过 usermanager getUserProfiles 解析获得
                         (framework/base/core/java/android/os/UserManager.java),实际上就是当前进程的 UserHandle
    		1.4.4 widgetsModel.update(mApp, null):从应用中更新或者解析创建桌面部件
    
    /*到这里,桌面需要显示的应用信息已经获得,后面就是通过适配器把数据填充、显示,最后就是我们能看到的设备桌面*/
    
            —— legacyCamera
            —— managedProvisioning
            —— messaging
            —— music
            —— musicFX
            —— nfc
            —— onDeviceAppPrediction
            —— oneTimeInitializer
            —— phoneCommon
            —— protips
            —— provision
            —— quickAccessWallet
            —— quickSearchBox
            —— safetyRegulartoryInfo
            —— sampleLocationAttribution
            —— secureElement
            —— settings
            —— settingsIntelligence
            —— soundRecorder
            —— stk
            —— storageManager
            —— tag
            —— terminal
            —— themepicker
            —— timeZoneData
            —— TimeZoneUpdate
            —— traceur 
            —— tv
            —— tvSettings
            —— universalMediaPlayer
            —— wallpaperPicker
            —— wallpaperPicker2
        
        —— inputmethods   输入法
    
        —— modules
    
        —— providers      数据来源(其实就是对操作数据库,只是 CURD 操作系统封装为内容提供者——contentprovider,有一部分系统应用的数据源内容提供者,比如:联系人、日历)
            —— blocedNumberProvider   被屏蔽的电话提供者(数据库:blockednumbers.db)
            —— bookmarkProvider       书签提供者(一看代码无任何实现,留着估计是为了兼容考虑)
            —— calenderProvider       日历(数据库:calender.db;包含日历闹钟提醒、日历信息更新等)
            —— contactsProvider       联系人
            —— downloadProvider       接收器——通过系统广播接受,通知——notificationManager,扫描——mediaScannerConnectionClient,
                                      存储——fileSystemProvider,线程——发起下载请求、文件磁盘持久化
                                     (数据库:downloads.db;JobService——特定条件下执行的后台服务,比如:下载并安装完毕需删除安装包,删除的不仅是安装包文件还有数据库中的记录)
            —— mediaProvider          多媒体(媒体访问往往需要权限,提供音频播放、图片视频选择界面)
            —— partnerBookmarksProvider 合作伙伴书签?不太了解
            —— telephonyProvider      电话(运营商信息:CarrierInformation.db   运营商标识:carrierIdentification.d   短信内容:mmssms.db  电话内容:telephony.db)
            —— tvProvider             电视(机顶盒?  数据库:tv.db)
            —— userDictionaryProvider 用户字典
    
        —— screensavers   屏保
            —— basic          基础工具(只有一个颜色选择)
            —— phototable     界面 activity、数据源 source、适配器 adapter
    
        —— services
            —— alternativeNetworkAccess  网络相关
            —— builtinPrint              打印服务
            —— car                       车载服务
            —— mms                       多媒体消息(multimedia messaging service)
            —— mtp                       媒体传输协议(media transfer protocol)
            —— telecomm                  通讯工具
                —— bluetooth       蓝牙
                —— callfiltering   电话过滤
                —— callrederiction 电话重定向
            —— telephone                 电话服务
    
        —— wallpapers     壁纸
            —— live wallpapers           实时壁纸
    
    • 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
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154

    附加

    参考链接

    • A2PD:Advanced Audio Distribution Profile 蓝牙音频传输模型规范
    • AVRCP:Audio/Video Remote Control Profile 音视频远程控制规范
    • 浏览器:https://www.chromium.org/developers/how-tos/android-build-instructions
    • Chromium:https://github.com/chromium/chromium
  • 相关阅读:
    Linux 操作系统启动流程1
    WPF如何实现应用程序托盘
    react-redux的connect函数实现
    数字人直播系统源码交付,数字人直播软件下载迎来普及化
    解决navicat premium连接数据库自动断开问题
    Java计算机毕业设计大学生社团管理系统源码+系统+数据库+lw文档
    浅谈 Raft 分布式一致性协议|图解 Raft
    就在刚刚这份java八股文成功让我进入字节,拿到了人生第一个18k
    linux后台执行命令:nohup
    Java SE 7将于7月退役
  • 原文地址:https://blog.csdn.net/printf123scanf/article/details/126459284