Giới thiệu
Bài viết này minh họa cách lấy số serial của thẻ SIM (ICCID) trên Android bằng TelephonyManager.getSimSerialNumber(). Tương tự như Device ID, từ Android 10 (API 29) quyền truy cập thông tin SIM bị hạn chế nghiêm ngặt.
Các bước thực hiện
Bước 1: Tạo project mới
Android Studio → File → New Project → Empty Activity → Điền thông tin → Finish.
Bước 2: Giao diện (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvSimSerial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SIM Serial Number"
android:textSize="18sp" />
</LinearLayout>
Bước 3: Khai báo quyền (AndroidManifest.xml)
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- Android 11+ cần quyền READ_PRIVILEGED_PHONE_STATE (chỉ system app) -->
Bước 4: Code xử lý (MainActivity.kt)
package com.example.simserial
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.telephony.TelephonyManager
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val REQUEST_CODE = 101
private lateinit var telephonyManager: TelephonyManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
checkPermission()
}
private fun checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
arrayOf(Manifest.permission.READ_PHONE_STATE), REQUEST_CODE)
} else {
showSimSerial()
}
} else {
showSimSerial()
}
}
private fun showSimSerial() {
var simSerial = ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10+: getSimSerialNumber() trả về null cho app thông thường
simSerial = "Android 10+: Cần quyền READ_PRIVILEGED_PHONE_STATE (chỉ system app)"
} else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
== PackageManager.PERMISSION_GRANTED) {
simSerial = telephonyManager.simSerialNumber ?: "Không có SIM hoặc không đọc được"
} else {
simSerial = "Chưa cấp quyền"
}
}
tvSimSerial.text = "SIM Serial: $simSerial"
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showSimSerial()
} else {
Toast.makeText(this, "Cần quyền READ_PHONE_STATE", Toast.LENGTH_SHORT).show()
}
}
}
}
Lưu ý quan trọng
- Android 10 (API 29):
getSimSerialNumber()trả về null cho ứng dụng thông thường. - Android 11 (API 30): Cần quyền
READ_PRIVILEGED_PHONE_STATE- chỉ ứng dụng hệ thống (system app) mới được cấp. - Thiết bị đa SIM: Dùng
TelephonyManager.createForSubscriptionId(subId)để lấy thông tin từng SIM slot. - Emulator: Thường không có SIM serial thật, cần test trên thiết bị thật.
Giải pháp thay thế
Nếu ứng dụng cần định danh người dùng/thiết bị, hãy xem xét:
- Firebase Installation ID (Instance ID)
- Advertising ID (Google Play Services)
- ANDROID_ID (
Settings.Secure.ANDROID_ID) - Tự sinh UUID và lưu trong SharedPreferences