【PR系列之001-1101288】Android 5.0 contacts 添加帐号时选择帐号后闪现“Choose an account”

本文分析了Android中选择帐号Activity的问题,详细解释了ChooseTypeAndAccountActivity与ChooseAccountTypeActivity的工作原理及交互流程,针对5.0版本中存在的“Choose an account”闪现问题给出了根本原因及解决方案。

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

经分析得出结果为:

点击添加帐号后,会同时创建两个Activity,分别是ChooseTypeAndAccountActivity和ChooseAccountTypeActivity,前者CTAAA通过startChooseAccountTypeActivity()方法瞬间启动CATA,所以与用户交互的列出选择帐号的Activity为后者CATA,但是5.0中startChooseAccountTypeActivity()方法写到了resume()方法中,当CATA界面选择帐号后会执行finish()方法,然后CTAAA会执行resume ()方法,所以会再次执行startChooseAccountTypeActivity()方法,也就是此时又重新创建了一个CATA Activity,导致闪现“Choose an account”,在Android M中Google把5.0中onresume中的内容写到了onCreat方法里面,并删除了onresume方法,如此一来问题即可解决。


frameworks/base/core/java/android/accounts/ChooseTypeAndAccountActivity.java

frameworks/base/core/java/android/accounts/ChooseAccountTypeActivity.java

<think>我们正在处理一个关于Android11中如何添加联系人并选择存储到SIM卡的问题。根据提供的引用信息,我们可以了解到一些背景:-引用[1]提到Mtk平台实现了开机自动导入SIM卡联系人,并且数据库中通过`indicate_phone_or_sim_contact`字段区分SIM卡联系人以及SIM1和SIM2。同,SimContacts类负责显示SIM卡联系人并与用户交互,AdnList负责与SIM卡交互。-引用[2]展示了如何通过ContentResolver查询联系人信息(虽然这里是获取电话号码,但表明我们使用ContentResolver操作联系人数据)。-引用[3]解释了联系人数据模型:一个账号(account)拥有自己的原始联系人(rawcontacts),每个rawcontact包含多个数据项(如电话、邮箱等)。-引用[4]详细描述了data表的结构,该表存储了联系人的具体数据,如电话号码等,并且通过raw_contact_id与raw_contacts表关联。然而,Android官方API并没有提供直接向SIM卡添加联系人的方法。从历史上看,操作SIM卡联系人需要特定的系统权限(如`android.permission.WRITE_CONTACTS`)以及使用特定的Uri。在较新的Android版本中,由于安全性和厂商定制的原因,向SIM卡写入联系人的API可能被隐藏或需要特殊处理。在Android11中,要添加联系人并选择存储到SIM卡,我们可能需要考虑以下步骤:1.**检查SIM卡状态和权限**:确保设备有有效的SIM卡,并且应用具有必要的权限(例如`READ_CONTACTS`、`WRITE_CONTACTS`,以及可能的`WRITE_EXTERNAL_STORAGE`,但注意在Android11中存储权限有所变化)。2.**使用特定的Uri操作SIM卡联系人**:根据引用[1],我们可以推测操作SIM卡联系人可能需要使用特定的内容提供者(ContentProvider)。通常,SIM卡联系人的Uri是`content://icc/adn`(或者对于双卡,可能会有不同的Uri,如`content://icc0/adn`和`content://icc1/adn`)。但请注意,这些Uri在官方API中通常没有文档说明,并且可能因设备制造商不同而有所变化。3.**构建联系人数据**:根据引用[3]和[4],联系人数据由多个部分(rawcontacts)组成,每个部分包含多个数据项(如姓名、电话号码等)。对于SIM卡联系人,通常只存储姓名和电话号码(可能还有一条备注),因为SIM卡的存储能力有限。4.**插入操作**:使用ContentResolver的insert方法,传入正确的SIM卡联系人Uri,并构建ContentValues对象,包含姓名和电话号码等信息。但是,由于Android官方对SIM卡操作的限制,这种方法可能不适用于所有设备,特别是非系统应用可能无法使用这些Uri。因此,另一种可能的做法是使用系统提供的Intent,让用户通过系统自带的联系人应用来添加联系人到SIM卡。**替代方案**:启动系统联系人应用的添加联系人界面,并提示用户选择存储位置(SIM卡或手机)。但系统联系人应用是否提供选择存储位置以及是否支持SIM卡存储,取决于设备制造商和系统版本。由于直接使用Uri`content://icc/adn`可能不被官方支持,且需要系统权限,因此对于普通应用来说,最可靠的方法可能是通过Intent调用系统联系人应用,并希望它提供存储位置选项。然而,我们也可以尝试使用反射来访问隐藏的API,但这可能导致应用无法在应用商店上架,并且不稳定(不同设备、不同Android版本可能失效)。**总结**:在Android11中,对于非系统应用,直接向SIM卡添加联系人的官方API不可用。建议通过系统联系人应用添加,并让用户选择存储位置。以下是两种可能的解决方案:###方案1:通过隐式Intent启动系统联系人添加界面(不保证所有设备都支持选择SIM卡)```javaIntentintent=newIntent(Intent.ACTION_INSERT);intent.setType(ContactsContract.Contacts.CONTENT_TYPE);//尝试添加额外信息(姓名和电话号码)intent.putExtra(ContactsContract.Intents.Insert.NAME,"联系人姓名");intent.putExtra(ContactsContract.Intents.Insert.PHONE,"123456789");startActivityForResult(intent,REQUEST_CODE_ADD_CONTACT);```当用户使用系统联系人应用添加联系人,有些设备的系统联系人应用会询问存储位置(手机内部存储或SIM卡)。但这不是所有设备都支持。###方案2:直接操作SIM卡联系人(需要系统权限,适用于系统应用或root设备)如果您的应用是系统应用(具有系统签名和sharedUserId),可以尝试使用以下代码:```java//对于单卡设备(或第一张SIM卡)UrisimUri=Uri.parse("content://icc/adn");ContentValuesvalues=newContentValues();values.put("tag","联系人姓名");//姓名字段values.put("number","123456789");//电话号码字段getContentResolver().insert(simUri,values);```对于双卡设备,可能需要使用`content://icc0/adn`(第一张卡)和`content://icc1/adn`(第二张卡)。然而,这些字段名("tag"和"number")是隐藏的,在官方API中没有暴露。此外,在Android11中,由于权限更严格,普通应用无法访问这些Uri。###结论对于普通应用开发者,建议使用方案1(隐式Intent),让用户自行选择存储位置。如果必须由应用控制存储位置(例如企业应用场景),可能需要与设备制造商合作,使用特定的SDK或API。由于上述操作具有平台差异性,请在实际设备上测试。§§相关问题§§1.Android11中如何检测SIM卡的存在和状态?2.Android11中如何读取SIM卡上的联系人?3.哪些Android设备制造商提供了向SIM卡写入联系人的API?4.Android开发中,如何获取系统权限(系统签名)?</think> ### Android 11 添加联系人到SIM卡的实现指南 在Android 11中添加联系人到SIM卡需要特殊处理,因为官方Contacts API不直接支持SIM卡存储操作。以下是具体实现方案: #### 核心实现步骤 1. **权限声明** 在`AndroidManifest.xml`添加: ```xml <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> ``` 2. **SIM卡联系人URI确定** ```java // 单卡设备 Uri SIM_URI = Uri.parse("content://icc/adn"); // 双卡设备 (需适配不同厂商) Uri SIM1_URI = Uri.parse("content://icc0/adn"); // SIM1 Uri SIM2_URI = Uri.parse("content://icc1/adn"); // SIM2 ``` 3. **插入SIM卡联系人** ```java public void addContactToSim(String name, String phoneNumber, int slotId) { ContentValues values = new ContentValues(); values.put("tag", name); // 姓名字段 values.put("number", phoneNumber); // 号码字段 Uri simUri = (slotId == 0) ? SIM1_URI : SIM2_URI; try { getContentResolver().insert(simUri, values); Toast.makeText(this, "SIM卡联系人添加成功", Toast.LENGTH_SHORT).show(); } catch (Exception e) { Log.e("SIM_CONTACT", "添加失败: " + e.getMessage()); } } ``` #### 关键注意事项 1. **设备兼容性问题** - 不同厂商(MTK/高通)URI路径可能不同,如: - 三星设备可能使用 `content://sim/adn` - 华为设备可能使用 `content://com.android.contacts/sim` 2. **系统权限限制** - 需要应用拥有**系统签名**(`android:sharedUserId="android.uid.system"`) - 普通应用需要通过**ADB命令**授权权限: ``` adb shell pm grant your.package.name android.permission.WRITE_CONTACTS ``` 3. **字段映射** - SIM卡仅支持基础字段(参考`AdnRecord`类): | 字段名 | 含义 | 最大长度 | |----------|--------------|----------| | `tag` | 联系人姓名 | 40字符 | | `number` | 电话号码 | 20字符 | #### 完整流程示例 ```java // 检查SIM卡状态 SubscriptionManager subMgr = getSystemService(SubscriptionManager.class); if (subMgr.getActiveSubscriptionInfoCount() == 0) { Toast.makeText(this, "无可用SIM卡", Toast.LENGTH_SHORT).show(); return; } // 获取SIM槽位信息 int targetSlot = 0; // 默认SIM1 List<SubscriptionInfo> subs = subMgr.getActiveSubscriptionInfoList(); if (subs.size() > 1) { // 显示SIM卡选择对话框 showSimSelectorDialog(subs); } else { // 添加联系人 addContactToSim("张三", "13800138000", targetSlot); } ``` #### 备选方案(官方推荐) 如果无法获取系统权限,可通过系统联系人应用间接实现: ```java Intent intent = new Intent(Intent.ACTION_INSERT); intent.setType(ContactsContract.Contacts.CONTENT_TYPE); intent.putExtra(Intents.Insert.EXTRA_PHONE_TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); intent.putExtra(Intents.Insert.PHONE, "13800138000"); intent.putExtra("com.android.contacts.extra.ACCOUNT_TYPE", "SIM"); // 厂商特定参数 startActivity(intent); ``` ### 重要说明 - ⚠️ Android 11对SIM卡操作增加了限制,普通应用只能**读取**SIM卡联系人 - 系统应用开发需参考厂商SDK(如MTK的`Telephony`扩展API[^1]) - SIM卡存储容量有限(通常≤500条),建议优先使用手机存储
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值