Android端末のSIMカード内の情報にアクセスする方法をまとめておきます。
※追記2020年2月
どうやらAndroid10(API29)からREAD_PRIVILEGED_PHONE_STATEのパーミッションも必要らしい。
Android 10で、端末からIMEIなどのSIM情報を取得する方法
https://qiita.com/hiesiea/items/6a2deb479958a3b44707
詳細は、別途調査します。。。
以下は、それ以前の情報です。
必要パーミッション
READ_PHONE_STATE
確かAndroid M(6.0、API23)から必要になったはず。
ACCESS_NETWORK_STATE
simState(SIM状態)を取得するのに必要だった。
これは、エラーで怒られてから気づいた。
java.lang.SecurityException: ConnectivityService: Neither user 10214 nor current process has android.permission.ACCESS_NETWORK_STATE.
パーミッション許可の実装例
Kotlinで、targetSDKVersion 24以上を想定
今回のケースでは、READ_PHONE_STATEのみ。ACCESS_NETWORK_STATEはManifestに追加するのみでOK
TelephonyManagerの公式リファレンスにいろいろ書いてある。
AndroidManifest.xmlに以下を追加
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Ktファイル内に以下のように実装
private val PERMISSIONS_REQUEST_CODE = 100
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Logger.debug(javaClass.simpleName, "onCreate")
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
// 許可済みの処理
getDisplay()
} else {
// 許可されていないので許可ダイアログを表示する
requestPermissions(arrayOf(Manifest.permission.READ_PHONE_STATE), PERMISSIONS_REQUEST_CODE)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
when (requestCode) {
PERMISSIONS_REQUEST_CODE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//許可された場合の処理
getDisplay()
} else {
//拒否された場合の処理
})
}
}
}
}
TelephonyManagerのよく使いそうなgetメソッド
メソッド名 情報
getLine1Number 電話番号
getDeviceId デバイスID
getSimCountryIso SIMの国コード
getSimOperator MCC+MNC (mobile country code + mobile network code)
getSimOperatorName サービスプロバイダの名前
getSimSerialNumber SIMのシリアル番号
getSimState SIMの状態(通信可能か、PINロックされているかなど)
getVoiceMailNumber ボイスメールナンバー
- 公式リファレンス
android.telephony.TelephonyManager
もっといろいろとgetメソッドがある。getはあるけどsetはない。
例:電話番号を取得する場合は、以下のようにする
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
String line1Number = telephonyManager.getLine1Number();
なお、マニフェストにandroid.permission.READ_PHONE_STATE パーミッションの許可を記載する必要があります。
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
取得できる情報の意味について
名称 | 説明 | 格納先 | 例 |
---|---|---|---|
UDID | デバイス識別子 (Unique Device IDentifier) | デバイス | ffc1ded6f4570d557ad65f986684fc10c7f8d51f |
シリアル番号 | シリアル番号 | デバイス | 12345ABCDEF |
Wi-Fiアドレス | 無線LANデバイスのMACアドレス | デバイス | 00:12:08:23:7D:A2 |
ICCID | 携帯電話に付与される番号 | SIMカード | 1234 5678 1234 5678 123 |
IMEI | 携帯電話に付与される番号 | デバイス | 12 123456 123456 0 |
IMSI | 携帯電話ユーザーに付与される番号 | SIMカード | 12 123456 123456 0 |
ECID | デバイス識別に使われる16桁数値(16進) Exclusive Chip Identification | デバイス | 9999902578999 |
※例のうち、UDIDの値だけ表記上の理由により途中で改行入れています
ICCIDの取得方法について(リンクのコピペでないと見れない?)
ICCIDは,皆様ご指摘のとおり,SIM固有の番号です。
IMSはI (International Mobile Subscriber Identity)であり,ドコモなどの携帯事業者がSIMに割り当てた識別コードです。
したがってICCIDがIMSIを特定できれば,SIMを特定できます。携帯電話の通信では,IMSIが電話番号の代わりをします。
SIMがないと,電話番号がなくなることになるため,通信できなくなります。それ以外の識別コードとして,IMEIがあります。
IMEI(International Mobile Equipment Identifier)は,国際移動体装置識別番号(端末識別番号)であり端末に割り当てられた番号です。
これはSIMに割り当てられた番号ではないので,SIMがなくても取得できます。
余談ですが,欧州の規格であるGSMは,SIMがなくても警察などの緊急呼ができるようになっています。
SIMがない場合,IMSIがない(つまり電話番号を持っていない)ので,本来,通常通信できないのですが,緊急呼の場合は,IMSIがなければIMEIを使用することになっています。ICCIDやIMSIではSIMの識別ができ,IMEIを使用すると端末の識別ができます。
おまけ
android.telephony.TelephonyManagerクラスに,getSimSerialNumber()があります。
実機を持っていないので,これでICCIDの取得が可能であるかは確認しておりませんが,エミュレータでは使用できました。
使用するときには,READ_PHONE_STATEパーミッションが必要です。同様に,getDeviceId()でIMEIを取得できます。
コメント