You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android:如何通过代码创建并保存联系人至SIM卡?代码存卡异常咨询

Hey there! Let's dive into your two Android SIM card contact questions—they're super common when dealing with SIM storage, so I've got you covered.

1. 如何通过代码创建联系人并保存至SIM卡?

Saving contacts to a SIM card relies on Android's ContentProvider for SIM storage, but there are a few critical steps to get right:

  • First, secure necessary permissions: You’ll need WRITE_CONTACTS and READ_CONTACTS permissions. For Android 6.0 (API 23) and above, you have to request these dynamically at runtime, not just declare them in the manifest.
  • Use the correct SIM content URI: The standard URI is content://icc/adn, but some manufacturers use variations (like content://sim/adn for certain devices). For dual-SIM phones, target a specific SIM by appending the subscription ID, e.g., content://icc/adn/subId/{subId}.
  • Build and insert contact data: Create a ContentValues object with the contact’s name (stored under the tag key) and phone number (under number), then use ContentResolver.insert() to add it to the SIM.
  • Handle exceptions: SIM operations can fail for various reasons (full storage, unsupported SIM, permission issues), so always wrap code in a try-catch block.

Here’s a basic implementation outline:

private const val PERMISSION_REQUEST_CODE = 1001

private fun requestPermissionsIfNeeded(context: Context) {
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(context as Activity, 
            arrayOf(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS), 
            PERMISSION_REQUEST_CODE)
    }
}

private fun addContactToSim(context: Context, number: String, name: String) {
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        Log.e("SimContact", "WRITE_CONTACTS permission not granted")
        return
    }
    try {
        val simUri = Uri.parse("content://icc/adn")
        val cv = ContentValues().apply {
            put("tag", name)
            put("number", number)
        }
        val insertedUri = context.contentResolver.insert(simUri, cv)
        if (insertedUri != null) {
            // Notify system of the change
            context.contentResolver.notifyChange(simUri, null)
            // Trigger a refresh for the contacts app
            val refreshIntent = Intent(Intent.ACTION_PROVIDER_CHANGED).apply {
                data = ContactsContract.Contacts.CONTENT_URI
            }
            context.sendBroadcast(refreshIntent)
            Log.d("SimContact", "Contact added successfully")
        } else {
            Log.e("SimContact", "Failed to insert contact to SIM")
        }
    } catch (e: Exception) {
        e.printStackTrace()
        Log.e("SimContact", "Error adding contact: ${e.message}")
    }
}
2. 代码执行成功但联系人未显示,重启后表现不一致的解决办法?

Your existing code is a solid starting point, but the inconsistent display usually stems from system caching, URI mismatches, or missing refresh triggers. Let’s break down the fixes:

Common Causes & Solutions:

  • Incorrect SIM URI: Some devices use non-standard URIs, and dual-SIM phones might require targeting a specific SIM. To fix this:

    • Use TelephonyManager to get active SIM subscription IDs and build the correct URI:
      val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
      val subscriptionInfos = telephonyManager.activeSubscriptionInfoList
      subscriptionInfos?.forEach { info ->
          val simUri = Uri.parse("content://icc/adn/subId/${info.subscriptionId}")
          // Try inserting to this SIM-specific URI
      }
      
    • Test content://sim/adn if the standard URI doesn’t work for your device.
  • System contact app caching: The default contacts app might not immediately pick up new SIM contacts. Your notifyChange call helps, but adding a broadcast ensures the app refreshes:

    val refreshIntent = Intent(Intent.ACTION_PROVIDER_CHANGED).apply {
        data = ContactsContract.Contacts.CONTENT_URI
        addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)
    }
    context.sendBroadcast(refreshIntent)
    
  • Unverified insertion success: No exception doesn’t mean the insert worked. Always check if insert() returns a non-null URI. If it’s null, the operation failed (maybe the SIM is full or unsupported).

  • SIM storage limits: SIM cards have fixed contact slots (usually 200-500). Check available space first:

    val cursor = context.contentResolver.query(simUri, null, null, null, null)
    val contactCount = cursor?.count ?: 0
    cursor?.close()
    if (contactCount >= 500) { // Adjust based on typical SIM limits
        Log.e("SimContact", "SIM is full")
        return
    }
    
  • Manufacturer-specific quirks: OEMs like Samsung or Xiaomi have custom contact sync logic. For these devices, add a short delay after insertion or trigger a manual sync (requires additional permissions).

Optimized Version of Your Code:

Here’s how to update your function with these fixes:

private fun addContactToSim(context: Context, number: String, name: String) {
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
        Log.e("SimContact", "WRITE_CONTACTS permission not granted")
        return
    }

    val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
    val subscriptionInfos = telephonyManager.activeSubscriptionInfoList

    // Try inserting to each available SIM
    subscriptionInfos?.forEach { info ->
        try {
            val simUri = Uri.parse("content://icc/adn/subId/${info.subscriptionId}")
            // Check SIM storage first
            val cursor = context.contentResolver.query(simUri, null, null, null, null)
            val contactCount = cursor?.count ?: 0
            cursor?.close()
            if (contactCount >= 500) {
                Log.e("SimContact", "SIM ${info.displayName} is full")
                return@forEach
            }

            val cv = ContentValues().apply {
                put("tag", name)
                put("number", number)
            }
            val insertedUri = context.contentResolver.insert(simUri, cv)
            if (insertedUri != null) {
                context.contentResolver.notifyChange(simUri, null)
                // Broadcast to refresh contacts app
                val refreshIntent = Intent(Intent.ACTION_PROVIDER_CHANGED).apply {
                    data = ContactsContract.Contacts.CONTENT_URI
                    addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND)
                }
                context.sendBroadcast(refreshIntent)
                Log.d("SimContact", "Contact added to SIM ${info.displayName}")
            } else {
                Log.e("SimContact", "Failed to insert to SIM ${info.displayName}")
            }
        } catch (e: Exception) {
            e.printStackTrace()
            Log.e("SimContact", "Error inserting to SIM ${info.displayName}: ${e.message}")
        }
    }

    // Fallback to default URI if no subscription info found
    if (subscriptionInfos.isNullOrEmpty()) {
        try {
            val simUri = Uri.parse("content://icc/adn")
            val cv = ContentValues().apply {
                put("tag", name)
                put("number", number)
            }
            val insertedUri = context.contentResolver.insert(simUri, cv)
            if (insertedUri != null) {
                context.contentResolver.notifyChange(simUri, null)
                val refreshIntent = Intent(Intent.ACTION_PROVIDER_CHANGED).apply {
                    data = ContactsContract.Contacts.CONTENT_URI
                }
                context.sendBroadcast(refreshIntent)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

内容的提问来源于stack exchange,提问作者MARSH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:40:16