Android M Dialer完全总结

本文详细总结了Android M Dialer的架构和功能,包括Dialer的UI设计、拨号盘实现、设置选项以及数据获取过程。通过对源码的分析,揭示了Dialer在双卡拨号、快速拨号、设置页面和CallLog数据获取方面的实现原理。同时探讨了代码细节,如组合模式和异步设置TextWatcher。文章还建议改进设置页面的设计,并对比了国内外UI设计的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

作为Dialer Owner,作一下基于M版本的总结吧。
在线源码阅读:http://androidxref.com

总体轮廓

手机之所以被称为手机,是因为它是一个通讯工具,而完成这一核心功能的软件模块,即为Telephony。
Telephony包含的范围非常广泛,单拿上层来说,大致可以划分成五大部分:Telephony应用(DialerContactsMms),service Telephony和service Telecomm,framework Telephony和framework Telecomm。
现在这一架构的主要变化是从L版本开始的,相较旧版的主要变迁可以参考:Android 4.4 Kitkat Phone工作流程浅析(十二)__4.4小结与5.0概览


图片资料

本文只关注Dialer,那么先看几张Nexus 6p的实机截图来个感性的认识:

Dialer_示例1
Dialer_示例2
Dialer_示例3


架构分析

Dialer主要涉及的包有:
1)/packages/apps下
DialerInCallUIContactsCommonPhoneCommonVoiceDialer

凭借makefile,分包可以非常的自由随意,看如下片断:

6incallui_dir := ../InCallUI
7contacts_common_dir := ../ContactsCommon
8phone_common_dir := ../PhoneCommon
9
10src_dirs := src \
11    $(incallui_dir)/src \
12    $(contacts_common_dir)/src \
13    $(phone_common_dir)/src

DialerInCallUIPhoneCommonContactsCommon全都在src_dirs路径下了,于是最终的Dialer.apk由这四个包下的代码编译生成。

VoiceDialer提供语音相关功能,入口看下图:

VoiceDialer

但是,此功能侵略性过强,在天朝是基本残废的,在海外多数运营商也不喜欢表示要去除,所以不予关注。

2)/packages/services下
MmsTelephonyTelecomm,生成MmsService.apk,Telecom.apk与TeleService.apk,对Dialer来说是提供通话菜单功能的。
应该说不管从逻辑还是物理上,切分出来都是大有好处,这样才能让Android能够良好支持第三方通讯类应用。

3)/packages/providers下
TelephonyProviderContactsProvider,数据创建及查询,当然也是要切分的部分。

4)frameworks/opt和frameworks/base下
telephony等和上面类似的眼熟名字,具体关系到各种功能点如MmiCode,Clear Code,Number match,Number format,DTMF,FDN等等等等。


具体分析

看完整体架构之后,单单一个Dialer包的定位也变得很清晰了:它就只是一个拨号器而已。

1.层次结构

Dialer的UI是否美观是个见仁见智的问题,我个人还是挺喜欢的。

这里我们只谈其实现原理。
这是Dialer的主layout dialtacts_activity.xml:

16<FrameLayout
17    xmlns:android="http://schemas.android.com/apk/res/android"
18    android:id="@+id/dialtacts_mainlayout"
19    android:layout_width="match_parent"
20    android:layout_height="match_parent"
21    android:orientation="vertical"
22    android:focusable="true"
23    android:focusableInTouchMode="true"
24    android:clipChildren="false"
25    android:background="@color/background_dialer_light">
26
27    <FrameLayout
28        android:id="@+id/dialtacts_container"
29        android:layout_width="match_parent"
30        android:layout_height="match_parent"
31        android:clipChildren="false">
32        <!-- The main contacts grid -->
33        <FrameLayout
34            android:layout_height="match_parent"
35            android:layout_width="match_parent"
36            android:id="@+id/dialtacts_frame"
37            android:clipChildren="false" />
38    </FrameLayout>
39
40    <FrameLayout
41        android:id="@+id/floating_action_button_container"
42        android:background="@drawable/fab_blue"
43        android:layout_width="@dimen/floating_action_button_width
<think>好的,用户想在Android系统中更改通话界面的壁纸。首先,我需要回忆一下Android开发中自定义系统界面相关的知识。根据之前看到的引用内容,比如引用[1]和[2]提到使用WindowManager、BroadcastReceiver和Service来实现自定义来电界面,这可能涉及到监听来电广播,然后显示自定义的布局。不过用户的问题更具体,是要更改通话界面的壁纸,而不是完全自定义整个界面。 接下来,我需要确定系统通话界面是否允许直接修改壁纸。通常来说,系统通话界面属于系统应用,比如Dialer应用,普通应用没有权限直接修改其资源。所以可能需要通过其他方式,比如覆盖层或者动态修改布局。 根据引用[1]中的例子,当有电话进来时,通过BroadcastReceiver检测来电,然后启动Service使用WindowManager添加自定义视图。或许用户可以通过类似的方法,在检测到来电时显示一个半透明的背景图片,覆盖在系统通话界面之上,从而达到更改壁纸的效果。不过需要注意权限问题,比如SYSTEM_ALERT_WINDOW权限,并且在较新的Android版本中可能需要用户手动授权。 另外,引用[3]提到通过反射调用TelephonyManager的方法,但这种方法可能不稳定,并且需要系统级权限,不适合普通应用。因此,可能更推荐使用WindowManager的方法。 还需要考虑不同Android版本的兼容性,尤其是Android 8.0以后对后台服务的限制,可能需要使用前台服务来保持Service的运行。同时,来电号码的获取可能需要READ_PHONE_STATE权限,并且需要在AndroidManifest.xml中声明,动态请求这些权限。 总结步骤可能是:监听来电状态,获取来电事件,启动服务,添加带有自定义壁纸的View到WindowManager。需要注意的是,这种方法可能无法完全替换系统默认的壁纸,而是以悬浮层的形式覆盖,可能存在遮挡其他UI元素的风险,需要调整布局的透明度或位置。 此外,用户可能需要处理去电界面,同样需要监听拨号事件,执行类似的操作。测试时需要考虑不同设备和系统版本的差异,以及权限获取的正确性。 最后,生成相关问题时要围绕自定义界面、权限处理、兼容性等方面,帮助用户深入理解相关技术点。</think>### 分步实现Android通话界面壁纸自定义 #### 1. 监听通话状态 通过`TelephonyManager`监听通话状态变化,使用`PhoneStateListener`捕获来电/去电事件: ```java public class CallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); tm.listen(new PhoneStateListener() { @Override public void onCallStateChanged(int state, String phoneNumber) { if (state == TelephonyManager.CALL_STATE_RINGING) { // 启动悬浮窗服务 startWallpaperService(context); } else if (state == TelephonyManager.CALL_STATE_IDLE) { // 关闭悬浮窗 stopWallpaperService(context); } } }, PhoneStateListener.LISTEN_CALL_STATE); } } ``` #### 2. 创建悬浮窗服务 使用`WindowManager`添加半透明背景层: ```java public class WallpaperService extends Service { private WindowManager windowManager; private View overlayView; @Override public void onCreate() { windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建壁纸布局 overlayView = LayoutInflater.from(this).inflate(R.layout.wallpaper_overlay, null); ImageView wallpaper = overlayView.findViewById(R.id.wallpaper_image); wallpaper.setImageResource(R.drawable.custom_wallpaper); wallpaper.setAlpha(0.7f); // 设置透明度 // 窗口参数配置 WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, // Android 8.0+要求 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSLUCENT ); windowManager.addView(overlayView, params); } @Override public void onDestroy() { if (overlayView != null) { windowManager.removeView(overlayView); } } } ``` #### 3. 权限配置 在`AndroidManifest.xml`中添加必要权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <service android:name=".WallpaperService" android:enabled="true" android:exported="false"/> ``` #### 4. 动态权限申请 在Activity中请求运行时权限: ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!Settings.canDrawOverlays(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); startActivity(intent); } } ``` ### 技术要点说明 1. **悬浮窗类型**:Android 8.0+必须使用`TYPE_APPLICATION_OVERLAY` 2. **布局层级**:通过设置`FLAG_NOT_FOCUSABLE`避免影响通话按钮操作 3. **壁纸适配**:建议使用`.9.png`格式图片适配不同屏幕 4. **性能优化**:使用轻量级图片资源,避免内存泄漏 ### 效果示意图 ```plaintext [系统通话界面] +---------------------------+ | [自定义半透明壁纸背景] | | +-------------------+ | | | 系统默认通话控件 | | | | 接听按钮 挂断按钮 | | | +-------------------+ | +---------------------------+ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值