Clean Architecture, Clean Life

仕事・個人での技術的なことつぶやきます

【Android】【Kotlin】コード上で機器のIMEIを取得する

経緯

今関わっているプロダクトで、トラックID的にIMEIを取得したいケースが出てきて調べたが、あまりまとまっていなかったので備忘録として

下準備

まずは権限が必要なので、マニフェストファイルに記載

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Activityに書く場合

普通にMainActivityに書く場合は簡単 onCreateあたりにこいつをぶち込む

val telephonyManager = this.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val imei = telephonyManager.imei

ただこれだけだと、パーミッションのチェックができてない!って怒られてしまいます

なんで、今回はパーミッションが許可された際のみ取得するように記載

if (ActivityCompat.checkSelfPermission(
            this,
            Manifest.permission.READ_PHONE_STATE
        ) == PackageManager.PERMISSION_GRANTED
        ) {
            val telephonyManager = this.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
            imei = telephonyManager.imei
        }

Fragmentに書く場合

このケースになるといきなり難易度が増します getSystemServiceを呼ぶにはContextが必要ですが、Fragmentからは直接呼ぶことができません

少し雑なやり方をすると、fragmentでは呼ばれたActivityを取ることができるので、それを使って

if (ActivityCompat.checkSelfPermission(
            activity!!,
            Manifest.permission.READ_PHONE_STATE
        ) == PackageManager.PERMISSION_GRANTED
        ) {
            val telephonyManager = activity!!.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
            imei = telephonyManager.imei
        }

と書くこともできる (調べるとgetActivity()がいっぱい出てきますが、今はactivityだけでいけるようです)

でも!!はあまり使いたくないですね もしかしたら予期してなかったところから呼ばれる可能性もあります

その場合はFragmentからApplicationContextを参照できるようにすればいいです

参照

qiita.com

こちらを使うことで、このように書くことができます

if (ActivityCompat.checkSelfPermission(
            ApplicationContext.instance,
            Manifest.permission.READ_PHONE_STATE
        ) == PackageManager.PERMISSION_GRANTED
        ) {
            val telephonyManager =
                ApplicationContext.instance.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
            NewRelic.setAttribute("IMEI", telephonyManager.imei)
        }

ApplicationContextは、上記のQiita記事を参考に自分で作ったクラスです

IMEI取るためだけにここまでやるのは面倒かもしれませんが、意外と便利なケースがあるので、後のことを考えておくならやっておくのもありかなと思います

Context周りは正直まで全然理解できていないので、頑張って理解していきたいと思います

ではまた~