Android API低于21版本获取SIM卡信息及短信SIM识别方案咨询
Hey there! I get your frustration—pre-API 21 Android versions don’t expose subscription_id through public TelephonyManager or SMSManager APIs, and scraping all SMS to find SIM info is unreliable and inefficient. Let’s dive into how apps like GO SMS handle this, plus practical implementation ideas for API 19.
How Apps Like GO SMS Do It
Most popular SMS apps rely on reflection to access hidden system APIs and vendor-specific database fields. Android’s underlying framework has SIM/slot identification logic even in API 19—it just isn’t exposed publicly. These apps tap into those hidden methods to get the data they need.
API 19-Specific Implementation Approaches
1. Reflect Hidden TelephonyManager Methods
API 19’s TelephonyManager has hidden methods to access multi-SIM info, even though public APIs don’t support it yet. Here’s a common approach:
- First, get the number of SIM slots using the hidden
getPhoneCount()method. - For each slot, fetch SIM identifiers like serial number or subscriber ID with slot-specific hidden methods.
Example code snippet:
TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); try { // Get total number of SIM slots Method getPhoneCountMethod = tm.getClass().getMethod("getPhoneCount"); int slotCount = (int) getPhoneCountMethod.invoke(tm); for (int slotId = 0; slotId < slotCount; slotId++) { // Fetch SIM serial number for the slot Method getSimSerialMethod = tm.getClass().getMethod("getSimSerialNumber", int.class); String simSerial = (String) getSimSerialMethod.invoke(tm, slotId); // Fetch subscriber ID (IMSI) for the slot Method getSubscriberIdMethod = tm.getClass().getMethod("getSubscriberId", int.class); String imsi = (String) getSubscriberIdMethod.invoke(tm, slotId); // Use these identifiers to track which SIM corresponds to which SMS } } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { // Handle exceptions (common on custom ROMs with modified methods) e.printStackTrace(); }
2. Extract Hidden Extras from SMS Broadcasts
When a new SMS arrives, the system sends a SMS_RECEIVED broadcast. Many devices (even API 19) include hidden extras in the intent that indicate the slot/SIM the SMS came from. Look for extras like "subscription", "slot", or "sim_id" (vendor-specific names vary).
Example of checking for these extras:
@Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_SMS_RECEIVED.equals(intent.getAction())) { // Check for hidden slot/subscription info int slotId = intent.getIntExtra("slot", -1); int subscriptionId = intent.getIntExtra("subscription", -1); if (slotId != -1) { // Use slotId to map to the corresponding SIM } } }
3. Query Vendor-Specific SMS Database Fields
The system SMS content provider (content://sms/) often includes non-standard fields added by device manufacturers. On many API 19 devices, you’ll find fields like sim_id or slot_id that directly link a SMS to its originating SIM.
Note: This is highly vendor-dependent—field names might differ across Samsung, Xiaomi, LG, etc. Test on target devices to confirm.
Key Caveats to Keep in Mind
- Compatibility: Hidden APIs and vendor fields can change between ROMs. Always add fallback logic (like defaulting to a single SIM assumption) if reflection/database queries fail.
- Permissions: You’ll need
READ_PHONE_STATEandREAD_SMSpermissions (no dynamic permissions needed in API 19—declare them in your manifest). - Privacy: Make sure your app clearly communicates why it needs access to SIM/SMS data, and comply with privacy regulations.
内容的提问来源于stack exchange,提问作者Mohsen Robatjazi

