Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

เข้าถึง Unique Device ID (IMEI) ใน Android


⚠️ สำคัญ: การเปลี่ยนแปลงนโยบาย Privacy (Android 10+)

ตั้งแต่ Android 10 (API 29) Google จำกัดการเข้าถึง Hardware Identifier (IMEI, Serial Number, MAC Address) อย่างเครดง เพื่อความเป็นส่วนตัว:

  • ต้องมี Permission READ_PRIVILEGED_PHONE_STATE (System App เท่านั้น)
  • App ธรรมดา ไม่สามารถอ่าน IMEI ได้แล้ว
  • ใช้ Alternatives แทน (ดูด้านล่าง)

รหัสตัวตนตัวเลือก (Alternatives)

IdentifierAPIความคงที่Permissionใช้ได้ Android 10+
SSAID (Android ID)Settings.Secure.ANDROID_IDต่ออุปกรณ์ (Reset เมื่อ Factory Reset)ไม่ต้อง Permission✅
Advertising ID (GAID)AdvertisingIdClientต่อ User (Reset ได้ใน Settings)com.google.android.gms.permission.AD_ID (Play Services)✅
Instance ID / Firebase Installation IDFirebaseInstallationsต่อ App Installไม่ต้อง Permission✅
UUID Random (App-specific)Generate เอง + เก็บ SharedPreferencesต่อ App Install (ลบ App = หาย)ไม่ต้อง Permission✅
IMEI/MEIDTelephonyManager.getImei()Hardware (ถาวร)READ_PRIVILEGED_PHONE_STATE❌ (App ธรรมดา)
Serial NumberBuild.getSerial()HardwareREAD_PRIVILEGED_PHONE_STATE❌

วิธีที่แนะนำ: ใช้ Android ID (SSAID)

import android.content.Context;
import android.provider.Settings.Secure;

public class DeviceIdHelper {
    public static String getAndroidId(Context context) {
        return Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
    }
}

// ใช้งาน
String androidId = DeviceIdHelper.getAndroidId(this);
// ผลลัพธ์: "a1b2c3d4e5f6g7h8" (64-bit hex string)
> ⚠️ **ข้อควรระวัง Android ID:** > - เปลี่ยนเมื่อ Factory Reset > - อาจซ้ำกันได้บนอุปกรณ์บางรุ่น (Bug รุ่นเก่า) > - ไม่ควรใช้เป็น Primary Key สำหรับ Server Auth เดียว

วิธีที่ 2: Advertising ID (GAID) - สำหรับ Ads/Analytics

// build.gradle
implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'

// ใช้งาน (ต้องรันบน Background Thread)
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import java.io.IOException;

public class AdIdHelper {
    public static void getAdvertisingId(Context context, OnAdIdListener listener) {
        new Thread(() -> {
            try {
                AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
                String adId = adInfo.getId();
                boolean limitAdTracking = adInfo.isLimitAdTrackingEnabled();
                listener.onAdIdReceived(adId, limitAdTracking);
            } catch (GooglePlayServicesNotAvailableException | 
                     GooglePlayServicesRepairableException | IOException e) {
                listener.onError(e);
            }
        }).start();
    }

    public interface OnAdIdListener {
        void onAdIdReceived(String adId, boolean limitAdTracking);
        void onError(Exception e);
    }
}

วิธีที่ 3: Firebase Installation ID (FID) - สำหรับ Firebase Apps

// build.gradle
implementation 'com.google.firebase:firebase-installations:17.2.0'

// ใช้งาน
FirebaseInstallations.getInstance().getId()
    .addOnCompleteListener(task -> {
        if (task.isSuccessful()) {
            String fid = task.getResult();
            // ใช้ FID เป็น Device/App Identifier
        }
    });

วิธีที่ 4: สร้าง UUID เอง (App-specific ID) - แนะนำที่สุดสำหรับ General Use

import android.content.Context;
import android.content.SharedPreferences;
import java.util.UUID;

public class AppDeviceId {
    private static final String PREFS_NAME = "device_id_prefs";
    private static final String KEY_DEVICE_ID = "device_id";

    public static String getDeviceId(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
        String deviceId = prefs.getString(KEY_DEVICE_ID, null);
        
        if (deviceId == null) {
            deviceId = UUID.randomUUID().toString();
            prefs.edit().putString(KEY_DEVICE_ID, deviceId).apply();
        }
        return deviceId;
    }

    public static void resetDeviceId(Context context) {
        context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            .edit().remove(KEY_DEVICE_ID).apply();
    }
}

Legacy Code: TelephonyManager (Android 9 และก่อน / System Apps)

เก็บไว้เพื่อ Maintenance Legacy Code เท่านั้น

Permission ใน Manifest



Java Code (Deprecated API)

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import androidx.core.app.ActivityCompat;

public class LegacyDeviceId {
    @SuppressLint("MissingPermission")
    public static String getImei(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        
        // Check Permission (Runtime Permission สำหรับ Android 6-9)
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) 
                != PackageManager.PERMISSION_GRANTED) {
            return null; // หรือ Request Permission
        }
        
        // API 26+ (Android 8.0+)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return telephonyManager.getImei(); // Slot 1
            // telephonyManager.getImei(0); // Slot 1
            // telephonyManager.getImei(1); // Slot 2 (Dual SIM)
        } else {
            // Deprecated ใน API 26
            return telephonyManager.getDeviceId();
        }
    }
}

Best Practices สำหรับ Device Identification

  1. ใช้ App-specific UUID สำหรับการระบุ User/Device ใน Backend ของตัวเอง (Simple, Reliable, Privacy-friendly)
  2. ใช้ Android ID (SSAID) สำหรับ Cross-app Identification (Anti-fraud, Analytics)
  3. ใช้ Advertising ID (GAID) สำหรับ Ads/Marketing เท่านั้น (User สามารถ Reset/Opt-out ได้)
  4. ใช้ Firebase Installation ID สำหรับ Firebase Ecosystem (FCM, Analytics, Crashlytics)
  5. ไม่ควร Hardcode IMEI/Serial ใน Logic ใหม่ (เข้าถึงไม่ได้ใน Android 10+)
  6. Respect User Privacy: ระบุใน Privacy Policy ว่าเก็บ Identifier อะไร

สรุป

Use CaseRecommended Identifier
User/Device ID สำหรับ Backend ของตัวเองApp-specific UUID (generate + store)
Cross-app Tracking / Fraud DetectionAndroid ID (SSAID)
Advertising / MarketingAdvertising ID (GAID)
Firebase Services (FCM, Analytics)Firebase Installation ID (FID)
Legacy System App (Carrier/OEM)IMEI (ต้อง Privileged Permission)