Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách lấy Device ID trên Android

Giới thiệu

Bài viết này hướng dẫn cách lấy Device ID (mã định danh thiết bị) trên Android thông qua TelephonyManager. Lưu ý: Kể từ Android 10 (API 29), việc truy cập các định danh phần cứng như IMEI/MEID bị hạn chế chặt chẽ do chính sách quyền riêng tư. Cách tiếp cận hiện đại nên sử dụng Instance ID, Advertising ID hoặc các phương án thay thế khác.

Các bước thực hiện

Bước 1: Tạo project mới

Mở Android Studio → File → New Project → Chọn "Empty Activity" → Điền thông tin cần thiết → Finish.

Bước 2: Thiết kế 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"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvDeviceId"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:padding="16dp"
        android:text="Device ID sẽ hiển thị ở đây" />

</LinearLayout>

Bước 3: Cấp quyền trong AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
    package="com.example.deviceid">

    <!-- Quyền cần thiết cho các phiên bản Android cũ -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.DeviceID">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Bước 4: Code logic (MainActivity.java / MainActivity.kt)

Java:

package com.example.deviceid;

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.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSION_REQUEST_CODE = 100;
    private TextView tvDeviceId;
    private TelephonyManager telephonyManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvDeviceId = findViewById(R.id.tvDeviceId);
        telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);

        checkPermissionAndGetDeviceId();
    }

    private void checkPermissionAndGetDeviceId() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.READ_PHONE_STATE},
                        PERMISSION_REQUEST_CODE);
            } else {
                getDeviceId();
            }
        } else {
            getDeviceId();
        }
    }

    private void getDeviceId() {
        String deviceId = "";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Android 10+ không cho phép truy cập IMEI/MEID trực tiếp
            deviceId = "Android 10+: Không thể truy cập IMEI/MEID. Hãy dùng Instance ID hoặc Advertising ID.";
        } else {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
                    == PackageManager.PERMISSION_GRANTED) {
                deviceId = telephonyManager.getDeviceId(); // IMEI/MEID
            }
        }
        tvDeviceId.setText("Device ID: " + deviceId);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getDeviceId();
            } else {
                Toast.makeText(this, "Cần cấp quyền READ_PHONE_STATE", Toast.LENGTH_SHORT).show();
                tvDeviceId.setText("Quyền bị từ chối");
            }
        }
    }
}

Kotlin (được khuyến nghị):

package com.example.deviceid

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 PERMISSION_REQUEST_CODE = 100
    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
        checkPermissionAndGetDeviceId()
    }

    private fun checkPermissionAndGetDeviceId() {
        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),
                    PERMISSION_REQUEST_CODE)
            } else {
                getDeviceId()
            }
        } else {
            getDeviceId()
        }
    }

    private fun getDeviceId() {
        val deviceId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            "Android 10+: Không thể truy cập IMEI/MEID. Dùng Instance ID hoặc Advertising ID."
        } else {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
                == PackageManager.PERMISSION_GRANTED) {
                telephonyManager.deviceId ?: "Không lấy được"
            } else "Chưa cấp quyền"
        }
        tvDeviceId.text = "Device ID: $deviceId"
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getDeviceId()
            } else {
                Toast.makeText(this, "Cần cấp quyền READ_PHONE_STATE", Toast.LENGTH_SHORT).show()
                tvDeviceId.text = "Quyền bị từ chối"
            }
        }
    }
}

Lưu ý quan trọng

  • Android 10 (API 29) trở lên: Google đã hạn chế truy cập IMEI, MEID, Serial Number. Các ứng dụng thông thường sẽ nhận được SecurityException hoặc giá trị null.
  • Giải pháp thay thế:
    • Instance ID (Firebase Installations): Định danh duy nhất cho mỗi cài đặt ứng dụng.
    • Advertising ID: Dùng cho quảng cáo, người dùng có thể reset.
    • Settings.Secure.ANDROID_ID: Định danh 64-bit, reset khi factory reset.
  • Quyền READ_PHONE_STATE: Là quyền nguy hiểm (dangerous), phải xin cấp quyền tại runtime từ Android 6.0 (API 23).

Chạy ứng dụng

Kết nối thiết bị thật (không dùng emulator vì emulator không có IMEI thật) → Nhấn Run → Cấp quyền khi được hỏi → Xem kết quả trên màn hình.