自己写的Android Contacts操作类,以后还会补充

本文介绍了如何在Android系统中通过API操作与查找联系人,包括添加、删除保持状态的联系人,以及根据ID和电话号码获取联系人信息。

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.Contacts;
import android.provider.ContactsContract;

@SuppressWarnings("deprecation")
public class ContactsUtil {
 private static final int REMOVE = 0;
 private static final int ADD = 1;
 Context context;
 public ContactsUtil(Context context){
  this.context = context;
 }
 
 public Boolean addKeepedContacts(long _id){
  int apiLevel = Build.VERSION.SDK_INT;
  if(apiLevel > 7){
   return addOrRemoveKeepedContactsInHighSDK(_id, ContactsUtil.ADD);
  }else{
   return addOrRemoveKeepedContactsInLowSDK(_id, ContactsUtil.ADD);
  }
 }
 
 public Boolean removeKeepedContacts(long _id){
  int apiLevel = Build.VERSION.SDK_INT;
  if(apiLevel > 7){
   return addOrRemoveKeepedContactsInHighSDK(_id, ContactsUtil.REMOVE);
  }else{
   return addOrRemoveKeepedContactsInLowSDK(_id, ContactsUtil.REMOVE);
  }
 }
 
 private Boolean addOrRemoveKeepedContactsInLowSDK(long _id, int flag){
  ContentResolver contentResolver = this.context.getContentResolver();
  Cursor cusor = null;
  String[] projection = new String[] { Contacts.People._ID, Contacts.People.NAME, Contacts.People.NUMBER };
  cusor = contentResolver.query(Contacts.People.CONTENT_URI, projection, Contacts.People._ID + "=?", new String[] { _id + "" }, Contacts.People.NAME + " ASC");
     cusor.moveToFirst();
  ContentValues values = new ContentValues();
  Uri uri = Uri.withAppendedPath(Contacts.People.CONTENT_URI, cusor.getString(cusor.getColumnIndex(Contacts.People._ID)));
//  values.put(Contacts.People.NAME, newName);
  values.put(Contacts.People.STARRED, flag);
//  values.put(Contacts.Phones.NUMBER, newPhoneNum);
  int i = contentResolver.update(uri, values, null, null);
  return i == 1;
 }
 
 private Boolean addOrRemoveKeepedContactsInHighSDK(long _id, int flag){
  ContentValues contentValues = new ContentValues();
  contentValues.put(ContactsContract.Contacts.STARRED, flag);
  int i = this.context.getContentResolver().update(ContactsContract.Contacts.CONTENT_URI, contentValues, ContactsContract.Contacts._ID + " = ? ", new String[]{_id + ""});
  return i == 1;
 }
 
 /**
  * 根据ContactID得到电话号码

  * @param _id
  * @return
  */
 public String getPhoneNumbersByContactID(Long _id){
  Cursor cursor = context.getContentResolver().query(
    ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
                null, 
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" 
                + Long.toString(_id), null, null);
  //处理多个号码的情况

  String phoneNumber = "";
  while(cursor.moveToNext()){
   String strNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
   phoneNumber += strNumber + ":";
  }
  cursor.close();
  return phoneNumber;
 }
 
 /**
  *根据电话号码得到ContactsID 

  * @param phoneNumber
  * @return
  */
 public Long getContactIDByPhoneNumber(String phoneNumber){
  Cursor cursor = context.getContentResolver().query(
    ContactsContract.CommonDataKinds.Phone.CONTENT_URI, 
                null, 
                ContactsContract.CommonDataKinds.Phone.NUMBER + "=" 
                + phoneNumber, null, null);
  Long ContactID = 0l;
  while(cursor.moveToNext()){
   ContactID = cursor.getLong(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
  }
  cursor.close();
  return ContactID;
 }
 
 /**
  *根据电话号码,该电话号码加入收藏中 

 * @param phoneNumber
  * @return
  */
 public Boolean addKeepedContactsByPhoneNumber(String phoneNumber){
  //得到对应电话号码的contactID
  Long _id = getContactIDByPhoneNumber(phoneNumber);

 return addKeepedContacts(_id);
 }
 /**
  *根据电话号码,将该电话号码对应的联系人从收藏夹中移除
  * @param phoneNumber
  * @return
  */
 public Boolean removeKeepedContactsByPhoneNumber(String phoneNumber){
   Long _id = getContactIDByPhoneNumber(phoneNumber);
  return removeKeepedContacts(_id);
 }
}

<think>嗯,用户询问的是Android15系统中预加载的精简问题,这涉及到系统优化层面。用户可能正在开发定制ROM或进行深度系统优化,需要明确哪些预加载可以安全移除。 从技术角度看,Android系统预加载主要分布在三个层面:AOSP基础、GMS服务和OEM定制。其中AOSP基础如ActivityManagerService等绝对不能移除,否则会导致系统崩溃。GMS相关如GooglePlayServicesUtil在非谷歌设备上可考虑移除,但要注意依赖关系。OEM预装应用相关的如MiuiSystemUI是主要精简对象。 用户特别强调"安全移除",说明ta可能有过因误删导致系统不稳定的经历。需要重点提醒备份和测试流程,建议采用分批注释的方式验证。有趣的是用户提到"不需要"的,这暗示ta可能想最大限度精简系统,因此需要补充说明即使可移除的也可能影响特定功能。注意到引用内容中提到了ADB卸载和定制ROM两种方式,但用户问题聚焦在""级别而非应用层面,说明ta需要更底层的修改方案。RecyclerView的引用虽然不直接相关,但其缓存机制的设计思路可以借鉴到系统优化中——就像RecyclerView的多级缓存,系统预加载也可以分层处理。 需要警告的是Android15新引入的PrivacySandbox相关看似可删,实际会破坏广告API兼容性。另外ProjectMainline模块化设计使得某些看似独立实则存在动态依赖,这点必须重点说明。</think>在 Android 15 系统中识别哪些预加载可以安全移除或不必要,需要极其谨慎的操作和深入分析。主要可考虑移除的别包括: **一、 可考虑移除的预加载 (需严格验证)** 1. **特定 OEM / 运营商定制应用:** * **描述:** 手机厂商 (`OEM`) 或运营商 (`Carrier`) 预装的非必要应用(如推广应用、特定区域服务、品牌定制应用)。 * **示例前缀/包名:** `com.<oem_name>.<app_name>`, `com.<carrier_name>.<app_name>` (例如 `com.example.oem.bloatware`, `com.example.carrier.videoapp`)。具体名称因设备和地区而异。 * **风险:** 相对较低,但需确认该应用无底层系统依赖(如作为系统设置的入口)。移除前**务必备份**。 2. **过时或替代的 AOSP 应用:** * **描述:** Android 开源项目 (`AOSP`) 包含的基础应用,如果用户或 OEM 已用更优方案替代,其相关可能冗余。 * **示例:** 旧版 `Email` 应用(若使用 Gmail 或其他客户端)、旧版 `Browser` 应用(若使用 Chrome 或其他浏览器)、`BasicDreams`(基础屏保,若不用)。 * **风险:** 中等。需确认替代应用功能完整,且系统无隐藏依赖(如 Intent 处理)。移除前**充分测试**核心功能。 3. **特定 GMS 组件 (非核心/非必需):** * **描述:** Google 移动服务 (`GMS`) 中非核心或用户设备不需要的部分(主要在非谷歌设备或极度精简场景)。 * **示例:** `Play Movies & TV`, `Play Books`, `Play Games`, `Google+`(历史遗留), 特定区域服务(如 `WalletService` 在无支付需求地区)。**核心 GMS (如 GSF, Play Services 框架)绝对不可移除!** * **风险:** 高。可能导致依赖这些组件的其他应用(甚至系统应用)崩溃或功能缺失。**极度不推荐普通用户操作,仅限深度定制。** **二、 绝对不可移除的预加载 (移除将导致系统崩溃/无法启动/严重故障)** 1. **核心框架与服务:** * **描述:** Android 系统运行的基础。 * **示例:** `android.*` 包下关键框架 (`ActivityManagerService`, `PackageManagerService`, `WindowManagerService` 等), `SystemUI` 相关, `Telephony` 核心, `Wifi` 核心, `Bluetooth` 核心。 2. **关键 AOSP 应用:** * **描述:** 提供基本系统功能的应用。 * **示例:** `Settings` (设置), `Launcher` (桌面), `Dialer` (电话), `Contacts` (通讯录), `Messaging` (短信), `Camera2` (相机框架)。 3. **核心 GMS (如果设备预装 GMS):** * **描述:** Google 服务框架的核心。 * **示例:** `Google Services Framework (GSF)`, `Google Play Services` 核心库 (`com.google.android.gms.*` 中的基础部分), `AccountManager` 相关集成。 4. **硬件抽象层 (`HAL`) / 驱动相关:** * **描述:** 与设备硬件交互的接口。 * **示例:** `android.hardware.*` 包下的关键。 5. **启动器 (`Init`) 相关:** * **描述:** 系统启动过程必需的。 6. **ART 虚拟机核心:** * **描述:** 应用运行环境的核心。 **三、 识别与移除方法 (高风险!仅适用于开发者/高级用户)** 1. **分析预加载列表:** * 获取设备 `system.img` 或 `product.img` 等分区镜像。 * 解包镜像,检查 `/system/framework/`, `/system/app/`, `/system/priv-app/`, `/product/app/`, `/product/priv-app/` 等目录下的 APK/JAR 文件。 * 使用 `dexdump`, `baksmali/smali` 或 `jadx` 等工具反编译 APK/JAR,查看其包含的 (`classes.dex`, `classes2.dex`, ...)。 2. **依赖关系分析 (至关重要!):** * 检查 `AndroidManifest.xml`: 查看应用的 `<uses-library>` 声明、`<intent-filter>` 定义、`<permission>` 和 `<uses-permission>` 等,分析其依赖和被依赖关系。 * 代码分析: 查找对其他包名/名的显式引用 (如 `import` 语句, `Class.forName()` 调用)。 * 动态分析: 在修改后的系统上运行,使用 `logcat` 监控错误日志(尤其是 `ClassNotFoundException`, `NoClassDefFoundError`)。 3. **移除方法:** * **ADB 卸载 (临时,重启可能恢复):** 仅对非系统级应用有效,且需设备已 `root` 或启用 `ADB` 卸载系统应用权限。 ```bash adb shell pm uninstall -k --user 0 <package.name> ``` * **定制 ROM (永久):** 在编译 Android 15 源码时,修改 `makefile` (如 `device/<vendor>/<device>/device.mk` 或 `product makefiles`) 中 `PRODUCT_PACKAGES` 变量,移除对应应用的条目。这是**最彻底、最推荐**给开发者的方法[^1]。 * **直接删除系统分区文件 (高风险!):** 在已 `root` 的设备上,挂载 `/system` 分区为可 (`mount -o rw,remount /system`),删除对应的 APK/JAR/ODEX/VDEX 文件。**极易出错导致变砖!强烈不推荐。** **四、 重要警告与建议** * **备份!备份!备份!** 在进行任何操作前,完整备份系统和数据。 * **极高风险:** 移除系统预加载极易导致系统不稳定、功能失效、甚至无法启动(变砖)。 * **深度技术门槛:** 需要精通 Android 系统架构、`Linux`、`Java`、`ADB`、`ROM` 编译等。 * **充分测试:** 任何移除操作后,必须进行**全面**的功能测试和稳定性测试。 * **优先考虑非系统方法:** 对于普通用户,优先使用“禁用”功能 (`adb shell pm disable-user --user 0 <package.name>`) 或第三方工具冻结应用,这比移除更安全。 * **关注 Android 15 新特性:** Android 15 可能引入新的模块化设计或隐私沙盒相关,移除前需特别研究其作用。 **
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值