如何通过代码批量添加号码至手机并标记为已拦截?
问题描述
我正在开发一款应用,用于将1800+团队成员收到的垃圾及诈骗号码添加到手机中并标记为拦截状态,以便在团队内共享使用避免骚扰。目前已实现从文件导入号码至通讯录,但无法完成标记拦截的操作,以下是添加联系人的代码片段:
import android.Manifest; import android.content.ContentProviderOperation; import android.content.ContentValues; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.BlockedNumberContract; import android.provider.ContactsContract; import android.util.Log; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { private static final int READ_CONTACTS_PERMISSION_REQUEST = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Request READ_CONTACTS and WRITE_CONTACTS permissions if not granted if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS}, READ_CONTACTS_PERMISSION_REQUEST); } else { addBlockedNumbersToContacts(); } } private void addBlockedNumbersToContacts() { try { InputStream inputStream = getAssets().open("numbers.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); ArrayList<String> blockedNumbers = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { String normalizedNumber = line.trim(); if (!normalizedNumber.isEmpty()) { blockedNumbers.add(normalizedNumber); } } reader.close(); for (String number : blockedNumbers) { // Add the number to contacts with a custom label "Blocked" addNumberToContacts(number, "Blocked"); } } catch (IOException e) { e.printStackTrace(); } } private void addNumberToContacts(String phoneNumber, String label) { // Prepare the contact values ArrayList<ContentProviderOperation> ops = new ArrayList<>(); int rawContactInsertIndex = ops.size(); ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null) .build()); // Add the phone number to the contact data with the custom label ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactInsertIndex) .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, label) .build()); try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); Log.d("Contact", "Number added to contacts: " + phoneNumber); } catch (Exception e) { e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == READ_CONTACTS_PERMISSION_REQUEST) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { addBlockedNumbersToContacts(); } else { } } } }
实现号码拦截标记的方案
Android系统提供BlockedNumberContract API来管理系统级拦截号码,你可以基于现有代码扩展实现拦截功能,具体步骤如下:
1. 添加必要权限
除了现有通讯录权限,还需在AndroidManifest.xml中声明拦截号码的权限:
<uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS" /> <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" />
注意:WRITE_BLOCKED_NUMBERS权限在Android 7.0(API 24)及以上需要动态申请,需和通讯录权限一起处理。
2. 更新权限申请逻辑
修改onCreate和onRequestPermissionsResult方法,加入拦截权限的申请判断:
private static final int PERMISSION_REQUEST_CODE = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] requiredPermissions = { Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_BLOCKED_NUMBERS, Manifest.permission.WRITE_BLOCKED_NUMBERS }; boolean allPermissionsGranted = true; for (String perm : requiredPermissions) { if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (!allPermissionsGranted) { ActivityCompat.requestPermissions(this, requiredPermissions, PERMISSION_REQUEST_CODE); } else { addBlockedNumbersToContactsAndBlock(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSION_REQUEST_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (allGranted) { addBlockedNumbersToContactsAndBlock(); } else { // 处理权限被拒绝的情况,比如弹窗提示用户开启必要权限 } } }
3. 新增拦截号码的方法
添加专门用于拦截号码的工具方法,处理系统拦截逻辑:
private boolean blockPhoneNumber(String phoneNumber) { ContentValues values = new ContentValues(); values.put(BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER, phoneNumber); // 可选:标准化号码为E164格式(如+8613xxxxxxxxx),提升拦截准确性 values.put(BlockedNumberContract.BlockedNumbers.COLUMN_E164_NUMBER, normalizePhoneNumber(phoneNumber)); try { Uri insertedUri = getContentResolver().insert(BlockedNumberContract.BlockedNumbers.CONTENT_URI, values); return insertedUri != null; } catch (SecurityException e) { Log.e("BlockNumber", "拦截号码失败: " + phoneNumber, e); return false; } } // 可选:标准化号码格式,去除非数字字符并添加国家码(根据实际需求调整) private String normalizePhoneNumber(String number) { String cleanNumber = number.replaceAll("[^0-9]", ""); // 假设国内号码,自动添加+86前缀 if (cleanNumber.startsWith("1") && cleanNumber.length() == 11) { return "+86" + cleanNumber; } return cleanNumber; }
4. 修改导入流程,同时完成添加联系人与拦截
更新原有的导入方法,在添加联系人后调用拦截方法:
private void addBlockedNumbersToContactsAndBlock() { try { InputStream inputStream = getAssets().open("numbers.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); ArrayList<String> blockedNumbers = new ArrayList<>(); String line; while ((line = reader.readLine()) != null) { String normalizedNumber = line.trim(); if (!normalizedNumber.isEmpty()) { blockedNumbers.add(normalizedNumber); } } reader.close(); for (String number : blockedNumbers) { // 先添加到通讯录 addNumberToContacts(number, "Blocked"); // 再标记为拦截 boolean isBlocked = blockPhoneNumber(number); Log.d("BlockStatus", "号码 " + number + " 拦截状态: " + isBlocked); } } catch (IOException e) { e.printStackTrace(); } }
额外注意事项
- 系统版本限制:
BlockedNumberContract仅支持Android 7.0(API 24)及以上设备,低于该版本的设备需要采用替代方案,比如调用系统拦截Intent或依赖第三方安全应用接口。 - 重复拦截检查:可以先查询号码是否已被拦截,避免重复操作:
private boolean isNumberBlocked(String phoneNumber) { String selection = BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER + " = ?"; String[] selectionArgs = {phoneNumber}; try (var cursor = getContentResolver().query(BlockedNumberContract.BlockedNumbers.CONTENT_URI, null, selection, selectionArgs, null)) { return cursor != null && cursor.getCount() > 0; } }
- 性能优化:批量处理1800+号码时,建议使用异步任务(如
Coroutine)避免阻塞主线程,提升应用流畅度。
内容的提问来源于stack exchange,提问作者curious07
相关产品推荐
相关产品推荐

